chore: suit eslint rules

This commit is contained in:
Ali BARIN
2022-01-16 19:47:16 +01:00
parent f6d7971b4f
commit c09a535653
73 changed files with 1197 additions and 2549 deletions

View File

@@ -1,5 +1,4 @@
import { URLSearchParams } from 'url'; import { URLSearchParams } from 'url';
import DiscordApi from 'discord.js';
import axios, { AxiosInstance } from 'axios'; import axios, { AxiosInstance } from 'axios';
import App from '../../models/app'; import App from '../../models/app';
import Field from '../../types/field'; import Field from '../../types/field';

View File

@@ -1,4 +1,4 @@
import { google, google as GoogleApi } from 'googleapis'; import { google as GoogleApi } from 'googleapis';
import App from '../../models/app'; import App from '../../models/app';
import Field from '../../types/field'; import Field from '../../types/field';

View File

@@ -16,11 +16,11 @@ export default class Authentication {
this.appData = App.findOneByKey('github'); this.appData = App.findOneByKey('github');
} }
get oauthRedirectUrl() { get oauthRedirectUrl(): string {
return this.appData.fields.find((field: Field) => field.key == 'oAuthRedirectUrl').value; return this.appData.fields.find((field: Field) => field.key == 'oAuthRedirectUrl').value;
} }
async createAuthData() { async createAuthData(): { url: string } {
const { url } = await getWebFlowAuthorizationUrl({ const { url } = await getWebFlowAuthorizationUrl({
clientType: "oauth-app", clientType: "oauth-app",
clientId: this.connectionData.consumerKey, clientId: this.connectionData.consumerKey,
@@ -33,8 +33,8 @@ export default class Authentication {
}; };
} }
async verifyCredentials() { async verifyCredentials(): any {
const { data, authentication } = await exchangeWebFlowCode({ const { data } = await exchangeWebFlowCode({
clientType: "oauth-app", clientType: "oauth-app",
clientId: this.connectionData.consumerKey, clientId: this.connectionData.consumerKey,
clientSecret: this.connectionData.consumerSecret, clientSecret: this.connectionData.consumerSecret,
@@ -65,7 +65,7 @@ export default class Authentication {
}); });
} }
async isStillVerified() { async isStillVerified(): boolean {
try { try {
await this.getTokenInfo(); await this.getTokenInfo();

View File

@@ -1,4 +1,4 @@
import TwitchApi, { ApiVersions } from 'twitch-js'; import TwitchApi from 'twitch-js';
import fetchUtil from 'twitch-js/lib/utils/fetch'; import fetchUtil from 'twitch-js/lib/utils/fetch';
import App from '../../models/app'; import App from '../../models/app';
import Field from '../../types/field'; import Field from '../../types/field';

View File

@@ -1,20 +1,18 @@
import { GraphQLInt, GraphQLNonNull } from 'graphql'; import { GraphQLInt, GraphQLNonNull } from 'graphql';
import App from '../../models/app';
import Connection from '../../models/connection'; import Connection from '../../models/connection';
import Step from '../../models/step'; import Step from '../../models/step';
import stepType from '../types/step'; import stepType from '../types/step';
import RequestWithCurrentUser from '../../types/express/request-with-current-user';
type Params = { type Params = {
id: number, id: number,
data: object data: Record<string, unknown>
} }
const executeStepResolver = async (params: Params, req: RequestWithCurrentUser) => { const executeStepResolver = async (params: Params): Promise<any> => {
let step = await Step.query().findOne({ const step = await Step.query().findOne({
id: params.id id: params.id
}).throwIfNotFound(); }).throwIfNotFound();
let connection = await Connection.query().findOne({ const connection = await Connection.query().findOne({
id: step.connectionId id: step.connectionId
}).throwIfNotFound(); }).throwIfNotFound();
@@ -30,7 +28,7 @@ const executeStep = {
args: { args: {
id: { type: GraphQLNonNull(GraphQLInt) } id: { type: GraphQLNonNull(GraphQLInt) }
}, },
resolve: (_: any, params: Params, req: RequestWithCurrentUser) => executeStepResolver(params, req) resolve: (_: any, params: Params) => executeStepResolver(params)
}; };
export default executeStep; export default executeStep;

View File

@@ -1,7 +1,6 @@
import { GraphQLInt, GraphQLString, GraphQLNonNull } from 'graphql'; import { GraphQLInt, GraphQLString, GraphQLNonNull } from 'graphql';
import Flow from '../../models/flow'; import Flow from '../../models/flow';
import Step from '../../models/step'; import Step from '../../models/step';
import flowType from '../types/flow';
import stepType from '../types/step'; import stepType from '../types/step';
import availableAppsEnumType from '../types/available-apps-enum-type'; import availableAppsEnumType from '../types/available-apps-enum-type';
import RequestWithCurrentUser from '../../types/express/request-with-current-user'; import RequestWithCurrentUser from '../../types/express/request-with-current-user';

View File

@@ -1,9 +1,9 @@
import { GraphQLList, GraphQLString } from 'graphql'; import { GraphQLList } from 'graphql';
import Flow from '../../models/flow'; import Flow from '../../models/flow';
import RequestWithCurrentUser from '../../types/express/request-with-current-user'; import RequestWithCurrentUser from '../../types/express/request-with-current-user';
import flowType from '../types/flow'; import flowType from '../types/flow';
const getFlowsResolver = async (req: RequestWithCurrentUser) => { const getFlowsResolver = async (req: RequestWithCurrentUser): Promise<any[]> => {
const flows = await Flow.query() const flows = await Flow.query()
.withGraphJoined('[steps.[connection]]') .withGraphJoined('[steps.[connection]]')
.where({'flows.user_id': req.currentUser.id}); .where({'flows.user_id': req.currentUser.id});

View File

@@ -1,4 +1,4 @@
import { GraphQLString, GraphQLNonNull, GraphQLBoolean } from 'graphql'; import { GraphQLString, GraphQLNonNull } from 'graphql';
import Connection from '../../models/connection'; import Connection from '../../models/connection';
import RequestWithCurrentUser from '../../types/express/request-with-current-user'; import RequestWithCurrentUser from '../../types/express/request-with-current-user';
import connectionType from '../types/connection' import connectionType from '../types/connection'

View File

@@ -1,4 +1,4 @@
import { GraphQLObjectType, GraphQLString, GraphQLList, GraphQLInt, GraphQLBoolean } from 'graphql'; import { GraphQLObjectType, GraphQLString, GraphQLList, GraphQLBoolean } from 'graphql';
const actionType = new GraphQLObjectType({ const actionType = new GraphQLObjectType({
name: 'Action', name: 'Action',
@@ -6,13 +6,13 @@ const actionType = new GraphQLObjectType({
name: { type: GraphQLString }, name: { type: GraphQLString },
key: { type: GraphQLString }, key: { type: GraphQLString },
description: { type: GraphQLString }, description: { type: GraphQLString },
subSteps: { subSteps: {
type: GraphQLList( type: GraphQLList(
new GraphQLObjectType({ new GraphQLObjectType({
name: 'ActionSubStep', name: 'ActionSubStep',
fields: { fields: {
name: { type: GraphQLString }, name: { type: GraphQLString },
arguments: { arguments: {
type: GraphQLList( type: GraphQLList(
new GraphQLObjectType({ new GraphQLObjectType({
name: 'ActionSubStepArgument', name: 'ActionSubStepArgument',

View File

@@ -8,6 +8,7 @@ import actionType from './action';
const appType = new GraphQLObjectType({ const appType = new GraphQLObjectType({
name: 'App', name: 'App',
fields: () => { fields: () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const connectionType = require('./connection').default; const connectionType = require('./connection').default;
return { return {

View File

@@ -4,6 +4,7 @@ import connectionDataType from './connection-data';
const connectionType = new GraphQLObjectType({ const connectionType = new GraphQLObjectType({
name: 'Connection', name: 'Connection',
fields: () => { fields: () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const appType = require('./app').default; const appType = require('./app').default;
return { return {

View File

@@ -1,4 +1,4 @@
import { GraphQLObjectType, GraphQLString, GraphQLNonNull, GraphQLEnumType, GraphQLInt } from 'graphql'; import { GraphQLObjectType, GraphQLString, GraphQLEnumType, GraphQLInt } from 'graphql';
import ConnectionType from './connection'; import ConnectionType from './connection';
const stepType = new GraphQLObjectType({ const stepType = new GraphQLObjectType({

View File

@@ -1,4 +1,4 @@
import { GraphQLObjectType, GraphQLString, GraphQLList, GraphQLInt, GraphQLBoolean } from 'graphql'; import { GraphQLObjectType, GraphQLString, GraphQLList, GraphQLBoolean } from 'graphql';
const triggerType = new GraphQLObjectType({ const triggerType = new GraphQLObjectType({
name: 'Trigger', name: 'Trigger',
@@ -6,13 +6,13 @@ const triggerType = new GraphQLObjectType({
name: { type: GraphQLString }, name: { type: GraphQLString },
key: { type: GraphQLString }, key: { type: GraphQLString },
description: { type: GraphQLString }, description: { type: GraphQLString },
subSteps: { subSteps: {
type: GraphQLList( type: GraphQLList(
new GraphQLObjectType({ new GraphQLObjectType({
name: 'TriggerSubStep', name: 'TriggerSubStep',
fields: { fields: {
name: { type: GraphQLString }, name: { type: GraphQLString },
arguments: { arguments: {
type: GraphQLList( type: GraphQLList(
new GraphQLObjectType({ new GraphQLObjectType({
name: 'TriggerSubStepArgument', name: 'TriggerSubStepArgument',

View File

@@ -1,8 +1,8 @@
import { Request, Response, NextFunction } from 'express'; import { Response, NextFunction } from 'express';
import User from '../models/user'; import User from '../models/user';
import RequestWithCurrentUser from '../types/express/request-with-current-user'; import RequestWithCurrentUser from '../types/express/request-with-current-user';
const authentication = async (req: RequestWithCurrentUser, _res: Response, next: NextFunction) => { const authentication = async (req: RequestWithCurrentUser, _res: Response, next: NextFunction): Promise<void> => {
// We set authentication to use the sample user we created temporarily. // We set authentication to use the sample user we created temporarily.
req.currentUser = await User.query().findOne({ req.currentUser = await User.query().findOne({
email: 'user@automatisch.com' email: 'user@automatisch.com'

View File

@@ -1,7 +1,11 @@
import { Request, Response, NextFunction } from 'express'; import { Request, Response } from 'express';
import logger from './logger'; import logger from './logger';
const errorHandler = (err: any, req: Request, res: Response, _next: NextFunction) => { type Error = {
message: string;
}
const errorHandler = (err: Error, req: Request, res: Response): void => {
if(err.message === 'Not Found') { if(err.message === 'Not Found') {
res.status(404).end() res.status(404).end()
} else { } else {

View File

@@ -1,5 +1,5 @@
import { Model, snakeCaseMappers } from 'objection'; import { Model, snakeCaseMappers } from 'objection';
import type { Constructor, TransactionOrKnex, QueryBuilderType, QueryContext, ModelOptions, ColumnNameMappers } from 'objection'; import type { QueryContext, ModelOptions, ColumnNameMappers } from 'objection';
class Base extends Model { class Base extends Model {
createdAt!: string; createdAt!: string;
@@ -9,14 +9,14 @@ class Base extends Model {
return snakeCaseMappers(); return snakeCaseMappers();
} }
async $beforeInsert(queryContext: QueryContext) { async $beforeInsert(queryContext: QueryContext): Promise<void> {
await super.$beforeInsert(queryContext); await super.$beforeInsert(queryContext);
this.createdAt = new Date().toISOString(); this.createdAt = new Date().toISOString();
this.updatedAt = new Date().toISOString(); this.updatedAt = new Date().toISOString();
} }
async $beforeUpdate(opt: ModelOptions, queryContext: QueryContext) { async $beforeUpdate(opt: ModelOptions, queryContext: QueryContext): Promise<void> {
await super.$beforeUpdate(opt, queryContext); await super.$beforeUpdate(opt, queryContext);
this.updatedAt = new Date().toISOString(); this.updatedAt = new Date().toISOString();

View File

@@ -1,4 +1,5 @@
import { QueryContext, ModelOptions } from 'objection'; import { QueryContext, ModelOptions } from 'objection';
import type { RelationMappings } from 'objection';
import { AES, enc } from 'crypto-js'; import { AES, enc } from 'crypto-js';
import Base from './base' import Base from './base'
import User from './user' import User from './user'
@@ -27,7 +28,7 @@ class Connection extends Base {
} }
} }
static relationMappings = () => ({ static relationMappings = (): RelationMappings => ({
user: { user: {
relation: Base.BelongsToOneRelation, relation: Base.BelongsToOneRelation,
modelClass: User, modelClass: User,
@@ -38,33 +39,33 @@ class Connection extends Base {
} }
}) })
encryptData() { encryptData(): void {
if(!this.eligibleForEncryption()) return; if(!this.eligibleForEncryption()) return;
this.data = AES.encrypt(JSON.stringify(this.data), appConfig.encryptionKey).toString(); this.data = AES.encrypt(JSON.stringify(this.data), appConfig.encryptionKey).toString();
} }
decryptData() { decryptData(): void {
if(!this.eligibleForEncryption()) return; if(!this.eligibleForEncryption()) return;
this.data = JSON.parse(AES.decrypt(this.data, appConfig.encryptionKey).toString(enc.Utf8)); this.data = JSON.parse(AES.decrypt(this.data, appConfig.encryptionKey).toString(enc.Utf8));
} }
eligibleForEncryption() { eligibleForEncryption(): boolean {
return this.data ? true : false return this.data ? true : false
} }
// TODO: Make another abstraction like beforeSave instead of using // TODO: Make another abstraction like beforeSave instead of using
// beforeInsert and beforeUpdate separately for the same operation. // beforeInsert and beforeUpdate separately for the same operation.
async $beforeInsert(queryContext: QueryContext) { async $beforeInsert(queryContext: QueryContext): Promise<void> {
await super.$beforeInsert(queryContext); await super.$beforeInsert(queryContext);
this.encryptData(); this.encryptData();
} }
async $beforeUpdate(opt: ModelOptions, queryContext: QueryContext) { async $beforeUpdate(opt: ModelOptions, queryContext: QueryContext): Promise<void> {
await super.$beforeUpdate(opt, queryContext); await super.$beforeUpdate(opt, queryContext);
this.encryptData(); this.encryptData();
} }
async $afterFind(queryContext: QueryContext) { async $afterFind(): Promise<void> {
this.decryptData(); this.decryptData();
} }
} }

View File

@@ -1,7 +0,0 @@
'use strict';
const cli = require('..');
describe('cli', () => {
it('needs tests');
});

View File

@@ -1,7 +1,8 @@
'use strict'; 'use strict';
// eslint-disable-next-line no-undef
module.exports = cli; module.exports = cli;
function cli() { function cli() {
// TODO // TODO
} }

View File

@@ -23,7 +23,7 @@ type Response = {
[key: string]: any; [key: string]: any;
} }
export default function AddAppConnection(props: AddAppConnectionProps){ export default function AddAppConnection(props: AddAppConnectionProps): React.ReactElement {
const { application, connectionId, onClose } = props; const { application, connectionId, onClose } = props;
const { key, fields, authenticationSteps, reconnectionSteps } = application; const { key, fields, authenticationSteps, reconnectionSteps } = application;
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();

View File

@@ -1,4 +1,4 @@
import { useState } from 'react'; import * as React from 'react';
import { useQuery } from '@apollo/client'; import { useQuery } from '@apollo/client';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useTheme } from '@mui/material/styles'; import { useTheme } from '@mui/material/styles';
@@ -27,12 +27,12 @@ type AddNewAppConnectionProps = {
onClose: () => void; onClose: () => void;
}; };
export default function AddNewAppConnection(props: AddNewAppConnectionProps){ export default function AddNewAppConnection(props: AddNewAppConnectionProps): React.ReactElement {
const { onClose } = props; const { onClose } = props;
const theme = useTheme(); const theme = useTheme();
const matchSmallScreens = useMediaQuery(theme.breakpoints.down('sm')); const matchSmallScreens = useMediaQuery(theme.breakpoints.down('sm'));
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const [appName, setAppName] = useState<string | null>(null); const [appName, setAppName] = React.useState<string | null>(null);
const { data } = useQuery(GET_APPS, { variables: {name: appName } }); const { data } = useQuery(GET_APPS, { variables: {name: appName } });
return ( return (

View File

@@ -7,7 +7,7 @@ type ApolloProviderProps = {
children: React.ReactNode; children: React.ReactNode;
}; };
const ApolloProvider = (props: ApolloProviderProps) => { const ApolloProvider = (props: ApolloProviderProps): React.ReactElement => {
const { enqueueSnackbar } = useSnackbar(); const { enqueueSnackbar } = useSnackbar();
const onError = React.useCallback((message) => { const onError = React.useCallback((message) => {

View File

@@ -1,3 +1,4 @@
import * as React from 'react';
import { useTheme } from '@mui/material/styles'; import { useTheme } from '@mui/material/styles';
import useMediaQuery from '@mui/material/useMediaQuery'; import useMediaQuery from '@mui/material/useMediaQuery';
import MuiAppBar from '@mui/material/AppBar'; import MuiAppBar from '@mui/material/AppBar';
@@ -18,7 +19,7 @@ type AppBarProps = {
onDrawerClose: () => void; onDrawerClose: () => void;
}; };
export default function AppBar({ drawerOpen, onDrawerOpen, onDrawerClose }: AppBarProps) { export default function AppBar({ drawerOpen, onDrawerOpen, onDrawerClose }: AppBarProps): React.ReactElement {
const theme = useTheme(); const theme = useTheme();
const matchSmallScreens = useMediaQuery(theme.breakpoints.down('md'), { noSsr: true }); const matchSmallScreens = useMediaQuery(theme.breakpoints.down('md'), { noSsr: true });

View File

@@ -19,7 +19,7 @@ type ContextMenuProps = {
anchorEl: PopoverProps['anchorEl']; anchorEl: PopoverProps['anchorEl'];
}; };
export default function ContextMenu(props: ContextMenuProps) { export default function ContextMenu(props: ContextMenuProps): React.ReactElement {
const { appKey, connectionId, onClose, onMenuItemClick, anchorEl } = props; const { appKey, connectionId, onClose, onMenuItemClick, anchorEl } = props;
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();

View File

@@ -31,7 +31,7 @@ const countTranslation = (value: React.ReactNode) => (
</> </>
); );
function AppConnectionRow(props: AppConnectionRowProps) { function AppConnectionRow(props: AppConnectionRowProps): React.ReactElement {
const { enqueueSnackbar } = useSnackbar(); const { enqueueSnackbar } = useSnackbar();
const [verificationVisible, setVerificationVisible] = React.useState(false); const [verificationVisible, setVerificationVisible] = React.useState(false);
const [testConnection, { called: testCalled, loading: testLoading }] = useLazyQuery(TEST_CONNECTION, { const [testConnection, { called: testCalled, loading: testLoading }] = useLazyQuery(TEST_CONNECTION, {
@@ -51,12 +51,12 @@ function AppConnectionRow(props: AppConnectionRowProps) {
setAnchorEl(null); setAnchorEl(null);
}; };
const onContextMenuClick = (event: React.MouseEvent<HTMLButtonElement>) => setAnchorEl(contextButtonRef.current); const onContextMenuClick = () => setAnchorEl(contextButtonRef.current);
const onContextMenuAction = React.useCallback(async (event, action: { [key: string]: string }) => { const onContextMenuAction = React.useCallback(async (event, action: { [key: string]: string }) => {
if (action.type === 'delete') { if (action.type === 'delete') {
await deleteConnection({ await deleteConnection({
variables: { id }, variables: { id },
update: (cache, mutationResult) => { update: (cache) => {
const connectionCacheId = cache.identify({ const connectionCacheId = cache.identify({
__typename: 'Connection', __typename: 'Connection',
id, id,

View File

@@ -11,7 +11,7 @@ export const CardContent = styled(MuiCardContent)(({ theme }) => ({
})); }));
export const Typography = styled(MuiTypography)(({ theme }) => ({ export const Typography = styled(MuiTypography)(() => ({
textAlign: 'center', textAlign: 'center',
display: 'inline-block', display: 'inline-block',
})); }));

View File

@@ -12,7 +12,7 @@ type AppConnectionsProps = {
appKey: string; appKey: string;
} }
export default function AppConnections(props: AppConnectionsProps) { export default function AppConnections(props: AppConnectionsProps): React.ReactElement {
const { appKey } = props; const { appKey } = props;
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const { data } = useQuery(GET_APP_CONNECTIONS, { variables: { key: appKey } }); const { data } = useQuery(GET_APP_CONNECTIONS, { variables: { key: appKey } });

View File

@@ -12,7 +12,7 @@ type AppFlowRowProps = {
flow: any; flow: any;
} }
function AppFlowRow(props: AppFlowRowProps) { function AppFlowRow(props: AppFlowRowProps): React.ReactElement {
const { flow } = props; const { flow } = props;
return ( return (

View File

@@ -11,7 +11,7 @@ export const CardContent = styled(MuiCardContent)(({ theme }) => ({
})); }));
export const Typography = styled(MuiTypography)(({ theme }) => ({ export const Typography = styled(MuiTypography)(() => ({
display: 'inline-block', display: 'inline-block',
width: 300, width: 300,
maxWidth: '50%', maxWidth: '50%',

View File

@@ -4,11 +4,7 @@ import { GET_FLOWS } from 'graphql/queries/get-flows';
import AppFlowRow from 'components/AppFlowRow'; import AppFlowRow from 'components/AppFlowRow';
import type { Flow } from 'types/flow'; import type { Flow } from 'types/flow';
type AppFlowsProps = { export default function AppFlows(): React.ReactElement {
appKey: String;
}
export default function AppFlows(props: AppFlowsProps) {
const { data } = useQuery(GET_FLOWS); const { data } = useQuery(GET_FLOWS);
const appFlows: Flow[] = data?.getFlows || []; const appFlows: Flow[] = data?.getFlows || [];

View File

@@ -12,7 +12,7 @@ const inlineImgStyle: React.CSSProperties = {
objectFit: 'contain', objectFit: 'contain',
}; };
export default function AppIcon(props: AppIconProps & AvatarProps) { export default function AppIcon(props: AppIconProps & AvatarProps): React.ReactElement {
const { name, url, color, sx = {}, ...restProps } = props; const { name, url, color, sx = {}, ...restProps } = props;
return ( return (

View File

@@ -1,3 +1,4 @@
import * as React from 'react';
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';
@@ -23,7 +24,7 @@ const countTranslation = (value: React.ReactNode) => (
</> </>
); );
function AppRow(props: AppRowProps) { function AppRow(props: AppRowProps): React.ReactElement {
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const { name, primaryColor, iconUrl, connectionCount } = props.application; const { name, primaryColor, iconUrl, connectionCount } = props.application;

View File

@@ -11,7 +11,7 @@ export const CardContent = styled(MuiCardContent)(({ theme }) => ({
})); }));
export const Typography = styled(MuiTypography)(({ theme }) => ({ export const Typography = styled(MuiTypography)(() => ({
'&.MuiTypography-h6': { '&.MuiTypography-h6': {
textTransform: 'capitalize', textTransform: 'capitalize',
}, },

View File

@@ -2,10 +2,12 @@ import * as React from 'react';
import { useTheme } from '@mui/material/styles'; import { useTheme } from '@mui/material/styles';
import useMediaQuery from '@mui/material/useMediaQuery'; import useMediaQuery from '@mui/material/useMediaQuery';
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
import type { ButtonProps } from '@mui/material/Button';
import { IconButton } from './style'; import { IconButton } from './style';
export default function ConditionalIconButton(props: any) { // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export default function ConditionalIconButton(props: any): React.ReactElement {
const { icon, ...buttonProps } = props; const { icon, ...buttonProps } = props;
const theme = useTheme(); const theme = useTheme();
const matchSmallScreens = useMediaQuery(theme.breakpoints.down('md'), { noSsr: true }); const matchSmallScreens = useMediaQuery(theme.breakpoints.down('md'), { noSsr: true });
@@ -24,6 +26,6 @@ export default function ConditionalIconButton(props: any) {
} }
return ( return (
<Button {...buttonProps} /> <Button {...(buttonProps as ButtonProps)} />
); );
} }

View File

@@ -1,6 +1,7 @@
import * as React from 'react';
import MuiContainer, { ContainerProps } from '@mui/material/Container'; import MuiContainer, { ContainerProps } from '@mui/material/Container';
export default function Container(props: ContainerProps) { export default function Container(props: ContainerProps): React.ReactElement {
return ( return (
<MuiContainer {...props} /> <MuiContainer {...props} />
); );

View File

@@ -17,7 +17,7 @@ import { Drawer as BaseDrawer } from './style';
const iOS = typeof navigator !== 'undefined' && /iPad|iPhone|iPod/.test(navigator.userAgent); const iOS = typeof navigator !== 'undefined' && /iPad|iPhone|iPod/.test(navigator.userAgent);
export default function Drawer(props: SwipeableDrawerProps) { export default function Drawer(props: SwipeableDrawerProps): React.ReactElement {
const theme = useTheme(); const theme = useTheme();
const matchSmallScreens = useMediaQuery(theme.breakpoints.down('md'), { noSsr: true }); const matchSmallScreens = useMediaQuery(theme.breakpoints.down('md'), { noSsr: true });
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();

View File

@@ -8,7 +8,7 @@ type EditorProps = {
flow: Flow; flow: Flow;
} }
export default function Editor(props: EditorProps) { export default function Editor(props: EditorProps): React.ReactElement {
const [currentStep, setCurrentStep] = React.useState<number | null>(null); const [currentStep, setCurrentStep] = React.useState<number | null>(null);
const { flow } = props; const { flow } = props;

View File

@@ -15,11 +15,7 @@ import useFormatMessage from 'hooks/useFormatMessage';
import { GET_FLOW } from 'graphql/queries/get-flow'; import { GET_FLOW } from 'graphql/queries/get-flow';
import type { Flow } from 'types/flow'; import type { Flow } from 'types/flow';
type EditorLayoutProps = { export default function EditorLayout(): React.ReactElement {
children?: React.ReactNode;
}
export default function EditorLayout(props: EditorLayoutProps) {
const { flowId } = useParams(); const { flowId } = useParams();
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const { data } = useQuery(GET_FLOW, { variables: { id: Number(flowId) }}); const { data } = useQuery(GET_FLOW, { variables: { id: Number(flowId) }});

View File

@@ -13,7 +13,7 @@ type FlowRowProps = {
flow: Flow; flow: Flow;
} }
export default function FlowRow(props: FlowRowProps) { export default function FlowRow(props: FlowRowProps): React.ReactElement {
const { flow } = props; const { flow } = props;
return ( return (

View File

@@ -11,7 +11,7 @@ export const CardContent = styled(MuiCardContent)(({ theme }) => ({
})); }));
export const Typography = styled(MuiTypography)(({ theme }) => ({ export const Typography = styled(MuiTypography)(() => ({
'&.MuiTypography-h6': { '&.MuiTypography-h6': {
textTransform: 'capitalize', textTransform: 'capitalize',
}, },

View File

@@ -19,7 +19,7 @@ type FlowStepProps = {
onClose?: () => void; onClose?: () => void;
} }
export default function FlowStep(props: FlowStepProps) { export default function FlowStep(props: FlowStepProps): React.ReactElement | null {
const { collapsed, index, step } = props; const { collapsed, index, step } = props;
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const { data } = useQuery(GET_APP, { variables: { key: step?.appKey }}) const { data } = useQuery(GET_APP, { variables: { key: step?.appKey }})

View File

@@ -1,4 +1,4 @@
import React from 'react'; import * as React from 'react';
import { FormProvider, useForm, FieldValues, SubmitHandler, UseFormReturn } from 'react-hook-form'; import { FormProvider, useForm, FieldValues, SubmitHandler, UseFormReturn } from 'react-hook-form';
type FormProps = { type FormProps = {
@@ -6,7 +6,7 @@ type FormProps = {
onSubmit: SubmitHandler<FieldValues>; onSubmit: SubmitHandler<FieldValues>;
} }
export default function Form(props: FormProps) { export default function Form(props: FormProps): React.ReactElement {
const { children, onSubmit, ...formProps } = props; const { children, onSubmit, ...formProps } = props;
const methods: UseFormReturn = useForm(); const methods: UseFormReturn = useForm();

View File

@@ -1,7 +1,8 @@
import * as React from 'react';
import Slide, { SlideProps } from '@mui/material/Slide'; import Slide, { SlideProps } from '@mui/material/Slide';
import useScrollTrigger from '@mui/material/useScrollTrigger'; import useScrollTrigger from '@mui/material/useScrollTrigger';
export default function HideOnScroll(props: SlideProps) { export default function HideOnScroll(props: SlideProps): React.ReactElement {
const trigger = useScrollTrigger(); const trigger = useScrollTrigger();
return ( return (

View File

@@ -1,5 +1,6 @@
import type { AppFields } from 'types/app'; import * as React from 'react';
import { useFormContext } from 'react-hook-form'; import { useFormContext } from 'react-hook-form';
import type { AppFields } from 'types/app';
import TextField from 'components/TextField'; import TextField from 'components/TextField';
@@ -8,7 +9,7 @@ type InputCreatorProps = {
schema: AppFields; schema: AppFields;
}; };
export default function InputCreator(props: InputCreatorProps) { export default function InputCreator(props: InputCreatorProps): React.ReactElement {
const { const {
onChange, onChange,
schema, schema,

View File

@@ -5,7 +5,7 @@ type IntlProviderProps = {
children: React.ReactNode; children: React.ReactNode;
}; };
const IntlProvider = ({ children }: IntlProviderProps) => { const IntlProvider = ({ children }: IntlProviderProps): React.ReactElement => {
return ( return (
<BaseIntlProvider locale={navigator.language} defaultLocale="en" messages={englishMessages}> <BaseIntlProvider locale={navigator.language} defaultLocale="en" messages={englishMessages}>
{children} {children}

View File

@@ -1,4 +1,4 @@
import { useState } from 'react'; import * as React from 'react';
import { useTheme } from '@mui/material/styles'; import { useTheme } from '@mui/material/styles';
import useMediaQuery from '@mui/material/useMediaQuery'; import useMediaQuery from '@mui/material/useMediaQuery';
@@ -11,10 +11,10 @@ type LayoutProps = {
children: React.ReactNode; children: React.ReactNode;
} }
export default function Layout({ children }: LayoutProps) { export default function Layout({ children }: LayoutProps): React.ReactElement {
const theme = useTheme(); const theme = useTheme();
const matchSmallScreens = useMediaQuery(theme.breakpoints.down('lg'), { noSsr: true }); const matchSmallScreens = useMediaQuery(theme.breakpoints.down('lg'), { noSsr: true });
const [isDrawerOpen, setDrawerOpen] = useState(!matchSmallScreens); const [isDrawerOpen, setDrawerOpen] = React.useState(!matchSmallScreens);
const openDrawer = () => setDrawerOpen(true); const openDrawer = () => setDrawerOpen(true);
const closeDrawer = () => setDrawerOpen(false); const closeDrawer = () => setDrawerOpen(false);

View File

@@ -12,7 +12,7 @@ type ListItemLinkProps = {
onClick?: (event: React.SyntheticEvent) => void; onClick?: (event: React.SyntheticEvent) => void;
} }
export default function ListItemLink(props: ListItemLinkProps) { export default function ListItemLink(props: ListItemLinkProps): React.ReactElement {
const { icon, primary, to, onClick } = props; const { icon, primary, to, onClick } = props;
const selected = useMatch({ path: to, end: false }); const selected = useMatch({ path: to, end: false });

View File

@@ -12,7 +12,7 @@ type NoResultFoundProps = {
to: string; to: string;
} }
export default function NoResultFound(props: NoResultFoundProps) { export default function NoResultFound(props: NoResultFoundProps): React.ReactElement {
const { text, to } = props; const { text, to } = props;
const ActionAreaLink = React.useMemo( const ActionAreaLink = React.useMemo(

View File

@@ -1,10 +1,11 @@
import * as React from 'react';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
type PageTitleProps = { type PageTitleProps = {
children: React.ReactNode; children: React.ReactNode;
}; };
export default function PageTitle(props: PageTitleProps) { export default function PageTitle(props: PageTitleProps): React.ReactElement {
const { children } = props; const { children } = props;
return ( return (

View File

@@ -1,3 +1,4 @@
import * as React from 'react';
import InputLabel from '@mui/material/InputLabel'; import InputLabel from '@mui/material/InputLabel';
import OutlinedInput from '@mui/material/OutlinedInput'; import OutlinedInput from '@mui/material/OutlinedInput';
import InputAdornment from '@mui/material/InputAdornment'; import InputAdornment from '@mui/material/InputAdornment';
@@ -10,7 +11,7 @@ type SearchInputProps = {
onChange?: (event: React.ChangeEvent) => void; onChange?: (event: React.ChangeEvent) => void;
}; };
export default function SearchInput({ onChange }: SearchInputProps) { export default function SearchInput({ onChange }: SearchInputProps): React.ReactElement {
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
return ( return (

View File

@@ -1,6 +1,7 @@
import * as React from 'react';
import { SnackbarProvider as BaseSnackbarProvider, SnackbarProviderProps } from 'notistack'; import { SnackbarProvider as BaseSnackbarProvider, SnackbarProviderProps } from 'notistack';
const SnackbarProvider = (props: SnackbarProviderProps) => { const SnackbarProvider = (props: SnackbarProviderProps): React.ReactElement => {
return ( return (
<BaseSnackbarProvider <BaseSnackbarProvider
{...props} {...props}

View File

@@ -1,10 +1,12 @@
import * as React from 'react';
interface TabPanelProps { interface TabPanelProps {
children?: React.ReactNode; children?: React.ReactNode;
index: number; index: number;
value: number; value: number;
} }
export default function TabPanel(props: TabPanelProps) { export default function TabPanel(props: TabPanelProps): React.ReactElement {
const { children, value, index, ...other } = props; const { children, value, index, ...other } = props;
return ( return (

View File

@@ -1,4 +1,4 @@
import { useRef } from 'react'; import * as React from 'react';
import { Controller, Control, FieldValues } from 'react-hook-form'; import { Controller, Control, FieldValues } from 'react-hook-form';
import MuiTextField, { TextFieldProps as MuiTextFieldProps } from '@mui/material/TextField'; import MuiTextField, { TextFieldProps as MuiTextFieldProps } from '@mui/material/TextField';
import IconButton from '@mui/material/IconButton'; import IconButton from '@mui/material/IconButton';
@@ -15,7 +15,7 @@ type TextFieldProps = {
readOnly?: boolean; readOnly?: boolean;
} & MuiTextFieldProps; } & MuiTextFieldProps;
const createCopyAdornment = (ref: React.RefObject<HTMLInputElement | null>) => { const createCopyAdornment = (ref: React.RefObject<HTMLInputElement | null>): React.ReactElement => {
return ( return (
<InputAdornment position="end"> <InputAdornment position="end">
<IconButton <IconButton
@@ -28,8 +28,8 @@ const createCopyAdornment = (ref: React.RefObject<HTMLInputElement | null>) => {
); );
} }
export default function TextField(props: TextFieldProps) { export default function TextField(props: TextFieldProps): React.ReactElement {
const inputRef = useRef<HTMLInputElement | null>(null); const inputRef = React.useRef<HTMLInputElement | null>(null);
const { const {
control, control,
required, required,

View File

@@ -1,3 +1,4 @@
import * as React from 'react';
import { ThemeProvider as BaseThemeProvider } from '@mui/material/styles'; import { ThemeProvider as BaseThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline'; import CssBaseline from '@mui/material/CssBaseline';
import theme from 'styles/theme'; import theme from 'styles/theme';
@@ -6,7 +7,7 @@ type ThemeProviderProps = {
children: React.ReactNode; children: React.ReactNode;
}; };
const ThemeProvider = ({ children, ...props }: ThemeProviderProps) => { const ThemeProvider = ({ children, ...props }: ThemeProviderProps): React.ReactElement => {
return ( return (
<BaseThemeProvider theme={theme} {...props}> <BaseThemeProvider theme={theme} {...props}>
<CssBaseline /> <CssBaseline />

View File

@@ -4,21 +4,21 @@ export const EXPLORE = '/explore';
export const APPS = '/apps'; export const APPS = '/apps';
export const NEW_APP_CONNECTION = '/apps/new'; export const NEW_APP_CONNECTION = '/apps/new';
export const APP = (appKey: string) => `/app/${appKey}`; export const APP = (appKey: string): string => `/app/${appKey}`;
export const APP_PATTERN = '/app/:appKey'; export const APP_PATTERN = '/app/:appKey';
export const APP_CONNECTIONS = (appKey: string) => `/app/${appKey}/connections`; export const APP_CONNECTIONS = (appKey: string): string => `/app/${appKey}/connections`;
export const APP_CONNECTIONS_PATTERN = '/app/:appKey/connections'; export const APP_CONNECTIONS_PATTERN = '/app/:appKey/connections';
export const APP_ADD_CONNECTION = (appKey: string) => `/app/${appKey}/connections/add`; export const APP_ADD_CONNECTION = (appKey: string): string => `/app/${appKey}/connections/add`;
export const APP_ADD_CONNECTION_PATTERN = '/app/:appKey/connections/add'; export const APP_ADD_CONNECTION_PATTERN = '/app/:appKey/connections/add';
export const APP_RECONNECT_CONNECTION = (appKey: string, connectionId: string) => `/app/${appKey}/connections/${connectionId}/reconnect`; export const APP_RECONNECT_CONNECTION = (appKey: string, connectionId: string): string => `/app/${appKey}/connections/${connectionId}/reconnect`;
export const APP_RECONNECT_CONNECTION_PATTERN = '/app/:appKey/connections/:connectionId/reconnect'; export const APP_RECONNECT_CONNECTION_PATTERN = '/app/:appKey/connections/:connectionId/reconnect';
export const APP_FLOWS = (appKey: string) => `/app/${appKey}/flows`; export const APP_FLOWS = (appKey: string): string => `/app/${appKey}/flows`;
export const APP_FLOWS_PATTERN = '/app/:appKey/flows'; export const APP_FLOWS_PATTERN = '/app/:appKey/flows';
export const EDITOR = '/editor'; export const EDITOR = '/editor';
export const CREATE_FLOW = '/editor/create'; export const CREATE_FLOW = '/editor/create';
export const FLOW_EDITOR = (flowId: string) => `/editor/${flowId}`; export const FLOW_EDITOR = (flowId: string): string => `/editor/${flowId}`;
export const FLOWS = '/flows'; export const FLOWS = '/flows';
export const FLOW = (flowId: string) => `/flows/${flowId}`; export const FLOW = (flowId: string): string => `/flows/${flowId}`;
export const FLOW_PATTERN = '/flows/:flowId'; export const FLOW_PATTERN = '/flows/:flowId';

View File

@@ -9,7 +9,7 @@ const cache = new InMemoryCache({
mutationType: true, mutationType: true,
fields: { fields: {
createConnection: { createConnection: {
merge(existing, newConnection, { args, readField, cache }) { merge(existing, newConnection, { readField, cache }) {
const appKey = readField('key', newConnection); const appKey = readField('key', newConnection);
const appCacheId = cache.identify({ const appCacheId = cache.identify({
__typename: 'App', __typename: 'App',

View File

@@ -12,7 +12,7 @@ const client = new ApolloClient({
link: createLink({ uri: appConfig.graphqlUrl }) link: createLink({ uri: appConfig.graphqlUrl })
}); });
export function setLink({ onError }: CreateClientOptions) { export function setLink({ onError }: CreateClientOptions): typeof client {
const link = createLink({ uri: appConfig.graphqlUrl, onError }); const link = createLink({ uri: appConfig.graphqlUrl, onError });
client.setLink(link); client.setLink(link);

View File

@@ -1,4 +1,5 @@
import { HttpLink, from } from '@apollo/client'; import { HttpLink, from } from '@apollo/client';
import type { ApolloLink } from '@apollo/client';
import { onError } from '@apollo/client/link/error'; import { onError } from '@apollo/client/link/error';
type CreateLinkOptions = { type CreateLinkOptions = {
@@ -6,9 +7,9 @@ type CreateLinkOptions = {
onError?: (message: string) => void; onError?: (message: string) => void;
}; };
const createHttpLink = (uri: CreateLinkOptions['uri']) => new HttpLink({ uri }); const createHttpLink = (uri: CreateLinkOptions['uri']): ApolloLink => new HttpLink({ uri });
const createErrorLink = (callback: CreateLinkOptions['onError']) => onError(({ graphQLErrors, networkError }) => { const createErrorLink = (callback: CreateLinkOptions['onError']): ApolloLink => onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path }) => { graphQLErrors.forEach(({ message, locations, path }) => {
callback?.(message); callback?.(message);
@@ -24,7 +25,10 @@ const createErrorLink = (callback: CreateLinkOptions['onError']) => onError(({ g
} }
}); });
const createLink = ({ uri, onError = function() {} }: CreateLinkOptions) => { // eslint-disable-next-line @typescript-eslint/no-empty-function
const noop = () => {};
const createLink = ({ uri, onError = noop }: CreateLinkOptions): ApolloLink => {
return from([createErrorLink(onError), createHttpLink(uri)]); return from([createErrorLink(onError), createHttpLink(uri)]);
}; };

View File

@@ -7,7 +7,14 @@ enum AuthenticationSteps {
OpenWithPopup = 'openWithPopup', OpenWithPopup = 'openWithPopup',
} }
const processMutation = async (step: any, variables: any) => { type Step = {
name: string;
variables: Record<string, unknown>;
process: (step: any, variables: Record<string, unknown>) => Promise<any>;
type: AuthenticationSteps.Mutation | AuthenticationSteps.OpenWithPopup;
};
const processMutation = async (step: Step, variables: Record<string, unknown>) => {
const mutation = MUTATIONS[step.name]; const mutation = MUTATIONS[step.name];
const mutationResponse = await apolloClient.mutate({ mutation, variables }); const mutationResponse = await apolloClient.mutate({ mutation, variables });
const responseData = mutationResponse.data[step.name]; const responseData = mutationResponse.data[step.name];
@@ -31,8 +38,8 @@ function getObjectOfEntries(iterator: any) {
return result; return result;
} }
const processOpenWithPopup = (step: any, variables: any) => { const processOpenWithPopup = (step: Step, variables: Record<string, string>) => {
return new Promise((resolve, reject) => { return new Promise((resolve) => {
const windowFeatures = 'toolbar=no, menubar=no, width=600, height=700, top=100, left=100'; const windowFeatures = 'toolbar=no, menubar=no, width=600, height=700, top=100, left=100';
const url = variables.url; const url = variables.url;
@@ -55,16 +62,10 @@ const processOpenWithPopup = (step: any, variables: any) => {
}); });
}; };
export const processStep = (step: any, variables: any) => { export const processStep = async (step: Step, variables: Record<string, string>): Promise<any> => {
return new Promise(async (resolve, reject) => { if (step.type === AuthenticationSteps.Mutation) {
let response; return processMutation(step, variables);
} else if (step.type === AuthenticationSteps.OpenWithPopup) {
if (step.type === AuthenticationSteps.Mutation) { return processOpenWithPopup(step, variables);
response = await processMutation(step, variables); }
} else if (step.type === AuthenticationSteps.OpenWithPopup) {
response = await processOpenWithPopup(step, variables);
}
resolve(response);
});
}; };

View File

@@ -2,12 +2,23 @@ import template from 'lodash.template';
const interpolate = /{([\s\S]+?)}/g; const interpolate = /{([\s\S]+?)}/g;
type VARIABLES = { type Variables = {
[key: string]: any [key: string]: any
} }
const computeAuthStepVariables = (variableSchema: any, aggregatedData: any) => { type VariableSchema = {
const variables: VARIABLES = {}; properties: VariableSchema[];
name: string;
type: 'string' | 'integer';
value: string;
}
type AggregatedData = {
[key: string]: Record<string, unknown> | string;
}
const computeAuthStepVariables = (variableSchema: VariableSchema[], aggregatedData: AggregatedData): Variables => {
const variables: Variables = {};
for (const variable of variableSchema) { for (const variable of variableSchema) {
if (variable.properties) { if (variable.properties) {

View File

@@ -1,4 +1,5 @@
import copy from 'clipboard-copy'; import copy from 'clipboard-copy';
export default function copyInputValue(element: HTMLInputElement) {
export default function copyInputValue(element: HTMLInputElement): void {
copy(element.value); copy(element.value);
}; };

View File

@@ -4,7 +4,7 @@ type Values = {
[key: string]: any, [key: string]: any,
} }
export default function useFormatMessage() { export default function useFormatMessage(): (id: string, values?: Values) => string {
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
return (id: string, values: Values = {}) => formatMessage({ id }, values); return (id: string, values: Values = {}) => formatMessage({ id }, values);

View File

@@ -27,7 +27,7 @@ type ApplicationParams = {
connectionId?: string; connectionId?: string;
}; };
const ReconnectConnection = (props: any) => { const ReconnectConnection = (props: any): React.ReactElement => {
const { application, onClose } = props; const { application, onClose } = props;
const { connectionId } = useParams() as ApplicationParams; const { connectionId } = useParams() as ApplicationParams;
@@ -40,7 +40,7 @@ const ReconnectConnection = (props: any) => {
); );
} }
export default function Application() { export default function Application(): React.ReactElement {
const theme = useTheme(); const theme = useTheme();
const matchSmallScreens = useMediaQuery(theme.breakpoints.down('md'), { noSsr: true }); const matchSmallScreens = useMediaQuery(theme.breakpoints.down('md'), { noSsr: true });
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
@@ -155,7 +155,7 @@ export default function Application() {
</Box> </Box>
<Routes> <Routes>
<Route path={`${URLS.FLOWS}/*`} element={<AppFlows appKey={appKey} />} /> <Route path={`${URLS.FLOWS}/*`} element={<AppFlows />} />
<Route path={`${URLS.CONNECTIONS}/*`} element={<AppConnections appKey={appKey} />} /> <Route path={`${URLS.CONNECTIONS}/*`} element={<AppConnections appKey={appKey} />} />

View File

@@ -17,7 +17,7 @@ import { GET_CONNECTED_APPS } from 'graphql/queries/get-connected-apps';
import * as URLS from 'config/urls'; import * as URLS from 'config/urls';
import type { App } from 'types/app'; import type { App } from 'types/app';
export default function Applications() { export default function Applications(): React.ReactElement {
const navigate = useNavigate(); const navigate = useNavigate();
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const [appName, setAppName] = React.useState(null); const [appName, setAppName] = React.useState(null);

View File

@@ -10,7 +10,7 @@ import { CREATE_FLOW } from 'graphql/mutations/create-flow';
import Box from '@mui/material/Box'; import Box from '@mui/material/Box';
export default function CreateFlow() { export default function CreateFlow(): React.ReactElement {
const navigate = useNavigate(); const navigate = useNavigate();
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const [createFlow] = useMutation(CREATE_FLOW); const [createFlow] = useMutation(CREATE_FLOW);

View File

@@ -1,6 +1,7 @@
import * as React from 'react';
import EditorLayout from 'components/EditorLayout'; import EditorLayout from 'components/EditorLayout';
export default function FlowEditor() { export default function FlowEditor(): React.ReactElement {
return ( return (
<EditorLayout /> <EditorLayout />
) )

View File

@@ -3,7 +3,7 @@ import { Routes, Route } from 'react-router-dom';
import CreateFlowPage from './create'; import CreateFlowPage from './create';
import EditorPage from './index'; import EditorPage from './index';
export default function EditorRoutes() { export default function EditorRoutes(): React.ReactElement {
return ( return (
<Routes> <Routes>
<Route path="/create" element={<CreateFlowPage />} /> <Route path="/create" element={<CreateFlowPage />} />

View File

@@ -1,7 +1,8 @@
import * as React from 'react';
import Box from '@mui/material/Box'; import Box from '@mui/material/Box';
import Container from 'components/Container'; import Container from 'components/Container';
export default function Explore() { export default function Explore(): React.ReactElement {
return ( return (
<Box sx={{ py: 3 }}> <Box sx={{ py: 3 }}>
<Container> <Container>

View File

@@ -1,32 +1,15 @@
import * as React from 'react'; import * as React from 'react';
import { useQuery } from '@apollo/client'; import { useParams, } from 'react-router-dom';
import { Link, Route, Navigate, Routes, useParams, useMatch, useNavigate } from 'react-router-dom';
import type { LinkProps } from 'react-router-dom';
import { useTheme } from '@mui/material/styles';
import useMediaQuery from '@mui/material/useMediaQuery';
import Box from '@mui/material/Box'; import Box from '@mui/material/Box';
import Grid from '@mui/material/Grid'; import Grid from '@mui/material/Grid';
import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab';
import AddIcon from '@mui/icons-material/Add';
import useFormatMessage from 'hooks/useFormatMessage';
import { GET_APP } from 'graphql/queries/get-app';
import * as URLS from 'config/urls';
import ConditionalIconButton from 'components/ConditionalIconButton';
import AppConnections from 'components/AppConnections';
import AppFlows from 'components/AppFlows';
import AddAppConnection from 'components/AddAppConnection';
import AppIcon from 'components/AppIcon';
import Container from 'components/Container'; import Container from 'components/Container';
import PageTitle from 'components/PageTitle';
type ApplicationParams = { type ApplicationParams = {
flowId: string; flowId: string;
}; };
export default function Flow() { export default function Flow(): React.ReactElement {
const { flowId } = useParams() as ApplicationParams; const { flowId } = useParams() as ApplicationParams;
return ( return (

View File

@@ -1,5 +1,5 @@
import * as React from 'react'; import * as React from 'react';
import { Link, Routes, Route, useNavigate } from 'react-router-dom'; import { Link } from 'react-router-dom';
import type { LinkProps } from 'react-router-dom'; import type { LinkProps } from 'react-router-dom';
import { useQuery } from '@apollo/client'; import { useQuery } from '@apollo/client';
import Box from '@mui/material/Box'; import Box from '@mui/material/Box';
@@ -16,7 +16,7 @@ import { GET_FLOWS } from 'graphql/queries/get-flows';
import * as URLS from 'config/urls'; import * as URLS from 'config/urls';
import type { Flow } from 'types/flow'; import type { Flow } from 'types/flow';
export default function Flows() { export default function Flows(): React.ReactElement {
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const [flowName, setFlowName] = React.useState(''); const [flowName, setFlowName] = React.useState('');
const { data } = useQuery(GET_FLOWS); const { data } = useQuery(GET_FLOWS);

View File

@@ -1,6 +1,6 @@
import { ReportHandler } from 'web-vitals'; import { ReportHandler } from 'web-vitals';
const reportWebVitals = (onPerfEntry?: ReportHandler) => { const reportWebVitals = (onPerfEntry?: ReportHandler): void => {
if (onPerfEntry && onPerfEntry instanceof Function) { if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry); getCLS(onPerfEntry);

View File

@@ -6,6 +6,7 @@ export enum StepType {
export type Step = { export type Step = {
id: string; id: string;
key: string; key: string;
name: string;
appKey: string; appKey: string;
type: StepType; type: StepType;
connectionId: number; connectionId: number;

3411
yarn.lock

File diff suppressed because it is too large Load Diff