feat: add app connections w/ testing and deleting functions
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { Link } from 'react-router-dom';
|
||||
import DialogTitle from '@mui/material/DialogTitle';
|
||||
|
@@ -0,0 +1,57 @@
|
||||
import * as React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import type { PopoverProps } from '@mui/material/Popover';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
|
||||
import * as URLS from 'config/urls';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
|
||||
type Action = {
|
||||
type: 'test' | 'reconnect' | 'delete' | 'viewFlows';
|
||||
};
|
||||
|
||||
type ContextMenuProps = {
|
||||
appKey: string;
|
||||
onClose: () => void;
|
||||
onMenuItemClick: (event: React.MouseEvent, action: Action) => void;
|
||||
anchorEl: PopoverProps['anchorEl'];
|
||||
};
|
||||
|
||||
export default function ContextMenu(props: ContextMenuProps) {
|
||||
const { appKey, onClose, onMenuItemClick, anchorEl } = props;
|
||||
const formatMessage = useFormatMessage();
|
||||
|
||||
const createActionHandler = React.useCallback((action: Action) => {
|
||||
return function clickHandler(event: React.MouseEvent) {
|
||||
onMenuItemClick(event, action);
|
||||
|
||||
onClose();
|
||||
};
|
||||
}, [onMenuItemClick, onClose]);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
open={true}
|
||||
onClose={onClose}
|
||||
hideBackdrop={false}
|
||||
anchorEl={anchorEl}
|
||||
>
|
||||
<MenuItem component={Link} to={URLS.APP_FLOWS(appKey)} onClick={createActionHandler({ type: 'viewFlows' })}>
|
||||
{formatMessage('connection.viewFlows')}
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem onClick={createActionHandler({ type: 'test' })}>
|
||||
{formatMessage('connection.testConnection')}
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem onClick={createActionHandler({ type: 'reconnect' })}>
|
||||
{formatMessage('connection.reconnect')}
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem onClick={createActionHandler({ type: 'delete' })}>
|
||||
{formatMessage('connection.delete')}
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
);
|
||||
};
|
94
packages/web/src/components/AppConnectionRow/index.tsx
Normal file
94
packages/web/src/components/AppConnectionRow/index.tsx
Normal file
@@ -0,0 +1,94 @@
|
||||
import * as React from 'react';
|
||||
import { useLazyQuery, useMutation } from '@apollo/client';
|
||||
import Card from '@mui/material/Card';
|
||||
import Box from '@mui/material/Box';
|
||||
import CardActionArea from '@mui/material/CardActionArea';
|
||||
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
|
||||
|
||||
import { DELETE_CONNECTION } from 'graphql/mutations/delete-connection';
|
||||
import { TEST_CONNECTION } from 'graphql/queries/test-connection';
|
||||
import ConnectionContextMenu from 'components/AppConnectionContextMenu';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
import type { Connection } from 'types/connection';
|
||||
import { CardContent, Typography } from './style';
|
||||
|
||||
type AppConnectionRowProps = {
|
||||
connection: Connection;
|
||||
}
|
||||
|
||||
const countTranslation = (value: React.ReactNode) => (<><strong>{value}</strong><br /></>);
|
||||
|
||||
function AppConnectionRow(props: AppConnectionRowProps) {
|
||||
const [testConnection, { data: testData, called: testCalled, loading: testLoading }] = useLazyQuery(TEST_CONNECTION);
|
||||
const [deleteConnection] = useMutation(DELETE_CONNECTION);
|
||||
|
||||
const formatMessage = useFormatMessage();
|
||||
const { id, key, data } = props.connection;
|
||||
|
||||
const contextButtonRef = React.useRef<SVGSVGElement | null>(null);
|
||||
const [anchorEl, setAnchorEl] = React.useState<SVGSVGElement | null>(null);
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const onContextMenuClick = (event: React.MouseEvent<HTMLButtonElement>) => setAnchorEl(contextButtonRef.current);
|
||||
const onContextMenuAction = React.useCallback((event, action: { [key: string]: string }) => {
|
||||
if (action.type === 'delete') {
|
||||
deleteConnection({
|
||||
variables: { id },
|
||||
update: (cache, mutationResult) => {
|
||||
const connectionCacheId = cache.identify({
|
||||
__typename: 'connection',
|
||||
id,
|
||||
});
|
||||
|
||||
cache.evict({
|
||||
id: connectionCacheId,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (action.type === 'test') {
|
||||
testConnection({ variables: { id } });
|
||||
}
|
||||
}, [deleteConnection, id, testConnection]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card sx={{ my: 2 }}>
|
||||
<CardActionArea onClick={onContextMenuClick}>
|
||||
<CardContent>
|
||||
<Box>
|
||||
<Typography variant="h6">
|
||||
{data.screenName}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
{testCalled && !testLoading && (testData ? 'yes' : 'no')}
|
||||
</Box>
|
||||
|
||||
<Box sx={{ px: 2 }}>
|
||||
<Typography variant="body2">
|
||||
{formatMessage('connection.flowCount', { count: countTranslation(0) })}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<MoreHorizIcon ref={contextButtonRef} />
|
||||
</Box>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
|
||||
{anchorEl && <ConnectionContextMenu
|
||||
appKey={key}
|
||||
onClose={handleClose}
|
||||
onMenuItemClick={onContextMenuAction}
|
||||
anchorEl={anchorEl}
|
||||
/>}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default AppConnectionRow;
|
17
packages/web/src/components/AppConnectionRow/style.ts
Normal file
17
packages/web/src/components/AppConnectionRow/style.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { styled } from '@mui/material/styles';
|
||||
import MuiCardContent from '@mui/material/CardContent';
|
||||
import MuiTypography from '@mui/material/Typography';
|
||||
|
||||
export const CardContent = styled(MuiCardContent)(({ theme }) => ({
|
||||
display: 'grid',
|
||||
gridTemplateRows: 'auto',
|
||||
gridTemplateColumns: '1fr auto auto auto',
|
||||
gridColumnGap: theme.spacing(2),
|
||||
alignItems: 'center',
|
||||
}));
|
||||
|
||||
|
||||
export const Typography = styled(MuiTypography)(({ theme }) => ({
|
||||
textAlign: 'center',
|
||||
display: 'inline-block',
|
||||
}));
|
23
packages/web/src/components/AppConnections/index.tsx
Normal file
23
packages/web/src/components/AppConnections/index.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { GET_APP_CONNECTIONS } from 'graphql/queries/get-app-connections';
|
||||
|
||||
import AppConnectionRow from 'components/AppConnectionRow';
|
||||
import type { Connection } from 'types/connection';
|
||||
|
||||
type AppConnectionsProps = {
|
||||
appKey: String;
|
||||
}
|
||||
|
||||
export default function AppConnections(props: AppConnectionsProps) {
|
||||
const { appKey: key } = props;
|
||||
const { data } = useQuery(GET_APP_CONNECTIONS, { variables: { key } });
|
||||
const appConnections: Connection[] = data?.getApp?.connections || [];
|
||||
|
||||
return (
|
||||
<>
|
||||
{appConnections.map((appConnection: Connection) => (
|
||||
<AppConnectionRow key={appConnection.id} connection={appConnection} />
|
||||
))}
|
||||
</>
|
||||
)
|
||||
};
|
@@ -24,7 +24,7 @@ function AppRow(props: AppRowProps) {
|
||||
<Link to={URLS.APP(name.toLowerCase())}>
|
||||
<Card sx={{ my: 2 }}>
|
||||
<CardActionArea>
|
||||
<CardContent>
|
||||
<CardContent>
|
||||
<Box>
|
||||
<AppIcon name={name} url={iconUrl} color={primaryColor} />
|
||||
</Box>
|
||||
|
@@ -19,12 +19,10 @@ export default function InputCreator(props: InputCreatorProps) {
|
||||
const {
|
||||
key: name,
|
||||
label,
|
||||
type,
|
||||
required,
|
||||
readOnly,
|
||||
value,
|
||||
description,
|
||||
docUrl,
|
||||
clickToCopy,
|
||||
} = schema;
|
||||
|
||||
|
@@ -9,7 +9,7 @@ type LayoutProps = {
|
||||
}
|
||||
|
||||
export default function Layout({ children }: LayoutProps) {
|
||||
const [isDrawerOpen, setDrawerOpen] = useState(false);
|
||||
const [isDrawerOpen, setDrawerOpen] = useState(true);
|
||||
const onMenuClick = useCallback(() => { setDrawerOpen(value => !value) }, []);
|
||||
|
||||
return (
|
||||
|
Reference in New Issue
Block a user