chore: suit eslint rules
This commit is contained in:
@@ -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';
|
||||||
|
@@ -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';
|
||||||
|
|
||||||
|
@@ -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();
|
||||||
|
|
||||||
|
@@ -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';
|
||||||
|
@@ -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;
|
||||||
|
@@ -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';
|
||||||
|
@@ -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});
|
||||||
|
@@ -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'
|
||||||
|
@@ -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',
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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({
|
||||||
|
@@ -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',
|
||||||
|
@@ -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'
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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();
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const cli = require('..');
|
|
||||||
|
|
||||||
describe('cli', () => {
|
|
||||||
it('needs tests');
|
|
||||||
});
|
|
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
|
@@ -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 (
|
||||||
|
@@ -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) => {
|
||||||
|
@@ -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 });
|
||||||
|
|
||||||
|
@@ -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();
|
||||||
|
|
||||||
|
@@ -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,
|
||||||
|
@@ -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',
|
||||||
}));
|
}));
|
||||||
|
@@ -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 } });
|
||||||
|
@@ -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 (
|
||||||
|
@@ -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%',
|
||||||
|
@@ -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 || [];
|
||||||
|
|
||||||
|
@@ -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 (
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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',
|
||||||
},
|
},
|
||||||
|
@@ -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)} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -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} />
|
||||||
);
|
);
|
||||||
|
@@ -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();
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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) }});
|
||||||
|
@@ -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 (
|
||||||
|
@@ -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',
|
||||||
},
|
},
|
||||||
|
@@ -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 }})
|
||||||
|
@@ -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();
|
||||||
|
|
||||||
|
@@ -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 (
|
||||||
|
@@ -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,
|
||||||
|
@@ -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}
|
||||||
|
@@ -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);
|
||||||
|
@@ -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 });
|
||||||
|
|
||||||
|
@@ -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(
|
||||||
|
@@ -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 (
|
||||||
|
@@ -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 (
|
||||||
|
@@ -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}
|
||||||
|
@@ -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 (
|
||||||
|
@@ -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,
|
||||||
|
@@ -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 />
|
||||||
|
@@ -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';
|
||||||
|
@@ -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',
|
||||||
|
@@ -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);
|
||||||
|
@@ -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)]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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);
|
||||||
};
|
};
|
||||||
|
@@ -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);
|
||||||
|
@@ -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} />} />
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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 />
|
||||||
)
|
)
|
||||||
|
@@ -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 />} />
|
||||||
|
@@ -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>
|
||||||
|
@@ -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 (
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user