feat: Extend apps with further data

This commit is contained in:
Ali BARIN
2021-10-10 21:51:16 +02:00
parent 2a01407495
commit 1d65a7c0dd
14 changed files with 93 additions and 26 deletions

View File

@@ -7,7 +7,7 @@ const queryType = new GraphQLObjectType({
name: 'Query', name: 'Query',
fields: { fields: {
getApps: { getApps: {
type: GraphQLList(GraphQLString), type: GraphQLList(appType),
args: { args: {
name: { type: GraphQLString } name: { type: GraphQLString }
}, },

View File

@@ -7,6 +7,7 @@ const appType = new GraphQLObjectType({
name: { type: GraphQLString }, name: { type: GraphQLString },
iconUrl: { type: GraphQLString }, iconUrl: { type: GraphQLString },
docUrl: { type: GraphQLString }, docUrl: { type: GraphQLString },
primaryColor: { type: GraphQLString },
fields: { type: GraphQLList(fieldType) } fields: { type: GraphQLList(fieldType) }
} }
}); });

View File

@@ -1,12 +1,15 @@
import fs from 'fs'; import fs from 'fs';
class App { class App {
static folderPath = __dirname + '/../apps' static folderPath = __dirname + '/../apps';
static list = fs.readdirSync(this.folderPath); static list = fs.readdirSync(this.folderPath);
static findAll(name?: string): string[] { static findAll(name?: string): object[] {
if(!name) return this.list; if(!name) return this.list.map((name) => this.findOneByName(name));
return this.list.filter((app) => app.includes(name.toLowerCase()));
return this.list
.filter((app) => app.includes(name.toLowerCase()))
.map((name) => this.findOneByName(name));
} }
static findOneByName(name: string): object { static findOneByName(name: string): object {

View File

@@ -19,6 +19,7 @@
"graphql": "^15.6.0", "graphql": "^15.6.0",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-hook-form": "^7.17.2",
"react-intl": "^5.20.12", "react-intl": "^5.20.12",
"react-router-dom": "^5.3.0", "react-router-dom": "^5.3.0",
"react-scripts": "4.0.3", "react-scripts": "4.0.3",

View File

@@ -2,13 +2,16 @@ import DialogTitle from '@mui/material/DialogTitle';
import DialogContent from '@mui/material/DialogContent'; import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText'; import DialogContentText from '@mui/material/DialogContentText';
import Dialog from '@mui/material/Dialog'; import Dialog from '@mui/material/Dialog';
import type { App } from 'types/app';
type AddAppConnectionProps = { type AddAppConnectionProps = {
onClose: (value: string) => void; onClose: (value: string) => void;
application: App;
}; };
export default function AddAppConnection(props: AddAppConnectionProps){ export default function AddAppConnection(props: AddAppConnectionProps){
const { onClose } = props; const { application, onClose } = props;
const { name } = application;
return ( return (
<Dialog open={true} onClose={onClose}> <Dialog open={true} onClose={onClose}>
@@ -16,7 +19,7 @@ export default function AddAppConnection(props: AddAppConnectionProps){
<DialogContent> <DialogContent>
<DialogContentText tabIndex={-1}> <DialogContentText tabIndex={-1}>
Here comes the "add connection" dialog Add a connection to {name}
</DialogContentText> </DialogContentText>
</DialogContent> </DialogContent>
</Dialog> </Dialog>

View File

@@ -7,9 +7,9 @@ type AppIconProps = {
}; };
export default function AppIcon(props: AppIconProps) { export default function AppIcon(props: AppIconProps) {
const { color = '#00adef', name, url } = props; const { color, name, url } = props;
return ( return (
<Avatar component="span" variant="square" sx={{ bgcolor: color }} src={url} alt={name} /> <Avatar component="span" variant="square" sx={{ bgcolor: `#${color}` }} src={url} alt={name} />
); );
}; };

View File

@@ -1,36 +1,32 @@
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import Card from '@mui/material/Card'; import Card from '@mui/material/Card';
import Box from '@mui/material/Box'; import Box from '@mui/material/Box';
import Avatar from '@mui/material/Avatar';
import CardActionArea from '@mui/material/CardActionArea'; import CardActionArea from '@mui/material/CardActionArea';
import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import ChevronRightIcon from '@mui/icons-material/ChevronRight';
import useFormatMessage from 'hooks/useFormatMessage'; import useFormatMessage from 'hooks/useFormatMessage';
import AppIcon from 'components/AppIcon';
import * as URLS from 'config/urls';
import type { App } from 'types/app';
import { CardContent, Typography, DesktopOnlyBreakline } from './style'; import { CardContent, Typography, DesktopOnlyBreakline } from './style';
type AppRowProps = { type AppRowProps = {
icon?: React.ReactNode; application: App;
name: string;
connectionNumber?: number;
flowNumber?: number;
to: string;
} }
const countTranslation = (value: React.ReactNode) => (<><strong>{value}</strong><DesktopOnlyBreakline /></>); const countTranslation = (value: React.ReactNode) => (<><strong>{value}</strong><DesktopOnlyBreakline /></>);
function AppRow(props: AppRowProps) { function AppRow(props: AppRowProps) {
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const { name, to } = props; const { name, primaryColor, iconUrl } = props.application;
return ( return (
<Link to={to}> <Link to={URLS.APP(name.toLowerCase())}>
<Card sx={{ my: 2 }}> <Card sx={{ my: 2 }}>
<CardActionArea> <CardActionArea>
<CardContent> <CardContent>
<Box> <Box>
<Avatar variant="square"> <AppIcon name={name} url={iconUrl} color={primaryColor} />
{name[0].toUpperCase()}
</Avatar>
</Box> </Box>
<Box> <Box>

View File

@@ -0,0 +1,20 @@
import React from "react";
import { Controller, Control, FieldValues } from "react-hook-form";
import MuiTextField from "@mui/material/TextField";
type TextFieldProps = {
control: Control<FieldValues>;
name: string;
}
export default function TextField({ control, name }: TextFieldProps) {
return (
<Controller
name="MyCheckbox"
control={control}
defaultValue={false}
rules={{ required: true }}
render={({ field }) => <MuiTextField {...field} />}
/>
);
};

View File

@@ -6,6 +6,7 @@ export const GET_APP = gql`
name name
iconUrl iconUrl
docUrl docUrl
primaryColor
fields { fields {
key key
label label

View File

@@ -2,6 +2,22 @@ import { gql } from '@apollo/client';
export const GET_APPS = gql` export const GET_APPS = gql`
query GetApps($name: String) { query GetApps($name: String) {
getApps(name: $name) getApps(name: $name) {
name
iconUrl
docUrl
primaryColor
fields {
key
label
type
required
readOnly
placeholder
description
docUrl
clickToCopy
}
}
} }
`; `;

View File

@@ -38,7 +38,7 @@ export default function Application() {
<Container> <Container>
<Grid container sx={{ mb: 3 }}> <Grid container sx={{ mb: 3 }}>
<Grid item xs="auto" sx={{ mr: 1.5 }}> <Grid item xs="auto" sx={{ mr: 1.5 }}>
<AppIcon url={app.iconUrl} name={app.name} /> <AppIcon url={app.iconUrl} color={app.primaryColor} name={app.name} />
</Grid> </Grid>
<Grid item xs> <Grid item xs>
@@ -95,7 +95,7 @@ export default function Application() {
</Box> </Box>
<Route exact path={URLS.APP_ADD_CONNECTION_PATTERN}> <Route exact path={URLS.APP_ADD_CONNECTION_PATTERN}>
<AddAppConnection onClose={goToApplicationPage} /> <AddAppConnection onClose={goToApplicationPage} application={app} />
</Route> </Route>
</> </>
); );

View File

@@ -8,8 +8,8 @@ import PageTitle from 'components/PageTitle';
import AppRow from 'components/AppRow'; import AppRow from 'components/AppRow';
import SearchInput from 'components/SearchInput'; import SearchInput from 'components/SearchInput';
import * as URLS from 'config/urls'; import * as URLS from 'config/urls';
import { GET_APPS } from 'graphql/queries/get-apps'; import { GET_APPS } from 'graphql/queries/get-apps';
import type { App } from 'types/app';
export default function Applications() { export default function Applications() {
const [appName, setAppName] = useState(null); const [appName, setAppName] = useState(null);
@@ -32,8 +32,8 @@ export default function Applications() {
</Grid> </Grid>
</Grid> </Grid>
{data?.getApps?.map((name: string) => ( {data?.getApps?.map((app: App) => (
<AppRow key={name} name={name} to={URLS.APP(name)} /> <AppRow key={app.name} application={app} />
))} ))}
</Container> </Container>
</Box> </Box>

View File

@@ -0,0 +1,21 @@
type AppFields = {
key: string;
label: string;
type: string;
required: boolean,
readOnly: boolean,
placeholder: string;
description: string;
docUrl: string;
clickToCopy: boolean,
};
type App = {
name: string;
iconUrl: string;
docUrl: string;
primaryColor: string;
fields: AppFields;
};
export type { App, AppFields };

View File

@@ -12953,6 +12953,11 @@ react-error-overlay@^6.0.9:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a"
integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew== integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==
react-hook-form@^7.17.2:
version "7.17.2"
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.17.2.tgz#235f15bb65c13e7a1198d33f2db24bcc9e27b303"
integrity sha512-oBaHwlYnbpzSFdNrs43QpcM+K2A0kUeNjV86ECYkCimlR1Ctl+tz4oQQd9plfGYkO7PJGLVMOVpUtL5EHjAcYQ==
react-intl@^5.20.12: react-intl@^5.20.12:
version "5.20.12" version "5.20.12"
resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-5.20.12.tgz#1a4969d15c381378cae35912fa2ec7010e27b4f7" resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-5.20.12.tgz#1a4969d15c381378cae35912fa2ec7010e27b4f7"