diff --git a/packages/web/public/index.html b/packages/web/public/index.html index 902444b1..a81fbaf6 100644 --- a/packages/web/public/index.html +++ b/packages/web/public/index.html @@ -25,6 +25,11 @@ Learn how to configure a non-root public URL by running `npm run build`. --> Automatisch + + diff --git a/packages/web/src/components/AppBar/index.tsx b/packages/web/src/components/AppBar/index.tsx index 824117fe..5891ee58 100644 --- a/packages/web/src/components/AppBar/index.tsx +++ b/packages/web/src/components/AppBar/index.tsx @@ -4,20 +4,16 @@ import Toolbar from '@mui/material/Toolbar'; import IconButton from '@mui/material/IconButton'; import Typography from '@mui/material/Typography'; import MenuIcon from '@mui/icons-material/Menu'; -import SearchIcon from '@mui/icons-material/Search'; import HideOnScroll from 'components/HideOnScroll'; import { FormattedMessage } from 'react-intl'; -import useFormatMessage from 'hooks/useFormatMessage'; -import { Search, SearchIconWrapper, InputBase } from './style'; +import SearchInput from 'components/SearchInput'; type AppBarProps = { onMenuClick: () => void; }; export default function AppBar({ onMenuClick }: AppBarProps) { - const formatMessage = useFormatMessage(); - return ( @@ -41,19 +37,10 @@ export default function AppBar({ onMenuClick }: AppBarProps) { component="div" sx={{ flexGrow: 1, display: { xs: 'none', sm: 'block' } }} > - + - - - - - - - + diff --git a/packages/web/src/components/AppRow/index.tsx b/packages/web/src/components/AppRow/index.tsx index 5897630c..26f15681 100644 --- a/packages/web/src/components/AppRow/index.tsx +++ b/packages/web/src/components/AppRow/index.tsx @@ -1,28 +1,64 @@ +import { Link } from 'react-router-dom'; import Card from '@mui/material/Card'; +import Box from '@mui/material/Box'; +import Avatar from '@mui/material/Avatar'; import CardActionArea from '@mui/material/CardActionArea'; -import CardContent from '@mui/material/CardContent'; -import Typography from '@mui/material/Typography'; +import ChevronRightIcon from '@mui/icons-material/ChevronRight'; + +import useFormatMessage from 'hooks/useFormatMessage'; +import { CardContent, Typography, DesktopOnlyBreakline } from './style'; type AppRowProps = { icon?: React.ReactNode; name: string; connectionNumber?: number; flowNumber?: number; + to: string; } -export default function AppRow(props: AppRowProps) { - const { name } = props; +const countTranslation = (value: React.ReactNode) => (<>{value}); + +function AppRow(props: AppRowProps) { + const formatMessage = useFormatMessage(); + const { name, to } = props; return ( - - + + + + + + + {name[0].toUpperCase()} + + - - - {name} - - - - + + + {name} + + + + + + {formatMessage('app.connections', { count: countTranslation(Math.round(Math.random() * 100)) })} + + + + + + {formatMessage('app.flows', { count: countTranslation(Math.round(Math.random() * 100)) })} + + + + + + + + + + ); } + +export default AppRow; diff --git a/packages/web/src/components/AppRow/style.ts b/packages/web/src/components/AppRow/style.ts new file mode 100644 index 00000000..84f3612c --- /dev/null +++ b/packages/web/src/components/AppRow/style.ts @@ -0,0 +1,26 @@ +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: 'auto 1fr auto auto auto', + gridColumnGap: theme.spacing(2), + alignItems: 'center', +})); + + +export const Typography = styled(MuiTypography)(({ theme }) => ({ + '&.MuiTypography-h6': { + textTransform: 'capitalize', + }, + textAlign: 'center', + display: 'inline-block', +})); + +export const DesktopOnlyBreakline = styled('br')(({ theme }) => ({ + [theme.breakpoints.down('md')]: { + display: 'none', + } +})); diff --git a/packages/web/src/components/SearchInput/index.tsx b/packages/web/src/components/SearchInput/index.tsx new file mode 100644 index 00000000..888bddfc --- /dev/null +++ b/packages/web/src/components/SearchInput/index.tsx @@ -0,0 +1,26 @@ +import SearchIcon from '@mui/icons-material/Search'; + +import useFormatMessage from 'hooks/useFormatMessage'; +import { Search, SearchIconWrapper, InputBase } from './style'; + +type SearchInputProps = { + onChange?: (event: React.ChangeEvent) => void; +}; + +export default function SearchInput({ onChange }: SearchInputProps) { + const formatMessage = useFormatMessage(); + + return ( + + + + + + + + ); +} diff --git a/packages/web/src/components/AppBar/style.ts b/packages/web/src/components/SearchInput/style.ts similarity index 83% rename from packages/web/src/components/AppBar/style.ts rename to packages/web/src/components/SearchInput/style.ts index 3cd5bd23..e39ba2ae 100644 --- a/packages/web/src/components/AppBar/style.ts +++ b/packages/web/src/components/SearchInput/style.ts @@ -1,5 +1,5 @@ import { styled, alpha } from '@mui/material/styles'; -import MuiInputBase from '@mui/material/InputBase'; +import MuiInput from '@mui/material/Input'; export const Search = styled('div')(({ theme }) => ({ position: 'relative', @@ -10,6 +10,7 @@ export const Search = styled('div')(({ theme }) => ({ }, marginLeft: 0, width: '100%', + maxWidth: '100%', [theme.breakpoints.up('sm')]: { marginLeft: theme.spacing(1), width: 'auto', @@ -26,14 +27,16 @@ export const SearchIconWrapper = styled('div')(({ theme }) => ({ justifyContent: 'center', })); -export const InputBase = styled(MuiInputBase)(({ theme }) => ({ +export const InputBase = styled(MuiInput)(({ theme }) => ({ color: 'inherit', - '& .MuiInputBase-input': { + width: '100%', + maxWidth: '100%', + '& .MuiInput-input': { padding: theme.spacing(1, 1, 1, 0), // vertical padding + font size from searchIcon paddingLeft: `calc(1em + ${theme.spacing(4)})`, transition: theme.transitions.create('width'), - width: '100%', + width: '200', [theme.breakpoints.up('sm')]: { width: '12ch', '&:focus': { diff --git a/packages/web/src/config/urls.ts b/packages/web/src/config/urls.ts index 3bb2587f..3c13122e 100644 --- a/packages/web/src/config/urls.ts +++ b/packages/web/src/config/urls.ts @@ -1,4 +1,6 @@ export const DASHBOARD = '/dashboard'; export const APPS = '/apps'; export const FLOWS = '/flows'; -export const EXPLORE = '/explore'; \ No newline at end of file +export const EXPLORE = '/explore'; +export const APP_PATH = (appSlug: string) => `/app/${appSlug}`; +export const APP_PATH_PATTERN = '/app/:slug'; diff --git a/packages/web/src/graphql/queries/get-apps.ts b/packages/web/src/graphql/queries/get-apps.ts new file mode 100644 index 00000000..236aa78c --- /dev/null +++ b/packages/web/src/graphql/queries/get-apps.ts @@ -0,0 +1,7 @@ +import { gql } from '@apollo/client'; + +export const GET_APPS = gql` + query GetApps($name: String) { + getApps(name: $name) + } +`; \ No newline at end of file diff --git a/packages/web/src/locales/en.json b/packages/web/src/locales/en.json index 9e357a0c..e90c12d3 100644 --- a/packages/web/src/locales/en.json +++ b/packages/web/src/locales/en.json @@ -5,5 +5,7 @@ "drawer.dashboard": "Dashboard", "drawer.flows": "Flows", "drawer.apps": "My Apps", - "drawer.explore": "Explore" + "drawer.explore": "Explore", + "app.connections": "{count} connections", + "app.flows": "{count} flows" } \ No newline at end of file diff --git a/packages/web/src/pages/Application/index.tsx b/packages/web/src/pages/Application/index.tsx new file mode 100644 index 00000000..1c60f62f --- /dev/null +++ b/packages/web/src/pages/Application/index.tsx @@ -0,0 +1,26 @@ +import { useCallback, useState } from 'react'; +import Box from '@mui/material/Box'; +import Grid from '@mui/material/Grid'; + +import Container from 'components/Container'; +import PageTitle from 'components/PageTitle'; +import SearchInput from 'components/SearchInput'; + + +export default function Applications() { + + return ( + + + + + Application! + + + + + + + + ); +}; diff --git a/packages/web/src/pages/Applications/index.tsx b/packages/web/src/pages/Applications/index.tsx index 4f21f48e..e267f55d 100644 --- a/packages/web/src/pages/Applications/index.tsx +++ b/packages/web/src/pages/Applications/index.tsx @@ -1,18 +1,40 @@ +import { useCallback, useState } from 'react'; +import { useQuery } from '@apollo/client'; import Box from '@mui/material/Box'; +import Grid from '@mui/material/Grid'; + import Container from 'components/Container'; import PageTitle from 'components/PageTitle'; import AppRow from 'components/AppRow'; +import SearchInput from 'components/SearchInput'; +import * as URLS from 'config/urls'; + +import { GET_APPS } from 'graphql/queries/get-apps'; export default function Applications() { + const [appName, setAppName] = useState(null); + const { data } = useQuery(GET_APPS, { variables: {name: appName } }); + + const onSearchChange = useCallback((event) => { + setAppName(event.target.value); + }, []); + return ( - Applications + + + Applications + - - - - + + + + + + {data?.getApps?.map((name: string) => ( + + ))} ); diff --git a/packages/web/src/routes.tsx b/packages/web/src/routes.tsx index 738235dd..061ec64c 100644 --- a/packages/web/src/routes.tsx +++ b/packages/web/src/routes.tsx @@ -1,6 +1,7 @@ import { Route, Switch, Redirect } from "react-router"; import Dashboard from 'pages/Dashboard'; import Applications from 'pages/Applications'; +import Application from 'pages/Application'; import Flows from 'pages/Flows'; import Explore from 'pages/Explore'; import * as URLS from 'config/urls'; @@ -23,6 +24,10 @@ export default ( + + + + diff --git a/packages/web/src/styles/theme.ts b/packages/web/src/styles/theme.ts index d8e756c0..320f433e 100644 --- a/packages/web/src/styles/theme.ts +++ b/packages/web/src/styles/theme.ts @@ -1,5 +1,15 @@ import { createTheme } from '@mui/material/styles'; -const theme = createTheme(); +const theme = createTheme({ + components: { + MuiCssBaseline: { + styleOverrides: { + a: { + textDecoration: 'none', + }, + }, + }, + } +}); export default theme;