From 10b054065bca9f21b6320d8c7d46c8041cb60cd4 Mon Sep 17 00:00:00 2001 From: Hugo Guerrero <1001939+hguerrero@users.noreply.github.com> Date: Sun, 19 Nov 2023 21:52:49 -0500 Subject: [PATCH 01/11] add import dialog --- client/src/App.tsx | 25 ++++---- client/src/components/ImportDialog.tsx | 80 ++++++++++++++++++++++++++ client/src/components/Services.tsx | 18 ++++-- client/src/components/Settings.tsx | 6 +- 4 files changed, 108 insertions(+), 21 deletions(-) create mode 100644 client/src/components/ImportDialog.tsx diff --git a/client/src/App.tsx b/client/src/App.tsx index 15acb88..e6b094c 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -import { createDockerDesktopClient } from '@docker/extension-api-client'; import React, { useEffect, useState } from 'react'; import DoneOutlinedIcon from '@mui/icons-material/DoneOutlined'; @@ -25,6 +24,7 @@ import SettingsIcon from '@mui/icons-material/Settings'; import Backdrop from '@mui/material/Backdrop'; import IconButton from '@mui/material/IconButton'; +import OpenInNewIcon from '@mui/icons-material/OpenInNew'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import Chip from '@mui/material/Chip'; @@ -35,8 +35,9 @@ import Paper from '@mui/material/Paper'; import Stack from '@mui/material/Stack'; import Tooltip from '@mui/material/Tooltip'; import Typography from '@mui/material/Typography'; -import OpenInNewIcon from '@mui/icons-material/OpenInNew'; +import { ExecStreamOptions } from '@docker/extension-api-client-types/dist/v1'; +import './App.css'; import { getExtensionConfig, getHome, @@ -48,25 +49,23 @@ import { getContainerInfo } from './api/containers'; import { sendMetric } from './api/metrics'; import { ensureNetworkExists } from './api/network'; import { ensureVolumeExists } from './api/volume'; -import './App.css'; +import AlertDialog from './components/AlertDialog'; +import ClipboardCopy from './components/ClipboardCopy'; import DeleteDialog from './components/DeleteDialog'; import Footer from './components/Footer'; -import Settings from './components/Settings'; +import ImportDialog from './components/ImportDialog'; +import Services from './components/Services'; +import SettingsDialog from './components/Settings'; import { ContainerStatus } from './types/ContainerStatus'; import { ExtensionConfig } from './types/ExtensionConfig'; import { APP_CONTAINER, ASYNC_MINION_CONTAINER, EXTENSION_NETWORK, - EXTENSION_VOLUME, KAFKA_CONTAINER, - POSTMAN_CONTAINER, + POSTMAN_CONTAINER } from './utils/constants'; -import Services from './components/Services'; import { useDockerDesktopClient } from './utils/ddclient'; -import { ExecStreamOptions } from '@docker/extension-api-client-types/dist/v1'; -import AlertDialog from './components/AlertDialog'; -import ClipboardCopy from './components/ClipboardCopy'; const isWindows = () => { const platform = useDockerDesktopClient().host.platform; @@ -725,7 +724,7 @@ const App = () => { setIsSettingsDialog(true); }; - const handleCloseSettings = async ( + const handleCloseSettingsDialog = async ( config: ExtensionConfig | undefined | null, ) => { setIsSettingsDialog(!isSettingsDialog); @@ -961,11 +960,11 @@ const App = () => { )} - void; +}> = ({ isDialogOpen, closeHandler }) => { + const [file, setFile] = useState(); + const [isSecondary, setIsSecondary] = useState(false); + + const handleClose = () => { + closeHandler(); + }; + + const handleInputChange = (event: React.ChangeEvent) => { + setFile(event.target.files?.[0]); + }; + + const handleCheckboxChange = (event: React.ChangeEvent) => { + setIsSecondary(event.target.checked); + }; + + return ( + closeHandler()} + fullWidth + > + Upload Artifact + + + + + } + label="This is a secondary artifact" + /> + + + + + + + + ); +}; + +export default ImportDialog; diff --git a/client/src/components/Services.tsx b/client/src/components/Services.tsx index 1d8c974..36e2f81 100644 --- a/client/src/components/Services.tsx +++ b/client/src/components/Services.tsx @@ -42,11 +42,12 @@ import MockURLRow from './MockURLRow'; import ServiceTypeLabel from './ServiceTypeLabel'; import { Operation, Service } from '../types/Service'; import ServiceRow from './ServiceRow'; +import UploadIcon from '@mui/icons-material/Upload'; +import ImportDialog from './ImportDialog'; -const Services = (props: { config: ExtensionConfig }) => { +const Services = ({config}: { config: ExtensionConfig }) => { const [services, setServices] = useState([]); - - const { config } = props; + const [isImportDialog, setIsImportDialog] = useState(false) const ddClient = useDockerDesktopClient(); @@ -71,12 +72,17 @@ const Services = (props: { config: ExtensionConfig }) => { retrieveServices(); }, []); + const handleOpenImport = () => {setIsImportDialog(true)}; + + const handleCloseImportDialog = () => {setIsImportDialog(false)}; + return ( + <> Services - @@ -97,6 +103,8 @@ const Services = (props: { config: ExtensionConfig }) => { + + ); }; diff --git a/client/src/components/Settings.tsx b/client/src/components/Settings.tsx index 3d4a9b2..3588b0b 100644 --- a/client/src/components/Settings.tsx +++ b/client/src/components/Settings.tsx @@ -37,13 +37,13 @@ type Props = { config: ExtensionConfig; isRunning?: boolean; isDialogOpen: boolean; - handleCloseDialog: (newConfig: ExtensionConfig | undefined | null) => void; + closeHandler: (newConfig: ExtensionConfig | undefined | null) => void; }; const Settings: React.FC = ({ isDialogOpen, isRunning = true, - handleCloseDialog, + closeHandler, config, }) => { const [{ portOffset, asyncEnabled, postmanEnabled, aicopilotEnabled, openAiApiKey }, setLocalConfig] = useState(config); @@ -63,7 +63,7 @@ const Settings: React.FC = ({ }; const handleClose = (newConfig: ExtensionConfig | undefined | null) => { - handleCloseDialog(newConfig); + closeHandler(newConfig); if (!newConfig) { setLocalConfig(config); } From 307699533cdb62877bc3716f55940353191cd76a Mon Sep 17 00:00:00 2001 From: Hugo Guerrero <1001939+hguerrero@users.noreply.github.com> Date: Sun, 19 Nov 2023 22:38:44 -0500 Subject: [PATCH 02/11] use functions --- client/src/api/metrics.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/api/metrics.ts b/client/src/api/metrics.ts index 1e79755..e957a00 100644 --- a/client/src/api/metrics.ts +++ b/client/src/api/metrics.ts @@ -20,7 +20,7 @@ import { createDockerDesktopClient } from '@docker/extension-api-client'; var clientID = ""; -function send(eventName: string, clientID: string, payload: Object) { +const send = (eventName: string, clientID: string, payload: Object) => { fetch(`https://microcks-dde-metrics-oafcwlgvlq-ew.a.run.app/collect`, { method: "POST", body: JSON.stringify({ @@ -36,7 +36,7 @@ function send(eventName: string, clientID: string, payload: Object) { }); } -export function sendMetric(eventName: string, payload: Object) { +export const sendMetric = (eventName: string, payload: Object) => { if (clientID !== "") { send(eventName, clientID, payload); } else { From e839142d52aa2d02256b329a6ba4e5747526f260 Mon Sep 17 00:00:00 2001 From: Hugo Guerrero <1001939+hguerrero@users.noreply.github.com> Date: Sun, 19 Nov 2023 22:38:54 -0500 Subject: [PATCH 03/11] fix imports --- client/src/components/Services.tsx | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/client/src/components/Services.tsx b/client/src/components/Services.tsx index 36e2f81..e0b9f15 100644 --- a/client/src/components/Services.tsx +++ b/client/src/components/Services.tsx @@ -16,34 +16,22 @@ * specific language governing permissions and limitations * under the License. */ -import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; -import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'; -import WarningAmberIcon from '@mui/icons-material/WarningAmber'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; -import Collapse from '@mui/material/Collapse'; -import IconButton from '@mui/material/IconButton'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; import Stack from '@mui/material/Stack'; import Table from '@mui/material/Table'; import TableBody from '@mui/material/TableBody'; -import TableCell from '@mui/material/TableCell'; import TableContainer from '@mui/material/TableContainer'; -import TableHead from '@mui/material/TableHead'; -import TableRow from '@mui/material/TableRow'; import Typography from '@mui/material/Typography'; -import React, { useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; import { APP_CONTAINER } from '../utils/constants'; import { useDockerDesktopClient } from '../utils/ddclient'; -import { ExtensionConfig } from '../types/ExtensionConfig'; -import MockURLRow from './MockURLRow'; -import ServiceTypeLabel from './ServiceTypeLabel'; -import { Operation, Service } from '../types/Service'; -import ServiceRow from './ServiceRow'; import UploadIcon from '@mui/icons-material/Upload'; +import { ExtensionConfig } from '../types/ExtensionConfig'; +import { Service } from '../types/Service'; import ImportDialog from './ImportDialog'; +import ServiceRow from './ServiceRow'; const Services = ({config}: { config: ExtensionConfig }) => { const [services, setServices] = useState([]); @@ -103,7 +91,7 @@ const Services = ({config}: { config: ExtensionConfig }) => { - + ); }; From 5366496afb48e89ba98587b06131dc63cf98094e Mon Sep 17 00:00:00 2001 From: Hugo Guerrero <1001939+hguerrero@users.noreply.github.com> Date: Sun, 19 Nov 2023 22:39:09 -0500 Subject: [PATCH 04/11] post file --- client/src/components/ImportDialog.tsx | 33 ++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/client/src/components/ImportDialog.tsx b/client/src/components/ImportDialog.tsx index fe85d88..0191043 100644 --- a/client/src/components/ImportDialog.tsx +++ b/client/src/components/ImportDialog.tsx @@ -9,20 +9,43 @@ import FormGroup from '@mui/material/FormGroup'; import FormControlLabel from '@mui/material/FormControlLabel'; import UploadIcon from '@mui/icons-material/Upload'; import React, { useState } from 'react'; +import { ExtensionConfig } from '../types/ExtensionConfig'; const ImportDialog: React.FC<{ isDialogOpen: boolean; + config: ExtensionConfig; closeHandler: () => void; -}> = ({ isDialogOpen, closeHandler }) => { - const [file, setFile] = useState(); +}> = ({ isDialogOpen, config, closeHandler }) => { + const [fileToUpload, setFileToUpload] = useState(); const [isSecondary, setIsSecondary] = useState(false); + const uploadFile = async (event: React.MouseEvent) => { + try { + const formData = new FormData(); + formData.append('file', fileToUpload as File); + + const result = await fetch( + `http://localhost:${ + 8080 + config.portOffset || 8080 + }/api/artifact/upload`, + { + method: 'POST', + body: formData, + }, + ); + + if (result.ok) { + closeHandler() + } + } catch (error) {} + }; + const handleClose = () => { closeHandler(); }; const handleInputChange = (event: React.ChangeEvent) => { - setFile(event.target.files?.[0]); + setFileToUpload(event.target.files?.[0]); }; const handleCheckboxChange = (event: React.ChangeEvent) => { @@ -67,8 +90,8 @@ const ImportDialog: React.FC<{ variant="contained" color="primary" size="large" - onClick={(event) => {}} - disabled={file === undefined} + onClick={uploadFile} + disabled={fileToUpload === undefined} > Import From f4c3e22a48f185d649d1f9d0511dd44e069d1690 Mon Sep 17 00:00:00 2001 From: Hugo Guerrero <1001939+hguerrero@users.noreply.github.com> Date: Sun, 19 Nov 2023 22:43:49 -0500 Subject: [PATCH 05/11] refresh after successful import --- client/src/components/ImportDialog.tsx | 4 +- client/src/components/Services.tsx | 72 +++++++++++++++----------- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/client/src/components/ImportDialog.tsx b/client/src/components/ImportDialog.tsx index 0191043..9798965 100644 --- a/client/src/components/ImportDialog.tsx +++ b/client/src/components/ImportDialog.tsx @@ -14,7 +14,7 @@ import { ExtensionConfig } from '../types/ExtensionConfig'; const ImportDialog: React.FC<{ isDialogOpen: boolean; config: ExtensionConfig; - closeHandler: () => void; + closeHandler: (refresh?:boolean) => void; }> = ({ isDialogOpen, config, closeHandler }) => { const [fileToUpload, setFileToUpload] = useState(); const [isSecondary, setIsSecondary] = useState(false); @@ -35,7 +35,7 @@ const ImportDialog: React.FC<{ ); if (result.ok) { - closeHandler() + closeHandler(true) } } catch (error) {} }; diff --git a/client/src/components/Services.tsx b/client/src/components/Services.tsx index e0b9f15..75dd146 100644 --- a/client/src/components/Services.tsx +++ b/client/src/components/Services.tsx @@ -33,9 +33,9 @@ import { Service } from '../types/Service'; import ImportDialog from './ImportDialog'; import ServiceRow from './ServiceRow'; -const Services = ({config}: { config: ExtensionConfig }) => { +const Services = ({ config }: { config: ExtensionConfig }) => { const [services, setServices] = useState([]); - const [isImportDialog, setIsImportDialog] = useState(false) + const [isImportDialog, setIsImportDialog] = useState(false); const ddClient = useDockerDesktopClient(); @@ -60,38 +60,52 @@ const Services = ({config}: { config: ExtensionConfig }) => { retrieveServices(); }, []); - const handleOpenImport = () => {setIsImportDialog(true)}; + const handleOpenImport = () => { + setIsImportDialog(true); + }; - const handleCloseImportDialog = () => {setIsImportDialog(false)}; + const handleCloseImportDialog = (refresh?: boolean) => { + if (refresh) retrieveServices(); + setIsImportDialog(false); + }; return ( <> - - - Services - - - - - - - - {services.map((service) => ( - - ))} - -
-
-
+ + + Services + + + + + + + + {services.map((service) => ( + + ))} + +
+
+
+
-
- + ); }; From 619d2507cb30c8feb7bdadb1e93a10ce4f8f49bc Mon Sep 17 00:00:00 2001 From: Hugo Guerrero <1001939+hguerrero@users.noreply.github.com> Date: Thu, 23 Nov 2023 00:05:50 -0500 Subject: [PATCH 06/11] import services with secondary artifacts --- client/src/components/ImportDialog.tsx | 16 ++- client/src/components/ServiceRow.tsx | 157 +++++++++++++++++-------- client/src/components/Services.tsx | 32 ++--- client/src/types/Service.ts | 18 ++- 4 files changed, 153 insertions(+), 70 deletions(-) diff --git a/client/src/components/ImportDialog.tsx b/client/src/components/ImportDialog.tsx index 9798965..a9ace6f 100644 --- a/client/src/components/ImportDialog.tsx +++ b/client/src/components/ImportDialog.tsx @@ -10,6 +10,7 @@ import FormControlLabel from '@mui/material/FormControlLabel'; import UploadIcon from '@mui/icons-material/Upload'; import React, { useState } from 'react'; import { ExtensionConfig } from '../types/ExtensionConfig'; +import { throwErrorAsString } from '../api/utils'; const ImportDialog: React.FC<{ isDialogOpen: boolean; @@ -23,8 +24,9 @@ const ImportDialog: React.FC<{ try { const formData = new FormData(); formData.append('file', fileToUpload as File); + formData.append('mainArtifact', isSecondary ? "false" : "true"); - const result = await fetch( + const response = await fetch( `http://localhost:${ 8080 + config.portOffset || 8080 }/api/artifact/upload`, @@ -34,10 +36,16 @@ const ImportDialog: React.FC<{ }, ); - if (result.ok) { - closeHandler(true) + if (!response.ok) { + console.error(response.statusText); + return; } - } catch (error) {} + + closeHandler(true) + + } catch (error) { + throwErrorAsString(error); + } }; const handleClose = () => { diff --git a/client/src/components/ServiceRow.tsx b/client/src/components/ServiceRow.tsx index 8b97d9d..8e9cbb5 100644 --- a/client/src/components/ServiceRow.tsx +++ b/client/src/components/ServiceRow.tsx @@ -16,47 +16,56 @@ import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; import Typography from '@mui/material/Typography'; -import { Operation, Service } from '../types/Service'; +import { + MessagesMap, + Operation, + ReqRespPair, + Service, + UnidirEvent, +} from '../types/Service'; import ServiceTypeLabel from './ServiceTypeLabel'; import { useDockerDesktopClient } from '../utils/ddclient'; import MockURLRow from './MockURLRow'; import { ExtensionConfig } from '../types/ExtensionConfig'; import { APP_CONTAINER } from '../utils/constants'; +import { throwErrorAsString } from '../api/utils'; const ServiceRow = (props: { service: Service; config: ExtensionConfig }) => { const [open, setOpen] = React.useState(false); - const [messagesMap, setMessagesMap] = useState<{[key: string]: []}>() + const [messagesMap, setMessagesMap] = useState(); const ddClient = useDockerDesktopClient(); const { service, config } = props; const retrieveServiceDetail = async () => { - const result = await ddClient.docker.cli.exec('exec', [ - APP_CONTAINER, - '/bin/curl', - '-s', - '-S', - `localhost:8080/api/services/${service.id}`, - ]); - if (result?.stderr) { - console.error(result.stderr); - return; + try { + const response = await fetch( + `http://localhost:${8080 + config.portOffset || 8080}/api/services/${ + service.id + }`, + ); + + if (!response.ok) { + console.error(response.statusText); + return; + } + + const svc = (await response.json()) as Service; + console.log(svc); + setMessagesMap(svc.messagesMap); + } catch (error) { + throwErrorAsString(error); } - const svc = result?.parseJsonObject() as Service; - console.log(svc); - setMessagesMap(svc.messagesMap); }; - const formatDestinationName = ( - operation: Operation, - ): string => { + const formatDestinationName = (operation: Operation): string => { const name = service.name.replace(/\s/g, '').replace(/-/g, '') + '-' + service.version + '-' + - operation.name.replace(operation.method + " ", '').replace(/\//g, '-'); + operation.name.replace(operation.method + ' ', '').replace(/\//g, '-'); return name; }; @@ -66,7 +75,7 @@ const ServiceRow = (props: { service: Service; config: ExtensionConfig }) => { const formatMockUrl = ( operation: Operation, - dispatchCriteria?: string, + dispatchCriteria?: string | null, ): string => { var result = `http://localhost:${8080 + config.portOffset}`; @@ -74,29 +83,40 @@ const ServiceRow = (props: { service: Service; config: ExtensionConfig }) => { result += '/rest/'; result += encodeUrl(service.name) + '/' + service.version; - var parts:{[key: string]: string} = {}; + var parts: { [key: string]: string } = {}; var params = {}; var operationName = operation.name; - + if (dispatchCriteria != null) { - var partsCriteria = (dispatchCriteria.indexOf('?') == -1 ? dispatchCriteria : dispatchCriteria.substring(0, dispatchCriteria.indexOf('?'))); - var paramsCriteria = (dispatchCriteria.indexOf('?') == -1 ? null : dispatchCriteria.substring(dispatchCriteria.indexOf('?') + 1)); + var partsCriteria = + dispatchCriteria.indexOf('?') == -1 + ? dispatchCriteria + : dispatchCriteria.substring(0, dispatchCriteria.indexOf('?')); + var paramsCriteria = + dispatchCriteria.indexOf('?') == -1 + ? null + : dispatchCriteria.substring(dispatchCriteria.indexOf('?') + 1); partsCriteria = encodeUrl(partsCriteria); partsCriteria.split('/').forEach((element, index, array) => { - if (element){ + if (element) { parts[element.split('=')[0]] = element.split('=')[1]; } }); - - operationName = operationName.replace(/{([a-zA-Z0-9-_]+)}/g, (match, p1, string) => { - return parts[p1]; - }); + operationName = operationName.replace( + /{([a-zA-Z0-9-_]+)}/g, + (match, p1, string) => { + return parts[p1]; + }, + ); // Support also Postman syntax with /:part - operationName = operationName.replace(/:([a-zA-Z0-9-_]+)/g, (match, p1, string) => { - return parts[p1]; - }); + operationName = operationName.replace( + /:([a-zA-Z0-9-_]+)/g, + (match, p1, string) => { + return parts[p1]; + }, + ); if (paramsCriteria != null) { operationName += '?' + paramsCriteria.replace(/\?/g, '&'); } @@ -111,7 +131,7 @@ const ServiceRow = (props: { service: Service; config: ExtensionConfig }) => { } else if (service.type === 'GENERIC_REST') { result += '/dynarest/'; result += encodeUrl(service.name) + '/' + service.version; - result += operation.name.replace(operation.method + " ", ''); + result += operation.name.replace(operation.method + ' ', ''); } else if (service.type === 'GRPC') { result = `http://localhost:${9090 + config.portOffset}`; } else if (service.type === 'EVENT') { @@ -228,24 +248,59 @@ const ServiceRow = (props: { service: Service; config: ExtensionConfig }) => {
) : messagesMap ? ( - - {messagesMap[operation.name].map( - (value: any, index) => ( - - - - ), - )} - + messagesMap[operation.name].length ? ( + + {messagesMap[operation.name].map( + (value: ReqRespPair | UnidirEvent, index) => + value.type === 'reqRespPair' ? ( + + + + ) : value.type === 'unidirEvent' && + index === 0 ? ( + + + + ) : ( + <> + ), + )} + + ) : ( + + + + There are no examples to mock for this + operation + + + ) ) : ( )} diff --git a/client/src/components/Services.tsx b/client/src/components/Services.tsx index 75dd146..b02ae9b 100644 --- a/client/src/components/Services.tsx +++ b/client/src/components/Services.tsx @@ -24,10 +24,10 @@ import TableBody from '@mui/material/TableBody'; import TableContainer from '@mui/material/TableContainer'; import Typography from '@mui/material/Typography'; import { useEffect, useState } from 'react'; -import { APP_CONTAINER } from '../utils/constants'; import { useDockerDesktopClient } from '../utils/ddclient'; import UploadIcon from '@mui/icons-material/Upload'; +import { throwErrorAsString } from '../api/utils'; import { ExtensionConfig } from '../types/ExtensionConfig'; import { Service } from '../types/Service'; import ImportDialog from './ImportDialog'; @@ -40,20 +40,24 @@ const Services = ({ config }: { config: ExtensionConfig }) => { const ddClient = useDockerDesktopClient(); const retrieveServices = async () => { - const result = await ddClient.docker.cli.exec('exec', [ - APP_CONTAINER, - '/bin/curl', - '-s', - '-S', - 'localhost:8080/api/services', - ]); - if (result?.stderr) { - console.error(result.stderr); - return; + try { + const response = await fetch( + `http://localhost:${ + 8080 + config.portOffset || 8080 + }/api/services` + ); + + if (!response.ok) { + console.error(response.statusText); + return; + } + + const svcs = await response.json() as Service[]; + console.log(svcs); + setServices(svcs); + } catch (error) { + throwErrorAsString(error); } - const svcs = result?.parseJsonObject() as Service[]; - console.log(svcs); - setServices(svcs); }; useEffect(() => { diff --git a/client/src/types/Service.ts b/client/src/types/Service.ts index ff80c49..2d0f466 100644 --- a/client/src/types/Service.ts +++ b/client/src/types/Service.ts @@ -13,7 +13,7 @@ export type Service = { version: string; type: ServiceType; operations: Operation[]; - messagesMap: any; + messagesMap: MessagesMap; }; export type Operation = { @@ -24,3 +24,19 @@ export type Operation = { dispatcherRules: string; resourcePaths: string[]; }; + +export type BaseMessagesMap = { + type: "reqRespPair" | "unidirEvent" +} + +export type ReqRespPair = { + request: any; + response: any; +} & BaseMessagesMap + +export type UnidirEvent = { + eventMessage: any +} & BaseMessagesMap + +export type MessagesMap = { + [key: string]: ReqRespPair[] | UnidirEvent[] }; From 07f7a21799ba300900c6512b22ec87783c658315 Mon Sep 17 00:00:00 2001 From: Hugo Guerrero <1001939+hguerrero@users.noreply.github.com> Date: Thu, 23 Nov 2023 12:17:32 -0500 Subject: [PATCH 07/11] use custom latest tag for extension --- client/src/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/App.tsx b/client/src/App.tsx index e6b094c..662ba94 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -296,7 +296,7 @@ const App = () => { `${9090 + config.portOffset}:9090`, '--label', 'com.docker.compose.project=microcks_microcks-docker-desktop-extension-desktop-extension', - 'quay.io/microcks/microcks-uber:latest', + 'quay.io/microcks/microcks-uber:latest-extension', ]; if (!appStatus.exists) { console.log('Creating ', APP_CONTAINER); From efc4bb9a4fdc9cb7ea2a3adf1b0c66305ce9475a Mon Sep 17 00:00:00 2001 From: Hugo Guerrero <1001939+hguerrero@users.noreply.github.com> Date: Thu, 23 Nov 2023 13:03:04 -0500 Subject: [PATCH 08/11] use only one mock url for graphql --- client/src/components/ServiceRow.tsx | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/client/src/components/ServiceRow.tsx b/client/src/components/ServiceRow.tsx index 8e9cbb5..db419e3 100644 --- a/client/src/components/ServiceRow.tsx +++ b/client/src/components/ServiceRow.tsx @@ -253,19 +253,22 @@ const ServiceRow = (props: { service: Service; config: ExtensionConfig }) => { {messagesMap[operation.name].map( (value: ReqRespPair | UnidirEvent, index) => value.type === 'reqRespPair' ? ( - - - + (!service.type.includes('GRAPHQL') || + index === 0) && ( + + + + ) ) : value.type === 'unidirEvent' && index === 0 ? ( From 782df1ab50dcbd23d35a72f43f8bc115251fb596 Mon Sep 17 00:00:00 2001 From: Hugo Guerrero <1001939+hguerrero@users.noreply.github.com> Date: Sat, 20 Jan 2024 18:00:10 -0500 Subject: [PATCH 09/11] render correctly gRPC --- client/src/components/ServiceRow.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/src/components/ServiceRow.tsx b/client/src/components/ServiceRow.tsx index db419e3..84069b1 100644 --- a/client/src/components/ServiceRow.tsx +++ b/client/src/components/ServiceRow.tsx @@ -1,4 +1,3 @@ -import React, { useState } from 'react'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'; import WarningAmberIcon from '@mui/icons-material/WarningAmber'; @@ -8,7 +7,6 @@ import Collapse from '@mui/material/Collapse'; import IconButton from '@mui/material/IconButton'; import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; -import Stack from '@mui/material/Stack'; import Table from '@mui/material/Table'; import TableBody from '@mui/material/TableBody'; import TableCell from '@mui/material/TableCell'; @@ -16,6 +14,9 @@ import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; import Typography from '@mui/material/Typography'; +import React, { useState } from 'react'; +import { throwErrorAsString } from '../api/utils'; +import { ExtensionConfig } from '../types/ExtensionConfig'; import { MessagesMap, Operation, @@ -23,12 +24,9 @@ import { Service, UnidirEvent, } from '../types/Service'; -import ServiceTypeLabel from './ServiceTypeLabel'; import { useDockerDesktopClient } from '../utils/ddclient'; import MockURLRow from './MockURLRow'; -import { ExtensionConfig } from '../types/ExtensionConfig'; -import { APP_CONTAINER } from '../utils/constants'; -import { throwErrorAsString } from '../api/utils'; +import ServiceTypeLabel from './ServiceTypeLabel'; const ServiceRow = (props: { service: Service; config: ExtensionConfig }) => { const [open, setOpen] = React.useState(false); @@ -38,6 +36,8 @@ const ServiceRow = (props: { service: Service; config: ExtensionConfig }) => { const { service, config } = props; + const singleRowTypes = ['GRAPHQL', 'GRPC'] + const retrieveServiceDetail = async () => { try { const response = await fetch( @@ -253,7 +253,7 @@ const ServiceRow = (props: { service: Service; config: ExtensionConfig }) => { {messagesMap[operation.name].map( (value: ReqRespPair | UnidirEvent, index) => value.type === 'reqRespPair' ? ( - (!service.type.includes('GRAPHQL') || + (!singleRowTypes.includes(service.type) || index === 0) && ( Date: Sat, 20 Jan 2024 18:00:41 -0500 Subject: [PATCH 10/11] Show message for unsupported bindings --- client/src/components/MockURLRow.tsx | 65 +++++++++++++++++++--------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/client/src/components/MockURLRow.tsx b/client/src/components/MockURLRow.tsx index 701fd51..131e435 100644 --- a/client/src/components/MockURLRow.tsx +++ b/client/src/components/MockURLRow.tsx @@ -1,11 +1,12 @@ import LaunchIcon from '@mui/icons-material/Launch'; +import WarningAmberIcon from '@mui/icons-material/WarningAmber'; +import Box from '@mui/material/Box'; import IconButton from '@mui/material/IconButton'; import Link from '@mui/material/Link'; import Typography from '@mui/material/Typography'; import React from 'react'; import { useDockerDesktopClient } from '../utils/ddclient'; import ClipboardCopy from './ClipboardCopy'; -import { Box } from '@mui/material'; interface MockURLRowProps { bindings?: any; @@ -21,26 +22,48 @@ const MockURLRow: React.FC = ({ const ddClient = useDockerDesktopClient(); return bindings ? ( - - {Object.keys(bindings).map((binding: any) => ( - <> - - {bindings[binding].type} endpoint:{' '} - - {mockURL} - - - - - {bindings[binding].type} destination:{' '} - - {destination} - - - - - ))} - + <> + {Object.keys(bindings).map((binding: any) => + binding == 'KAFKA' ? ( + + + {bindings[binding].type} endpoint:{' '} + + {mockURL} + + + + + {bindings[binding].type} destination:{' '} + + {destination} + + + + + ) : ( + + + + This extension does not support the {binding} binding at this time. + + + ), + )} + ) : ( Date: Sat, 20 Jan 2024 18:19:21 -0500 Subject: [PATCH 11/11] reset dialog --- client/src/components/ImportDialog.tsx | 31 +++++++++++++------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/client/src/components/ImportDialog.tsx b/client/src/components/ImportDialog.tsx index a9ace6f..6dc4cf8 100644 --- a/client/src/components/ImportDialog.tsx +++ b/client/src/components/ImportDialog.tsx @@ -1,21 +1,21 @@ -import Dialog from '@mui/material/Dialog'; -import DialogTitle from '@mui/material/DialogTitle'; -import DialogContent from '@mui/material/DialogContent'; -import DialogActions from '@mui/material/DialogActions'; +import UploadIcon from '@mui/icons-material/Upload'; import Button from '@mui/material/Button'; -import TextField from '@mui/material/TextField'; import Checkbox from '@mui/material/Checkbox'; -import FormGroup from '@mui/material/FormGroup'; +import Dialog from '@mui/material/Dialog'; +import DialogActions from '@mui/material/DialogActions'; +import DialogContent from '@mui/material/DialogContent'; +import DialogTitle from '@mui/material/DialogTitle'; import FormControlLabel from '@mui/material/FormControlLabel'; -import UploadIcon from '@mui/icons-material/Upload'; +import FormGroup from '@mui/material/FormGroup'; +import TextField from '@mui/material/TextField'; import React, { useState } from 'react'; -import { ExtensionConfig } from '../types/ExtensionConfig'; import { throwErrorAsString } from '../api/utils'; +import { ExtensionConfig } from '../types/ExtensionConfig'; const ImportDialog: React.FC<{ isDialogOpen: boolean; config: ExtensionConfig; - closeHandler: (refresh?:boolean) => void; + closeHandler: (refresh?: boolean) => void; }> = ({ isDialogOpen, config, closeHandler }) => { const [fileToUpload, setFileToUpload] = useState(); const [isSecondary, setIsSecondary] = useState(false); @@ -24,7 +24,7 @@ const ImportDialog: React.FC<{ try { const formData = new FormData(); formData.append('file', fileToUpload as File); - formData.append('mainArtifact', isSecondary ? "false" : "true"); + formData.append('mainArtifact', isSecondary ? 'false' : 'true'); const response = await fetch( `http://localhost:${ @@ -41,15 +41,16 @@ const ImportDialog: React.FC<{ return; } - closeHandler(true) - + handleClose(true); } catch (error) { throwErrorAsString(error); } }; - const handleClose = () => { - closeHandler(); + const handleClose = (refresh?: boolean) => { + setFileToUpload(undefined); + setIsSecondary(false); + closeHandler(refresh); }; const handleInputChange = (event: React.ChangeEvent) => { @@ -63,7 +64,7 @@ const ImportDialog: React.FC<{ return ( closeHandler()} + onClose={(event, reason) => handleClose()} fullWidth > Upload Artifact