Merge pull request #1537 from automatisch/web/types
chore: Use types from the web package
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import type { IApp, IField, IJSONObject } from '@automatisch/types';
|
import type { IApp, IField, IJSONObject } from 'types';
|
||||||
import LoadingButton from '@mui/lab/LoadingButton';
|
import LoadingButton from '@mui/lab/LoadingButton';
|
||||||
import Alert from '@mui/material/Alert';
|
import Alert from '@mui/material/Alert';
|
||||||
import Dialog from '@mui/material/Dialog';
|
import Dialog from '@mui/material/Dialog';
|
||||||
|
@@ -19,7 +19,7 @@ import InputLabel from '@mui/material/InputLabel';
|
|||||||
import OutlinedInput from '@mui/material/OutlinedInput';
|
import OutlinedInput from '@mui/material/OutlinedInput';
|
||||||
import FormControl from '@mui/material/FormControl';
|
import FormControl from '@mui/material/FormControl';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import type { IApp } from '@automatisch/types';
|
import type { IApp } from 'types';
|
||||||
|
|
||||||
import * as URLS from 'config/urls';
|
import * as URLS from 'config/urls';
|
||||||
import AppIcon from 'components/AppIcon';
|
import AppIcon from 'components/AppIcon';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { IField } from '@automatisch/types';
|
import type { IField } from 'types';
|
||||||
import LoadingButton from '@mui/lab/LoadingButton';
|
import LoadingButton from '@mui/lab/LoadingButton';
|
||||||
import Alert from '@mui/material/Alert';
|
import Alert from '@mui/material/Alert';
|
||||||
import Dialog from '@mui/material/Dialog';
|
import Dialog from '@mui/material/Dialog';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import React, { useCallback, useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import type { IApp } from '@automatisch/types';
|
import type { IApp } from 'types';
|
||||||
import { FieldValues, SubmitHandler } from 'react-hook-form';
|
import { FieldValues, SubmitHandler } from 'react-hook-form';
|
||||||
import { useMutation } from '@apollo/client';
|
import { useMutation } from '@apollo/client';
|
||||||
import { CREATE_APP_CONFIG } from 'graphql/mutations/create-app-config';
|
import { CREATE_APP_CONFIG } from 'graphql/mutations/create-app-config';
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import React, { useCallback, useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import type { IApp } from '@automatisch/types';
|
import type { IApp } from 'types';
|
||||||
import { FieldValues, SubmitHandler } from 'react-hook-form';
|
import { FieldValues, SubmitHandler } from 'react-hook-form';
|
||||||
import { useMutation } from '@apollo/client';
|
import { useMutation } from '@apollo/client';
|
||||||
import { UPDATE_APP_AUTH_CLIENT } from 'graphql/mutations/update-app-auth-client';
|
import { UPDATE_APP_AUTH_CLIENT } from 'graphql/mutations/update-app-auth-client';
|
||||||
|
@@ -3,7 +3,7 @@ import { Link } from 'react-router-dom';
|
|||||||
import Menu from '@mui/material/Menu';
|
import Menu from '@mui/material/Menu';
|
||||||
import type { PopoverProps } from '@mui/material/Popover';
|
import type { PopoverProps } from '@mui/material/Popover';
|
||||||
import MenuItem from '@mui/material/MenuItem';
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
import type { IConnection } from '@automatisch/types';
|
import type { IConnection } from 'types';
|
||||||
|
|
||||||
import * as URLS from 'config/urls';
|
import * as URLS from 'config/urls';
|
||||||
import useFormatMessage from 'hooks/useFormatMessage';
|
import useFormatMessage from 'hooks/useFormatMessage';
|
||||||
|
@@ -11,7 +11,7 @@ import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar';
|
|||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import type { IConnection } from '@automatisch/types';
|
import type { IConnection } from 'types';
|
||||||
import ConnectionContextMenu from 'components/AppConnectionContextMenu';
|
import ConnectionContextMenu from 'components/AppConnectionContextMenu';
|
||||||
import { DELETE_CONNECTION } from 'graphql/mutations/delete-connection';
|
import { DELETE_CONNECTION } from 'graphql/mutations/delete-connection';
|
||||||
import { TEST_CONNECTION } from 'graphql/queries/test-connection';
|
import { TEST_CONNECTION } from 'graphql/queries/test-connection';
|
||||||
@@ -83,8 +83,8 @@ function AppConnectionRow(props: AppConnectionRowProps): React.ReactElement {
|
|||||||
enqueueSnackbar(formatMessage('connection.deletedMessage'), {
|
enqueueSnackbar(formatMessage('connection.deletedMessage'), {
|
||||||
variant: 'success',
|
variant: 'success',
|
||||||
SnackbarProps: {
|
SnackbarProps: {
|
||||||
'data-test': 'snackbar-delete-connection-success'
|
'data-test': 'snackbar-delete-connection-success',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
} else if (action.type === 'test') {
|
} else if (action.type === 'test') {
|
||||||
setVerificationVisible(true);
|
setVerificationVisible(true);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
|
|
||||||
import type { IConnection } from '@automatisch/types';
|
import type { IConnection } from 'types';
|
||||||
import { GET_APP_CONNECTIONS } from 'graphql/queries/get-app-connections';
|
import { GET_APP_CONNECTIONS } from 'graphql/queries/get-app-connections';
|
||||||
import AppConnectionRow from 'components/AppConnectionRow';
|
import AppConnectionRow from 'components/AppConnectionRow';
|
||||||
import NoResultFound from 'components/NoResultFound';
|
import NoResultFound from 'components/NoResultFound';
|
||||||
|
@@ -8,7 +8,7 @@ import * as URLS from 'config/urls';
|
|||||||
import AppFlowRow from 'components/FlowRow';
|
import AppFlowRow from 'components/FlowRow';
|
||||||
import NoResultFound from 'components/NoResultFound';
|
import NoResultFound from 'components/NoResultFound';
|
||||||
import useFormatMessage from 'hooks/useFormatMessage';
|
import useFormatMessage from 'hooks/useFormatMessage';
|
||||||
import type { IFlow } from '@automatisch/types';
|
import type { IFlow } from 'types';
|
||||||
|
|
||||||
type AppFlowsProps = {
|
type AppFlowsProps = {
|
||||||
appKey: string;
|
appKey: string;
|
||||||
|
@@ -7,7 +7,7 @@ import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
|
|||||||
|
|
||||||
import useFormatMessage from 'hooks/useFormatMessage';
|
import useFormatMessage from 'hooks/useFormatMessage';
|
||||||
import AppIcon from 'components/AppIcon';
|
import AppIcon from 'components/AppIcon';
|
||||||
import type { IApp } from '@automatisch/types';
|
import type { IApp } from 'types';
|
||||||
|
|
||||||
import { CardContent, Typography } from './style';
|
import { CardContent, Typography } from './style';
|
||||||
|
|
||||||
|
@@ -7,13 +7,7 @@ import ListItem from '@mui/material/ListItem';
|
|||||||
import TextField from '@mui/material/TextField';
|
import TextField from '@mui/material/TextField';
|
||||||
import Autocomplete from '@mui/material/Autocomplete';
|
import Autocomplete from '@mui/material/Autocomplete';
|
||||||
import Chip from '@mui/material/Chip';
|
import Chip from '@mui/material/Chip';
|
||||||
import type {
|
import type { IApp, IStep, ISubstep, ITrigger, IAction } from 'types';
|
||||||
IApp,
|
|
||||||
IStep,
|
|
||||||
ISubstep,
|
|
||||||
ITrigger,
|
|
||||||
IAction,
|
|
||||||
} from '@automatisch/types';
|
|
||||||
|
|
||||||
import useFormatMessage from 'hooks/useFormatMessage';
|
import useFormatMessage from 'hooks/useFormatMessage';
|
||||||
import useApps from 'hooks/useApps';
|
import useApps from 'hooks/useApps';
|
||||||
|
@@ -6,7 +6,7 @@ import ListItem from '@mui/material/ListItem';
|
|||||||
import TextField from '@mui/material/TextField';
|
import TextField from '@mui/material/TextField';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import type { IApp, IConnection, IStep, ISubstep } from '@automatisch/types';
|
import type { IApp, IConnection, IStep, ISubstep } from 'types';
|
||||||
import AddAppConnection from 'components/AddAppConnection';
|
import AddAppConnection from 'components/AddAppConnection';
|
||||||
import AppAuthClientsDialog from 'components/AppAuthClientsDialog/index.ee';
|
import AppAuthClientsDialog from 'components/AppAuthClientsDialog/index.ee';
|
||||||
import FlowSubstepTitle from 'components/FlowSubstepTitle';
|
import FlowSubstepTitle from 'components/FlowSubstepTitle';
|
||||||
|
@@ -1,9 +1,12 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Controller, useFormContext } from 'react-hook-form';
|
import { Controller, useFormContext } from 'react-hook-form';
|
||||||
import FormHelperText from '@mui/material/FormHelperText';
|
import FormHelperText from '@mui/material/FormHelperText';
|
||||||
import Autocomplete, { AutocompleteProps, createFilterOptions } from '@mui/material/Autocomplete';
|
import Autocomplete, {
|
||||||
|
AutocompleteProps,
|
||||||
|
createFilterOptions,
|
||||||
|
} from '@mui/material/Autocomplete';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import type { IFieldDropdownOption } from '@automatisch/types';
|
import type { IFieldDropdownOption } from 'types';
|
||||||
|
|
||||||
interface ControlledAutocompleteProps
|
interface ControlledAutocompleteProps
|
||||||
extends AutocompleteProps<IFieldDropdownOption, boolean, boolean, boolean> {
|
extends AutocompleteProps<IFieldDropdownOption, boolean, boolean, boolean> {
|
||||||
@@ -23,8 +26,8 @@ const filterOptions = createFilterOptions<IFieldDropdownOption>({
|
|||||||
stringify: ({ label, value }) => `
|
stringify: ({ label, value }) => `
|
||||||
${label}
|
${label}
|
||||||
${value}
|
${value}
|
||||||
`
|
`,
|
||||||
})
|
});
|
||||||
|
|
||||||
function ControlledAutocomplete(
|
function ControlledAutocomplete(
|
||||||
props: ControlledAutocompleteProps
|
props: ControlledAutocompleteProps
|
||||||
|
@@ -3,7 +3,7 @@ import Popper from '@mui/material/Popper';
|
|||||||
import Tab from '@mui/material/Tab';
|
import Tab from '@mui/material/Tab';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import type { IFieldDropdownOption } from '@automatisch/types';
|
import type { IFieldDropdownOption } from 'types';
|
||||||
import Suggestions from 'components/PowerInput/Suggestions';
|
import Suggestions from 'components/PowerInput/Suggestions';
|
||||||
import TabPanel from 'components/TabPanel';
|
import TabPanel from 'components/TabPanel';
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import type { IFieldDropdownOption } from '@automatisch/types';
|
import type { IFieldDropdownOption } from 'types';
|
||||||
import ListItemButton from '@mui/material/ListItemButton';
|
import ListItemButton from '@mui/material/ListItemButton';
|
||||||
import ListItemText from '@mui/material/ListItemText';
|
import ListItemText from '@mui/material/ListItemText';
|
||||||
import throttle from 'lodash/throttle';
|
import throttle from 'lodash/throttle';
|
||||||
@@ -13,7 +13,7 @@ import { SearchInputWrapper } from './style';
|
|||||||
interface OptionsProps {
|
interface OptionsProps {
|
||||||
data: readonly IFieldDropdownOption[];
|
data: readonly IFieldDropdownOption[];
|
||||||
onOptionClick: (event: React.MouseEvent, option: any) => void;
|
onOptionClick: (event: React.MouseEvent, option: any) => void;
|
||||||
};
|
}
|
||||||
|
|
||||||
const SHORT_LIST_LENGTH = 4;
|
const SHORT_LIST_LENGTH = 4;
|
||||||
const LIST_ITEM_HEIGHT = 64;
|
const LIST_ITEM_HEIGHT = 64;
|
||||||
@@ -21,9 +21,11 @@ const LIST_ITEM_HEIGHT = 64;
|
|||||||
const computeListHeight = (currentLength: number) => {
|
const computeListHeight = (currentLength: number) => {
|
||||||
const numberOfRenderedItems = Math.min(SHORT_LIST_LENGTH, currentLength);
|
const numberOfRenderedItems = Math.min(SHORT_LIST_LENGTH, currentLength);
|
||||||
return LIST_ITEM_HEIGHT * numberOfRenderedItems;
|
return LIST_ITEM_HEIGHT * numberOfRenderedItems;
|
||||||
}
|
};
|
||||||
|
|
||||||
const renderItemFactory = ({ onOptionClick }: Pick<OptionsProps, 'onOptionClick'>) => (props: ListChildComponentProps) => {
|
const renderItemFactory =
|
||||||
|
({ onOptionClick }: Pick<OptionsProps, 'onOptionClick'>) =>
|
||||||
|
(props: ListChildComponentProps) => {
|
||||||
const { index, style, data } = props;
|
const { index, style, data } = props;
|
||||||
|
|
||||||
const suboption = data[index];
|
const suboption = data[index];
|
||||||
@@ -57,27 +59,30 @@ const renderItemFactory = ({ onOptionClick }: Pick<OptionsProps, 'onOptionClick'
|
|||||||
|
|
||||||
const Options = (props: OptionsProps) => {
|
const Options = (props: OptionsProps) => {
|
||||||
const formatMessage = useFormatMessage();
|
const formatMessage = useFormatMessage();
|
||||||
const {
|
const { data, onOptionClick } = props;
|
||||||
data,
|
const [filteredData, setFilteredData] =
|
||||||
onOptionClick
|
React.useState<readonly IFieldDropdownOption[]>(data);
|
||||||
} = props;
|
|
||||||
const [filteredData, setFilteredData] = React.useState<readonly IFieldDropdownOption[]>(
|
|
||||||
data
|
|
||||||
);
|
|
||||||
|
|
||||||
React.useEffect(function syncOptions() {
|
React.useEffect(
|
||||||
|
function syncOptions() {
|
||||||
setFilteredData((filteredData) => {
|
setFilteredData((filteredData) => {
|
||||||
if (filteredData.length === 0 && filteredData.length !== data.length) {
|
if (filteredData.length === 0 && filteredData.length !== data.length) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
return filteredData;
|
return filteredData;
|
||||||
})
|
});
|
||||||
}, [data]);
|
},
|
||||||
|
[data]
|
||||||
|
);
|
||||||
|
|
||||||
const renderItem = React.useMemo(() => renderItemFactory({
|
const renderItem = React.useMemo(
|
||||||
onOptionClick
|
() =>
|
||||||
}), [onOptionClick]);
|
renderItemFactory({
|
||||||
|
onOptionClick,
|
||||||
|
}),
|
||||||
|
[onOptionClick]
|
||||||
|
);
|
||||||
|
|
||||||
const onSearchChange = React.useMemo(
|
const onSearchChange = React.useMemo(
|
||||||
() =>
|
() =>
|
||||||
@@ -89,7 +94,11 @@ const Options = (props: OptionsProps) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newFilteredData = data.filter(option => `${option.label}\n${option.value}`.toLowerCase().includes(search.toLowerCase()));
|
const newFilteredData = data.filter((option) =>
|
||||||
|
`${option.label}\n${option.value}`
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(search.toLowerCase())
|
||||||
|
);
|
||||||
|
|
||||||
setFilteredData(newFilteredData);
|
setFilteredData(newFilteredData);
|
||||||
}, 400),
|
}, 400),
|
||||||
@@ -122,5 +131,4 @@ const Options = (props: OptionsProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default Options;
|
export default Options;
|
||||||
|
@@ -5,7 +5,7 @@ import FormHelperText from '@mui/material/FormHelperText';
|
|||||||
import { AutocompleteProps } from '@mui/material/Autocomplete';
|
import { AutocompleteProps } from '@mui/material/Autocomplete';
|
||||||
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
|
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
|
||||||
import ClearIcon from '@mui/icons-material/Clear';
|
import ClearIcon from '@mui/icons-material/Clear';
|
||||||
import type { IFieldDropdownOption } from '@automatisch/types';
|
import type { IFieldDropdownOption } from 'types';
|
||||||
import { ActionButtonsWrapper } from './style';
|
import { ActionButtonsWrapper } from './style';
|
||||||
|
|
||||||
import ClickAwayListener from '@mui/base/ClickAwayListener';
|
import ClickAwayListener from '@mui/base/ClickAwayListener';
|
||||||
|
@@ -8,7 +8,7 @@ import IconButton from '@mui/material/IconButton';
|
|||||||
import RemoveIcon from '@mui/icons-material/Remove';
|
import RemoveIcon from '@mui/icons-material/Remove';
|
||||||
import AddIcon from '@mui/icons-material/Add';
|
import AddIcon from '@mui/icons-material/Add';
|
||||||
|
|
||||||
import { IFieldDynamic } from '@automatisch/types';
|
import { IFieldDynamic } from 'types';
|
||||||
import InputCreator from 'components/InputCreator';
|
import InputCreator from 'components/InputCreator';
|
||||||
import { EditorContext } from 'contexts/Editor';
|
import { EditorContext } from 'contexts/Editor';
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@ import { useMutation } from '@apollo/client';
|
|||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
import AddIcon from '@mui/icons-material/Add';
|
import AddIcon from '@mui/icons-material/Add';
|
||||||
import type { IFlow, IStep } from '@automatisch/types';
|
import type { IFlow, IStep } from 'types';
|
||||||
|
|
||||||
import { GET_FLOW } from 'graphql/queries/get-flow';
|
import { GET_FLOW } from 'graphql/queries/get-flow';
|
||||||
import { CREATE_STEP } from 'graphql/mutations/create-step';
|
import { CREATE_STEP } from 'graphql/mutations/create-step';
|
||||||
|
@@ -17,7 +17,7 @@ import useFormatMessage from 'hooks/useFormatMessage';
|
|||||||
import { UPDATE_FLOW_STATUS } from 'graphql/mutations/update-flow-status';
|
import { UPDATE_FLOW_STATUS } from 'graphql/mutations/update-flow-status';
|
||||||
import { UPDATE_FLOW } from 'graphql/mutations/update-flow';
|
import { UPDATE_FLOW } from 'graphql/mutations/update-flow';
|
||||||
import { GET_FLOW } from 'graphql/queries/get-flow';
|
import { GET_FLOW } from 'graphql/queries/get-flow';
|
||||||
import type { IFlow } from '@automatisch/types';
|
import type { IFlow } from 'types';
|
||||||
import * as URLS from 'config/urls';
|
import * as URLS from 'config/urls';
|
||||||
|
|
||||||
export default function EditorLayout(): React.ReactElement {
|
export default function EditorLayout(): React.ReactElement {
|
||||||
|
@@ -4,7 +4,7 @@ import Stack from '@mui/material/Stack';
|
|||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import Tooltip from '@mui/material/Tooltip';
|
import Tooltip from '@mui/material/Tooltip';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import type { IExecution } from '@automatisch/types';
|
import type { IExecution } from 'types';
|
||||||
|
|
||||||
import useFormatMessage from 'hooks/useFormatMessage';
|
import useFormatMessage from 'hooks/useFormatMessage';
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ import CardActionArea from '@mui/material/CardActionArea';
|
|||||||
import Chip from '@mui/material/Chip';
|
import Chip from '@mui/material/Chip';
|
||||||
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
|
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import type { IExecution } from '@automatisch/types';
|
import type { IExecution } from 'types';
|
||||||
|
|
||||||
import * as URLS from 'config/urls';
|
import * as URLS from 'config/urls';
|
||||||
import useFormatMessage from 'hooks/useFormatMessage';
|
import useFormatMessage from 'hooks/useFormatMessage';
|
||||||
|
@@ -8,7 +8,7 @@ import Tab from '@mui/material/Tab';
|
|||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import Tooltip from '@mui/material/Tooltip';
|
import Tooltip from '@mui/material/Tooltip';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import type { IApp, IExecutionStep, IStep } from '@automatisch/types';
|
import type { IApp, IExecutionStep, IStep } from 'types';
|
||||||
|
|
||||||
import TabPanel from 'components/TabPanel';
|
import TabPanel from 'components/TabPanel';
|
||||||
import SearchableJSONViewer from 'components/SearchableJSONViewer';
|
import SearchableJSONViewer from 'components/SearchableJSONViewer';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import type { IStep } from '@automatisch/types';
|
import type { IStep } from 'types';
|
||||||
|
|
||||||
import AppIcon from 'components/AppIcon';
|
import AppIcon from 'components/AppIcon';
|
||||||
import IntermediateStepCount from 'components/IntermediateStepCount';
|
import IntermediateStepCount from 'components/IntermediateStepCount';
|
||||||
|
@@ -7,7 +7,7 @@ import Chip from '@mui/material/Chip';
|
|||||||
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
|
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
|
|
||||||
import type { IFlow } from '@automatisch/types';
|
import type { IFlow } from 'types';
|
||||||
import FlowAppIcons from 'components/FlowAppIcons';
|
import FlowAppIcons from 'components/FlowAppIcons';
|
||||||
import FlowContextMenu from 'components/FlowContextMenu';
|
import FlowContextMenu from 'components/FlowContextMenu';
|
||||||
import useFormatMessage from 'hooks/useFormatMessage';
|
import useFormatMessage from 'hooks/useFormatMessage';
|
||||||
|
@@ -14,13 +14,7 @@ import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
|||||||
import { yupResolver } from '@hookform/resolvers/yup';
|
import { yupResolver } from '@hookform/resolvers/yup';
|
||||||
import * as yup from 'yup';
|
import * as yup from 'yup';
|
||||||
import type { BaseSchema } from 'yup';
|
import type { BaseSchema } from 'yup';
|
||||||
import type {
|
import type { IApp, ITrigger, IAction, IStep, ISubstep } from 'types';
|
||||||
IApp,
|
|
||||||
ITrigger,
|
|
||||||
IAction,
|
|
||||||
IStep,
|
|
||||||
ISubstep,
|
|
||||||
} from '@automatisch/types';
|
|
||||||
|
|
||||||
import { EditorContext } from 'contexts/Editor';
|
import { EditorContext } from 'contexts/Editor';
|
||||||
import { StepExecutionsProvider } from 'contexts/StepExecutions';
|
import { StepExecutionsProvider } from 'contexts/StepExecutions';
|
||||||
|
@@ -8,7 +8,7 @@ import Divider from '@mui/material/Divider';
|
|||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
import RemoveIcon from '@mui/icons-material/Remove';
|
import RemoveIcon from '@mui/icons-material/Remove';
|
||||||
import AddIcon from '@mui/icons-material/Add';
|
import AddIcon from '@mui/icons-material/Add';
|
||||||
import type { IField, IFieldText, IFieldDropdown } from '@automatisch/types';
|
import type { IField, IFieldText, IFieldDropdown } from 'types';
|
||||||
|
|
||||||
import useFormatMessage from 'hooks/useFormatMessage';
|
import useFormatMessage from 'hooks/useFormatMessage';
|
||||||
import InputCreator from 'components/InputCreator';
|
import InputCreator from 'components/InputCreator';
|
||||||
@@ -19,7 +19,7 @@ type TGroupItem = {
|
|||||||
operator: string;
|
operator: string;
|
||||||
value: string;
|
value: string;
|
||||||
id: string;
|
id: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
type TGroup = Record<'and', TGroupItem[]>;
|
type TGroup = Record<'and', TGroupItem[]>;
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ const createGroupItem = (): TGroupItem => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const createGroup = (): TGroup => ({
|
const createGroup = (): TGroup => ({
|
||||||
and: [createGroupItem()]
|
and: [createGroupItem()],
|
||||||
});
|
});
|
||||||
|
|
||||||
const operators = [
|
const operators = [
|
||||||
@@ -69,7 +69,9 @@ const operators = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const createStringArgument = (argumentOptions: Omit<IFieldText, 'type' | 'required' | 'variables'>): IField => {
|
const createStringArgument = (
|
||||||
|
argumentOptions: Omit<IFieldText, 'type' | 'required' | 'variables'>
|
||||||
|
): IField => {
|
||||||
return {
|
return {
|
||||||
...argumentOptions,
|
...argumentOptions,
|
||||||
type: 'string',
|
type: 'string',
|
||||||
@@ -78,7 +80,9 @@ const createStringArgument = (argumentOptions: Omit<IFieldText, 'type' | 'requir
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const createDropdownArgument = (argumentOptions: Omit<IFieldDropdown, 'type' | 'required'>): IField => {
|
const createDropdownArgument = (
|
||||||
|
argumentOptions: Omit<IFieldDropdown, 'type' | 'required'>
|
||||||
|
): IField => {
|
||||||
return {
|
return {
|
||||||
...argumentOptions,
|
...argumentOptions,
|
||||||
required: true,
|
required: true,
|
||||||
@@ -91,9 +95,7 @@ type FilterConditionsProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function FilterConditions(props: FilterConditionsProps): React.ReactElement {
|
function FilterConditions(props: FilterConditionsProps): React.ReactElement {
|
||||||
const {
|
const { stepId } = props;
|
||||||
stepId
|
|
||||||
} = props;
|
|
||||||
const formatMessage = useFormatMessage();
|
const formatMessage = useFormatMessage();
|
||||||
const { control, setValue, getValues } = useFormContext();
|
const { control, setValue, getValues } = useFormContext();
|
||||||
const groups = useWatch({ control, name: 'parameters.or' });
|
const groups = useWatch({ control, name: 'parameters.or' });
|
||||||
@@ -110,7 +112,7 @@ function FilterConditions(props: FilterConditionsProps): React.ReactElement {
|
|||||||
const appendGroup = React.useCallback(() => {
|
const appendGroup = React.useCallback(() => {
|
||||||
const values = getValues('parameters.or');
|
const values = getValues('parameters.or');
|
||||||
|
|
||||||
setValue('parameters.or', values.concat(createGroup()))
|
setValue('parameters.or', values.concat(createGroup()));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const appendGroupItem = React.useCallback((index) => {
|
const appendGroupItem = React.useCallback((index) => {
|
||||||
@@ -124,48 +126,89 @@ function FilterConditions(props: FilterConditionsProps): React.ReactElement {
|
|||||||
if (group.length === 1) {
|
if (group.length === 1) {
|
||||||
const groups: TGroup[] = getValues('parameters.or');
|
const groups: TGroup[] = getValues('parameters.or');
|
||||||
|
|
||||||
setValue('parameters.or', groups.filter((group, index) => index !== groupIndex));
|
setValue(
|
||||||
|
'parameters.or',
|
||||||
|
groups.filter((group, index) => index !== groupIndex)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
setValue(`parameters.or.${groupIndex}.and`, group.filter((groupItem, index) => index !== groupItemIndex));
|
setValue(
|
||||||
|
`parameters.or.${groupIndex}.and`,
|
||||||
|
group.filter((groupItem, index) => index !== groupItemIndex)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Stack sx={{ width: "100%" }} direction="column" spacing={2} mt={2}>
|
<Stack sx={{ width: '100%' }} direction="column" spacing={2} mt={2}>
|
||||||
{groups?.map((group: TGroup, groupIndex: number) => (
|
{groups?.map((group: TGroup, groupIndex: number) => (
|
||||||
<>
|
<>
|
||||||
{groupIndex !== 0 && <Divider />}
|
{groupIndex !== 0 && <Divider />}
|
||||||
|
|
||||||
<Typography variant="subtitle2" gutterBottom>
|
<Typography variant="subtitle2" gutterBottom>
|
||||||
{groupIndex === 0 && formatMessage('filterConditions.onlyContinueIf')}
|
{groupIndex === 0 &&
|
||||||
{groupIndex !== 0 && formatMessage('filterConditions.orContinueIf')}
|
formatMessage('filterConditions.onlyContinueIf')}
|
||||||
|
{groupIndex !== 0 &&
|
||||||
|
formatMessage('filterConditions.orContinueIf')}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{group?.and?.map((groupItem: TGroupItem, groupItemIndex: number) => (
|
{group?.and?.map(
|
||||||
|
(groupItem: TGroupItem, groupItemIndex: number) => (
|
||||||
<Stack direction="row" spacing={2} key={`item-${groupItem.id}`}>
|
<Stack direction="row" spacing={2} key={`item-${groupItem.id}`}>
|
||||||
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={{ xs: 2 }} sx={{ display: 'flex', flex: 1 }}>
|
<Stack
|
||||||
<Box sx={{ display: 'flex', flex: '1 0 0px', maxWidth: ['100%', '33%'] }}>
|
direction={{ xs: 'column', sm: 'row' }}
|
||||||
|
spacing={{ xs: 2 }}
|
||||||
|
sx={{ display: 'flex', flex: 1 }}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flex: '1 0 0px',
|
||||||
|
maxWidth: ['100%', '33%'],
|
||||||
|
}}
|
||||||
|
>
|
||||||
<InputCreator
|
<InputCreator
|
||||||
schema={createStringArgument({ key: `or.${groupIndex}.and.${groupItemIndex}.key`, label: 'Choose field' })}
|
schema={createStringArgument({
|
||||||
|
key: `or.${groupIndex}.and.${groupItemIndex}.key`,
|
||||||
|
label: 'Choose field',
|
||||||
|
})}
|
||||||
namePrefix="parameters"
|
namePrefix="parameters"
|
||||||
stepId={stepId}
|
stepId={stepId}
|
||||||
disabled={editorContext.readOnly}
|
disabled={editorContext.readOnly}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box sx={{ display: 'flex', flex: '1 0 0px', maxWidth: ['100%', '33%'] }}>
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flex: '1 0 0px',
|
||||||
|
maxWidth: ['100%', '33%'],
|
||||||
|
}}
|
||||||
|
>
|
||||||
<InputCreator
|
<InputCreator
|
||||||
schema={createDropdownArgument({ key: `or.${groupIndex}.and.${groupItemIndex}.operator`, options: operators, label: 'Choose condition' })}
|
schema={createDropdownArgument({
|
||||||
|
key: `or.${groupIndex}.and.${groupItemIndex}.operator`,
|
||||||
|
options: operators,
|
||||||
|
label: 'Choose condition',
|
||||||
|
})}
|
||||||
namePrefix="parameters"
|
namePrefix="parameters"
|
||||||
stepId={stepId}
|
stepId={stepId}
|
||||||
disabled={editorContext.readOnly}
|
disabled={editorContext.readOnly}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box sx={{ display: 'flex', flex: '1 0 0px', maxWidth: ['100%', '33%'] }}>
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flex: '1 0 0px',
|
||||||
|
maxWidth: ['100%', '33%'],
|
||||||
|
}}
|
||||||
|
>
|
||||||
<InputCreator
|
<InputCreator
|
||||||
schema={createStringArgument({ key: `or.${groupIndex}.and.${groupItemIndex}.value`, label: 'Enter text' })}
|
schema={createStringArgument({
|
||||||
|
key: `or.${groupIndex}.and.${groupItemIndex}.value`,
|
||||||
|
label: 'Enter text',
|
||||||
|
})}
|
||||||
namePrefix="parameters"
|
namePrefix="parameters"
|
||||||
stepId={stepId}
|
stepId={stepId}
|
||||||
disabled={editorContext.readOnly}
|
disabled={editorContext.readOnly}
|
||||||
@@ -182,7 +225,8 @@ function FilterConditions(props: FilterConditionsProps): React.ReactElement {
|
|||||||
<RemoveIcon />
|
<RemoveIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Stack>
|
</Stack>
|
||||||
))}
|
)
|
||||||
|
)}
|
||||||
|
|
||||||
<Stack spacing={1} direction="row">
|
<Stack spacing={1} direction="row">
|
||||||
<IconButton
|
<IconButton
|
||||||
@@ -194,14 +238,16 @@ function FilterConditions(props: FilterConditionsProps): React.ReactElement {
|
|||||||
<AddIcon /> And
|
<AddIcon /> And
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|
||||||
{(groups.length - 1) === groupIndex && <IconButton
|
{groups.length - 1 === groupIndex && (
|
||||||
|
<IconButton
|
||||||
size="small"
|
size="small"
|
||||||
edge="start"
|
edge="start"
|
||||||
onClick={appendGroup}
|
onClick={appendGroup}
|
||||||
sx={{ width: 61, height: 61 }}
|
sx={{ width: 61, height: 61 }}
|
||||||
>
|
>
|
||||||
<AddIcon /> Or
|
<AddIcon /> Or
|
||||||
</IconButton>}
|
</IconButton>
|
||||||
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
|
@@ -4,7 +4,7 @@ import Collapse from '@mui/material/Collapse';
|
|||||||
import ListItem from '@mui/material/ListItem';
|
import ListItem from '@mui/material/ListItem';
|
||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
import Stack from '@mui/material/Stack';
|
import Stack from '@mui/material/Stack';
|
||||||
import type { IStep, ISubstep } from '@automatisch/types';
|
import type { IStep, ISubstep } from 'types';
|
||||||
|
|
||||||
import { EditorContext } from 'contexts/Editor';
|
import { EditorContext } from 'contexts/Editor';
|
||||||
import FlowSubstepTitle from 'components/FlowSubstepTitle';
|
import FlowSubstepTitle from 'components/FlowSubstepTitle';
|
||||||
@@ -54,7 +54,7 @@ function FlowSubstep(props: FlowSubstepProps): React.ReactElement {
|
|||||||
pb: 3,
|
pb: 3,
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
alignItems: 'flex-start',
|
alignItems: 'flex-start',
|
||||||
position: 'relative'
|
position: 'relative',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!!args?.length && (
|
{!!args?.length && (
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import MuiTextField from '@mui/material/TextField';
|
import MuiTextField from '@mui/material/TextField';
|
||||||
import CircularProgress from '@mui/material/CircularProgress';
|
import CircularProgress from '@mui/material/CircularProgress';
|
||||||
import type { IField, IFieldDropdownOption } from '@automatisch/types';
|
import type { IField, IFieldDropdownOption } from 'types';
|
||||||
|
|
||||||
import useDynamicFields from 'hooks/useDynamicFields';
|
import useDynamicFields from 'hooks/useDynamicFields';
|
||||||
import useDynamicData from 'hooks/useDynamicData';
|
import useDynamicData from 'hooks/useDynamicData';
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { JSONTree } from 'react-json-tree';
|
import { JSONTree } from 'react-json-tree';
|
||||||
import type { IJSONObject } from '@automatisch/types';
|
import type { IJSONObject } from 'types';
|
||||||
|
|
||||||
type JSONViewerProps = {
|
type JSONViewerProps = {
|
||||||
data: IJSONObject;
|
data: IJSONObject;
|
||||||
|
@@ -14,7 +14,7 @@ import Typography from '@mui/material/Typography';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useFormContext } from 'react-hook-form';
|
import { useFormContext } from 'react-hook-form';
|
||||||
|
|
||||||
import { IPermissionCatalog } from '@automatisch/types';
|
import { IPermissionCatalog } from 'types';
|
||||||
import ControlledCheckbox from 'components/ControlledCheckbox';
|
import ControlledCheckbox from 'components/ControlledCheckbox';
|
||||||
import useFormatMessage from 'hooks/useFormatMessage';
|
import useFormatMessage from 'hooks/useFormatMessage';
|
||||||
|
|
||||||
@@ -118,7 +118,9 @@ export default function PermissionSettings(props: PermissionSettingsProps) {
|
|||||||
{action.subjects.includes(subject) && (
|
{action.subjects.includes(subject) && (
|
||||||
<ControlledCheckbox
|
<ControlledCheckbox
|
||||||
name={`${fieldPrefix}.${action.key}.conditions.${condition.key}`}
|
name={`${fieldPrefix}.${action.key}.conditions.${condition.key}`}
|
||||||
dataTest={`${condition.key}-${action.key.toLowerCase()}-checkbox`}
|
dataTest={`${
|
||||||
|
condition.key
|
||||||
|
}-${action.key.toLowerCase()}-checkbox`}
|
||||||
defaultValue={defaultChecked}
|
defaultValue={defaultChecked}
|
||||||
disabled={
|
disabled={
|
||||||
getValues(
|
getValues(
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import type { IStep } from '@automatisch/types';
|
import type { IStep } from 'types';
|
||||||
import ExpandLess from '@mui/icons-material/ExpandLess';
|
import ExpandLess from '@mui/icons-material/ExpandLess';
|
||||||
import ExpandMore from '@mui/icons-material/ExpandMore';
|
import ExpandMore from '@mui/icons-material/ExpandMore';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
@@ -20,7 +20,7 @@ type SuggestionsProps = {
|
|||||||
data: {
|
data: {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
output: Record<string, unknown>[]
|
output: Record<string, unknown>[];
|
||||||
}[];
|
}[];
|
||||||
onSuggestionClick: (variable: any) => void;
|
onSuggestionClick: (variable: any) => void;
|
||||||
};
|
};
|
||||||
@@ -31,13 +31,15 @@ const LIST_ITEM_HEIGHT = 64;
|
|||||||
const computeListHeight = (currentLength: number) => {
|
const computeListHeight = (currentLength: number) => {
|
||||||
const numberOfRenderedItems = Math.min(SHORT_LIST_LENGTH, currentLength);
|
const numberOfRenderedItems = Math.min(SHORT_LIST_LENGTH, currentLength);
|
||||||
return LIST_ITEM_HEIGHT * numberOfRenderedItems;
|
return LIST_ITEM_HEIGHT * numberOfRenderedItems;
|
||||||
}
|
};
|
||||||
|
|
||||||
const getPartialArray = (array: any[], length = array.length) => {
|
const getPartialArray = (array: any[], length = array.length) => {
|
||||||
return array.slice(0, length);
|
return array.slice(0, length);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderItemFactory = ({ onSuggestionClick }: Pick<SuggestionsProps, 'onSuggestionClick'>) => (props: ListChildComponentProps) => {
|
const renderItemFactory =
|
||||||
|
({ onSuggestionClick }: Pick<SuggestionsProps, 'onSuggestionClick'>) =>
|
||||||
|
(props: ListChildComponentProps) => {
|
||||||
const { index, style, data } = props;
|
const { index, style, data } = props;
|
||||||
|
|
||||||
const suboption = data[index];
|
const suboption = data[index];
|
||||||
@@ -67,33 +69,35 @@ const renderItemFactory = ({ onSuggestionClick }: Pick<SuggestionsProps, 'onSugg
|
|||||||
/>
|
/>
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const Suggestions = (props: SuggestionsProps) => {
|
const Suggestions = (props: SuggestionsProps) => {
|
||||||
const formatMessage = useFormatMessage();
|
const formatMessage = useFormatMessage();
|
||||||
const {
|
const { data, onSuggestionClick = () => null } = props;
|
||||||
data,
|
|
||||||
onSuggestionClick = () => null
|
|
||||||
} = props;
|
|
||||||
const [current, setCurrent] = React.useState<number | null>(0);
|
const [current, setCurrent] = React.useState<number | null>(0);
|
||||||
const [listLength, setListLength] = React.useState<number>(SHORT_LIST_LENGTH);
|
const [listLength, setListLength] = React.useState<number>(SHORT_LIST_LENGTH);
|
||||||
const [filteredData, setFilteredData] = React.useState<any[]>(
|
const [filteredData, setFilteredData] = React.useState<any[]>(data);
|
||||||
data
|
|
||||||
);
|
|
||||||
|
|
||||||
React.useEffect(function syncOptions() {
|
React.useEffect(
|
||||||
|
function syncOptions() {
|
||||||
setFilteredData((filteredData) => {
|
setFilteredData((filteredData) => {
|
||||||
if (filteredData.length === 0 && filteredData.length !== data.length) {
|
if (filteredData.length === 0 && filteredData.length !== data.length) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
return filteredData;
|
return filteredData;
|
||||||
})
|
});
|
||||||
}, [data]);
|
},
|
||||||
|
[data]
|
||||||
|
);
|
||||||
|
|
||||||
const renderItem = React.useMemo(() => renderItemFactory({
|
const renderItem = React.useMemo(
|
||||||
onSuggestionClick
|
() =>
|
||||||
}), [onSuggestionClick]);
|
renderItemFactory({
|
||||||
|
onSuggestionClick,
|
||||||
|
}),
|
||||||
|
[onSuggestionClick]
|
||||||
|
);
|
||||||
|
|
||||||
const expandList = () => {
|
const expandList = () => {
|
||||||
setListLength(Infinity);
|
setListLength(Infinity);
|
||||||
@@ -122,12 +126,12 @@ const Suggestions = (props: SuggestionsProps) => {
|
|||||||
return {
|
return {
|
||||||
id: stepWithOutput.id,
|
id: stepWithOutput.id,
|
||||||
name: stepWithOutput.name,
|
name: stepWithOutput.name,
|
||||||
output: stepWithOutput.output
|
output: stepWithOutput.output.filter((option) =>
|
||||||
.filter(option => `${option.label}\n${option.sampleValue}`
|
`${option.label}\n${option.sampleValue}`
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(search.toLowerCase())
|
.includes(search.toLowerCase())
|
||||||
)
|
),
|
||||||
}
|
};
|
||||||
})
|
})
|
||||||
.filter((stepWithOutput) => stepWithOutput.output.length);
|
.filter((stepWithOutput) => stepWithOutput.output.length);
|
||||||
|
|
||||||
@@ -161,14 +165,27 @@ const Suggestions = (props: SuggestionsProps) => {
|
|||||||
(current === index ? <ExpandLess /> : <ExpandMore />)}
|
(current === index ? <ExpandLess /> : <ExpandMore />)}
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
|
|
||||||
<Collapse in={current === index || filteredData.length === 1} timeout="auto" unmountOnExit>
|
<Collapse
|
||||||
|
in={current === index || filteredData.length === 1}
|
||||||
|
timeout="auto"
|
||||||
|
unmountOnExit
|
||||||
|
>
|
||||||
<FixedSizeList
|
<FixedSizeList
|
||||||
height={computeListHeight(getPartialArray((option.output as any) || [], listLength).length)}
|
height={computeListHeight(
|
||||||
|
getPartialArray((option.output as any) || [], listLength)
|
||||||
|
.length
|
||||||
|
)}
|
||||||
width="100%"
|
width="100%"
|
||||||
itemSize={LIST_ITEM_HEIGHT}
|
itemSize={LIST_ITEM_HEIGHT}
|
||||||
itemCount={getPartialArray((option.output as any) || [], listLength).length}
|
itemCount={
|
||||||
|
getPartialArray((option.output as any) || [], listLength)
|
||||||
|
.length
|
||||||
|
}
|
||||||
overscanCount={2}
|
overscanCount={2}
|
||||||
itemData={getPartialArray((option.output as any) || [], listLength)}
|
itemData={getPartialArray(
|
||||||
|
(option.output as any) || [],
|
||||||
|
listLength
|
||||||
|
)}
|
||||||
data-test="power-input-suggestion-group"
|
data-test="power-input-suggestion-group"
|
||||||
>
|
>
|
||||||
{renderItem}
|
{renderItem}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import type { IStep } from '@automatisch/types';
|
import type { IStep } from 'types';
|
||||||
|
|
||||||
const joinBy = (delimiter = '.', ...args: string[]) =>
|
const joinBy = (delimiter = '.', ...args: string[]) =>
|
||||||
args.filter(Boolean).join(delimiter);
|
args.filter(Boolean).join(delimiter);
|
||||||
@@ -10,7 +10,12 @@ type TProcessPayload = {
|
|||||||
parentLabel?: string;
|
parentLabel?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const process = ({ data, parentKey, index, parentLabel = '' }: TProcessPayload): any[] => {
|
const process = ({
|
||||||
|
data,
|
||||||
|
parentKey,
|
||||||
|
index,
|
||||||
|
parentLabel = '',
|
||||||
|
}: TProcessPayload): any[] => {
|
||||||
if (typeof data !== 'object') {
|
if (typeof data !== 'object') {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -24,27 +29,19 @@ const process = ({ data, parentKey, index, parentLabel = '' }: TProcessPayload):
|
|||||||
const entries = Object.entries(data);
|
const entries = Object.entries(data);
|
||||||
|
|
||||||
return entries.flatMap(([name, sampleValue]) => {
|
return entries.flatMap(([name, sampleValue]) => {
|
||||||
const label = joinBy(
|
const label = joinBy('.', parentLabel, (index as number)?.toString(), name);
|
||||||
'.',
|
|
||||||
parentLabel,
|
|
||||||
(index as number)?.toString(),
|
|
||||||
name
|
|
||||||
);
|
|
||||||
|
|
||||||
const value = joinBy(
|
const value = joinBy('.', parentKey, (index as number)?.toString(), name);
|
||||||
'.',
|
|
||||||
parentKey,
|
|
||||||
(index as number)?.toString(),
|
|
||||||
name
|
|
||||||
);
|
|
||||||
|
|
||||||
if (Array.isArray(sampleValue)) {
|
if (Array.isArray(sampleValue)) {
|
||||||
return sampleValue.flatMap((item, index) => process({
|
return sampleValue.flatMap((item, index) =>
|
||||||
|
process({
|
||||||
data: item,
|
data: item,
|
||||||
parentKey: value,
|
parentKey: value,
|
||||||
index,
|
index,
|
||||||
parentLabel: label
|
parentLabel: label,
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof sampleValue === 'object' && sampleValue !== null) {
|
if (typeof sampleValue === 'object' && sampleValue !== null) {
|
||||||
@@ -77,7 +74,8 @@ export const processStepWithExecutions = (steps: IStep[]): any[] => {
|
|||||||
.map((step: IStep, index: number) => ({
|
.map((step: IStep, index: number) => ({
|
||||||
id: step.id,
|
id: step.id,
|
||||||
// TODO: replace with step.name once introduced
|
// TODO: replace with step.name once introduced
|
||||||
name: `${index + 1}. ${(step.appKey || '').charAt(0)?.toUpperCase() + step.appKey?.slice(1)
|
name: `${index + 1}. ${
|
||||||
|
(step.appKey || '').charAt(0)?.toUpperCase() + step.appKey?.slice(1)
|
||||||
}`,
|
}`,
|
||||||
output: process({
|
output: process({
|
||||||
data: step.executionSteps?.[0]?.dataOut || {},
|
data: step.executionSteps?.[0]?.dataOut || {},
|
||||||
|
@@ -3,7 +3,7 @@ import throttle from 'lodash/throttle';
|
|||||||
import isEmpty from 'lodash/isEmpty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import { Box, Typography } from '@mui/material';
|
import { Box, Typography } from '@mui/material';
|
||||||
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
import { IJSONObject } from 'types';
|
||||||
import JSONViewer from 'components/JSONViewer';
|
import JSONViewer from 'components/JSONViewer';
|
||||||
import SearchInput from 'components/SearchInput';
|
import SearchInput from 'components/SearchInput';
|
||||||
import useFormatMessage from 'hooks/useFormatMessage';
|
import useFormatMessage from 'hooks/useFormatMessage';
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { Text, Descendant } from 'slate';
|
import { Text, Descendant } from 'slate';
|
||||||
import { withHistory } from 'slate-history';
|
import { withHistory } from 'slate-history';
|
||||||
import { ReactEditor, withReact } from 'slate-react';
|
import { ReactEditor, withReact } from 'slate-react';
|
||||||
import { IFieldDropdownOption } from '@automatisch/types';
|
import { IFieldDropdownOption } from 'types';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
CustomEditor,
|
CustomEditor,
|
||||||
|
@@ -13,7 +13,7 @@ import { EXECUTE_FLOW } from 'graphql/mutations/execute-flow';
|
|||||||
import JSONViewer from 'components/JSONViewer';
|
import JSONViewer from 'components/JSONViewer';
|
||||||
import WebhookUrlInfo from 'components/WebhookUrlInfo';
|
import WebhookUrlInfo from 'components/WebhookUrlInfo';
|
||||||
import FlowSubstepTitle from 'components/FlowSubstepTitle';
|
import FlowSubstepTitle from 'components/FlowSubstepTitle';
|
||||||
import type { IStep, ISubstep } from '@automatisch/types';
|
import type { IStep, ISubstep } from 'types';
|
||||||
|
|
||||||
type TestSubstepProps = {
|
type TestSubstepProps = {
|
||||||
substep: ISubstep;
|
substep: ISubstep;
|
||||||
@@ -62,7 +62,7 @@ function TestSubstep(props: TestSubstepProps): React.ReactElement {
|
|||||||
EXECUTE_FLOW,
|
EXECUTE_FLOW,
|
||||||
{
|
{
|
||||||
refetchQueries: ['GetStepWithTestExecutions'],
|
refetchQueries: ['GetStepWithTestExecutions'],
|
||||||
context: { autoSnackbar: false }
|
context: { autoSnackbar: false },
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const response = data?.executeFlow?.data;
|
const response = data?.executeFlow?.data;
|
||||||
|
@@ -5,7 +5,7 @@ import get from 'lodash/get';
|
|||||||
import set from 'lodash/set';
|
import set from 'lodash/set';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
import { IJSONObject } from 'types';
|
||||||
import useConfig from 'hooks/useConfig';
|
import useConfig from 'hooks/useConfig';
|
||||||
import useAutomatischInfo from 'hooks/useAutomatischInfo';
|
import useAutomatischInfo from 'hooks/useAutomatischInfo';
|
||||||
import { defaultTheme, mationTheme } from 'styles/theme';
|
import { defaultTheme, mationTheme } from 'styles/theme';
|
||||||
|
@@ -11,7 +11,7 @@ import Divider from '@mui/material/Divider';
|
|||||||
import Grid from '@mui/material/Grid';
|
import Grid from '@mui/material/Grid';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
|
|
||||||
import { TBillingCardAction } from '@automatisch/types';
|
import { TBillingCardAction } from 'types';
|
||||||
import TrialOverAlert from 'components/TrialOverAlert/index.ee';
|
import TrialOverAlert from 'components/TrialOverAlert/index.ee';
|
||||||
import SubscriptionCancelledAlert from 'components/SubscriptionCancelledAlert/index.ee';
|
import SubscriptionCancelledAlert from 'components/SubscriptionCancelledAlert/index.ee';
|
||||||
import CheckoutCompletedAlert from 'components/CheckoutCompletedAlert/index.ee';
|
import CheckoutCompletedAlert from 'components/CheckoutCompletedAlert/index.ee';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import type { IStep } from '@automatisch/types';
|
import type { IStep } from 'types';
|
||||||
|
|
||||||
export const StepExecutionsContext = React.createContext<IStep[]>([]);
|
export const StepExecutionsContext = React.createContext<IStep[]>([]);
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import type { IAuthenticationStep, IJSONObject } from '@automatisch/types';
|
import type { IAuthenticationStep, IJSONObject } from 'types';
|
||||||
import apolloClient from 'graphql/client';
|
import apolloClient from 'graphql/client';
|
||||||
import MUTATIONS from 'graphql/mutations';
|
import MUTATIONS from 'graphql/mutations';
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import template from 'lodash/template';
|
import template from 'lodash/template';
|
||||||
import type { IAuthenticationStepField, IJSONObject } from '@automatisch/types';
|
import type { IAuthenticationStepField, IJSONObject } from 'types';
|
||||||
|
|
||||||
const interpolate = /{([\s\S]+?)}/g;
|
const interpolate = /{([\s\S]+?)}/g;
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { IRole, IPermission } from '@automatisch/types';
|
import { IRole, IPermission } from 'types';
|
||||||
|
|
||||||
type ComputeAction = {
|
type ComputeAction = {
|
||||||
conditions: Record<string, boolean>;
|
conditions: Record<string, boolean>;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import template from 'lodash/template';
|
import template from 'lodash/template';
|
||||||
import type { IAuthenticationStepField, IJSONObject } from '@automatisch/types';
|
import type { IAuthenticationStepField, IJSONObject } from 'types';
|
||||||
|
|
||||||
const interpolate = /{([\s\S]+?)}/g;
|
const interpolate = /{([\s\S]+?)}/g;
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { IJSONObject } from '@automatisch/types';
|
import { IJSONObject } from 'types';
|
||||||
import set from 'lodash/set';
|
import set from 'lodash/set';
|
||||||
|
|
||||||
export default function nestObject<T = IJSONObject>(
|
export default function nestObject<T = IJSONObject>(
|
||||||
|
@@ -1,5 +1,9 @@
|
|||||||
import { PureAbility, fieldPatternMatcher, mongoQueryMatcher } from '@casl/ability';
|
import {
|
||||||
import { IUser } from '@automatisch/types';
|
PureAbility,
|
||||||
|
fieldPatternMatcher,
|
||||||
|
mongoQueryMatcher,
|
||||||
|
} from '@casl/ability';
|
||||||
|
import { IUser } from 'types';
|
||||||
|
|
||||||
// Must be kept in sync with `packages/backend/src/helpers/user-ability.ts`!
|
// Must be kept in sync with `packages/backend/src/helpers/user-ability.ts`!
|
||||||
export default function userAbility(user: IUser) {
|
export default function userAbility(user: IUser) {
|
||||||
@@ -9,7 +13,7 @@ export default function userAbility(user: IUser) {
|
|||||||
// We're not using mongo, but our fields, conditions match
|
// We're not using mongo, but our fields, conditions match
|
||||||
const options = {
|
const options = {
|
||||||
conditionsMatcher: mongoQueryMatcher,
|
conditionsMatcher: mongoQueryMatcher,
|
||||||
fieldMatcher: fieldPatternMatcher
|
fieldMatcher: fieldPatternMatcher,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!role || !permissions) {
|
if (!role || !permissions) {
|
||||||
|
@@ -1,22 +1,16 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { IApp } from '@automatisch/types';
|
import { IApp } from 'types';
|
||||||
|
|
||||||
import { GET_APP } from 'graphql/queries/get-app';
|
import { GET_APP } from 'graphql/queries/get-app';
|
||||||
|
|
||||||
type QueryResponse = {
|
type QueryResponse = {
|
||||||
getApp: IApp;
|
getApp: IApp;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default function useApp(key: string) {
|
export default function useApp(key: string) {
|
||||||
const {
|
const { data, loading } = useQuery<QueryResponse>(GET_APP, {
|
||||||
data,
|
variables: { key },
|
||||||
loading
|
});
|
||||||
} = useQuery<QueryResponse>(
|
|
||||||
GET_APP,
|
|
||||||
{
|
|
||||||
variables: { key }
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const app = data?.getApp;
|
const app = data?.getApp;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { useLazyQuery } from '@apollo/client';
|
import { useLazyQuery } from '@apollo/client';
|
||||||
import { AppAuthClient } from '@automatisch/types';
|
import { AppAuthClient } from 'types';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { GET_APP_AUTH_CLIENT } from 'graphql/queries/get-app-auth-client.ee';
|
import { GET_APP_AUTH_CLIENT } from 'graphql/queries/get-app-auth-client.ee';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { useLazyQuery } from '@apollo/client';
|
import { useLazyQuery } from '@apollo/client';
|
||||||
import { AppAuthClient } from '@automatisch/types';
|
import { AppAuthClient } from 'types';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { GET_APP_AUTH_CLIENTS } from 'graphql/queries/get-app-auth-clients.ee';
|
import { GET_APP_AUTH_CLIENTS } from 'graphql/queries/get-app-auth-clients.ee';
|
||||||
|
@@ -1,23 +1,17 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { AppConfig } from '@automatisch/types';
|
import { AppConfig } from 'types';
|
||||||
|
|
||||||
import { GET_APP_CONFIG } from 'graphql/queries/get-app-config.ee';
|
import { GET_APP_CONFIG } from 'graphql/queries/get-app-config.ee';
|
||||||
|
|
||||||
type QueryResponse = {
|
type QueryResponse = {
|
||||||
getAppConfig: AppConfig;
|
getAppConfig: AppConfig;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default function useAppConfig(key: string) {
|
export default function useAppConfig(key: string) {
|
||||||
const {
|
const { data, loading } = useQuery<QueryResponse>(GET_APP_CONFIG, {
|
||||||
data,
|
|
||||||
loading
|
|
||||||
} = useQuery<QueryResponse>(
|
|
||||||
GET_APP_CONFIG,
|
|
||||||
{
|
|
||||||
variables: { key },
|
variables: { key },
|
||||||
context: { autoSnackbar: false }
|
context: { autoSnackbar: false },
|
||||||
}
|
});
|
||||||
);
|
|
||||||
const appConfig = data?.getAppConfig;
|
const appConfig = data?.getAppConfig;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { IApp } from '@automatisch/types';
|
import { IApp } from 'types';
|
||||||
|
|
||||||
import { GET_APPS } from 'graphql/queries/get-apps';
|
import { GET_APPS } from 'graphql/queries/get-apps';
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { IApp } from '@automatisch/types';
|
import { IApp } from 'types';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { processStep } from 'helpers/authenticationSteps';
|
import { processStep } from 'helpers/authenticationSteps';
|
||||||
@@ -10,14 +10,18 @@ type UseAuthenticateAppParams = {
|
|||||||
appAuthClientId?: string;
|
appAuthClientId?: string;
|
||||||
useShared?: boolean;
|
useShared?: boolean;
|
||||||
connectionId?: string;
|
connectionId?: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
type AuthenticatePayload = {
|
type AuthenticatePayload = {
|
||||||
fields?: Record<string, string>;
|
fields?: Record<string, string>;
|
||||||
appAuthClientId?: string;
|
appAuthClientId?: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
function getSteps(auth: IApp['auth'], hasConnection: boolean, useShared: boolean) {
|
function getSteps(
|
||||||
|
auth: IApp['auth'],
|
||||||
|
hasConnection: boolean,
|
||||||
|
useShared: boolean
|
||||||
|
) {
|
||||||
if (hasConnection) {
|
if (hasConnection) {
|
||||||
if (useShared) {
|
if (useShared) {
|
||||||
return auth?.sharedReconnectionSteps;
|
return auth?.sharedReconnectionSteps;
|
||||||
@@ -34,26 +38,17 @@ function getSteps(auth: IApp['auth'], hasConnection: boolean, useShared: boolean
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function useAuthenticateApp(payload: UseAuthenticateAppParams) {
|
export default function useAuthenticateApp(payload: UseAuthenticateAppParams) {
|
||||||
const {
|
const { appKey, appAuthClientId, connectionId, useShared = false } = payload;
|
||||||
appKey,
|
|
||||||
appAuthClientId,
|
|
||||||
connectionId,
|
|
||||||
useShared = false,
|
|
||||||
} = payload;
|
|
||||||
const { app } = useApp(appKey);
|
const { app } = useApp(appKey);
|
||||||
const [
|
const [authenticationInProgress, setAuthenticationInProgress] =
|
||||||
authenticationInProgress,
|
React.useState(false);
|
||||||
setAuthenticationInProgress
|
|
||||||
] = React.useState(false);
|
|
||||||
const steps = getSteps(app?.auth, !!connectionId, useShared);
|
const steps = getSteps(app?.auth, !!connectionId, useShared);
|
||||||
|
|
||||||
const authenticate = React.useMemo(() => {
|
const authenticate = React.useMemo(() => {
|
||||||
if (!steps?.length) return;
|
if (!steps?.length) return;
|
||||||
|
|
||||||
return async function authenticate(payload: AuthenticatePayload = {}) {
|
return async function authenticate(payload: AuthenticatePayload = {}) {
|
||||||
const {
|
const { fields } = payload;
|
||||||
fields,
|
|
||||||
} = payload;
|
|
||||||
setAuthenticationInProgress(true);
|
setAuthenticationInProgress(true);
|
||||||
|
|
||||||
const response: Record<string, any> = {
|
const response: Record<string, any> = {
|
||||||
@@ -62,7 +57,7 @@ export default function useAuthenticateApp(payload: UseAuthenticateAppParams) {
|
|||||||
connection: {
|
connection: {
|
||||||
id: connectionId,
|
id: connectionId,
|
||||||
},
|
},
|
||||||
fields
|
fields,
|
||||||
};
|
};
|
||||||
|
|
||||||
let stepIndex = 0;
|
let stepIndex = 0;
|
||||||
@@ -90,7 +85,7 @@ export default function useAuthenticateApp(payload: UseAuthenticateAppParams) {
|
|||||||
|
|
||||||
setAuthenticationInProgress(false);
|
setAuthenticationInProgress(false);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}, [steps, appKey, appAuthClientId, connectionId]);
|
}, [steps, appKey, appAuthClientId, connectionId]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@@ -2,15 +2,21 @@ import * as React from 'react';
|
|||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { TSubscription } from '@automatisch/types';
|
import { TSubscription } from 'types';
|
||||||
|
|
||||||
import { GET_BILLING_AND_USAGE } from 'graphql/queries/get-billing-and-usage.ee';
|
import { GET_BILLING_AND_USAGE } from 'graphql/queries/get-billing-and-usage.ee';
|
||||||
|
|
||||||
function transform(billingAndUsageData: NonNullable<UseBillingAndUsageDataReturn>) {
|
function transform(
|
||||||
|
billingAndUsageData: NonNullable<UseBillingAndUsageDataReturn>
|
||||||
|
) {
|
||||||
const nextBillDate = billingAndUsageData.subscription.nextBillDate;
|
const nextBillDate = billingAndUsageData.subscription.nextBillDate;
|
||||||
const nextBillDateTitle = nextBillDate.title;
|
const nextBillDateTitle = nextBillDate.title;
|
||||||
const nextBillDateTitleDateObject = DateTime.fromMillis(Number(nextBillDateTitle));
|
const nextBillDateTitleDateObject = DateTime.fromMillis(
|
||||||
const formattedNextBillDateTitle = nextBillDateTitleDateObject.isValid ? nextBillDateTitleDateObject.toFormat('LLL dd, yyyy') : nextBillDateTitle;
|
Number(nextBillDateTitle)
|
||||||
|
);
|
||||||
|
const formattedNextBillDateTitle = nextBillDateTitleDateObject.isValid
|
||||||
|
? nextBillDateTitleDateObject.toFormat('LLL dd, yyyy')
|
||||||
|
: nextBillDateTitle;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...billingAndUsageData,
|
...billingAndUsageData,
|
||||||
@@ -19,8 +25,8 @@ function transform(billingAndUsageData: NonNullable<UseBillingAndUsageDataReturn
|
|||||||
nextBillDate: {
|
nextBillDate: {
|
||||||
...billingAndUsageData.subscription.nextBillDate,
|
...billingAndUsageData.subscription.nextBillDate,
|
||||||
title: formattedNextBillDateTitle,
|
title: formattedNextBillDateTitle,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,27 +34,35 @@ type UseBillingAndUsageDataReturn = {
|
|||||||
subscription: TSubscription;
|
subscription: TSubscription;
|
||||||
usage: {
|
usage: {
|
||||||
task: number;
|
task: number;
|
||||||
}
|
};
|
||||||
} | null;
|
} | null;
|
||||||
|
|
||||||
export default function useBillingAndUsageData(): UseBillingAndUsageDataReturn {
|
export default function useBillingAndUsageData(): UseBillingAndUsageDataReturn {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const state = location.state as { checkoutCompleted: boolean };
|
const state = location.state as { checkoutCompleted: boolean };
|
||||||
const { data, loading, startPolling, stopPolling } = useQuery(GET_BILLING_AND_USAGE);
|
const { data, loading, startPolling, stopPolling } = useQuery(
|
||||||
|
GET_BILLING_AND_USAGE
|
||||||
|
);
|
||||||
const checkoutCompleted = state?.checkoutCompleted;
|
const checkoutCompleted = state?.checkoutCompleted;
|
||||||
const hasSubscription = !!data?.getBillingAndUsage?.subscription?.status;
|
const hasSubscription = !!data?.getBillingAndUsage?.subscription?.status;
|
||||||
|
|
||||||
React.useEffect(function pollDataUntilSubscriptionIsCreated() {
|
React.useEffect(
|
||||||
|
function pollDataUntilSubscriptionIsCreated() {
|
||||||
if (checkoutCompleted && !hasSubscription) {
|
if (checkoutCompleted && !hasSubscription) {
|
||||||
startPolling(1000);
|
startPolling(1000);
|
||||||
}
|
}
|
||||||
}, [checkoutCompleted, hasSubscription, startPolling]);
|
},
|
||||||
|
[checkoutCompleted, hasSubscription, startPolling]
|
||||||
|
);
|
||||||
|
|
||||||
React.useEffect(function stopPollingWhenSubscriptionIsCreated() {
|
React.useEffect(
|
||||||
|
function stopPollingWhenSubscriptionIsCreated() {
|
||||||
if (checkoutCompleted && hasSubscription) {
|
if (checkoutCompleted && hasSubscription) {
|
||||||
stopPolling();
|
stopPolling();
|
||||||
}
|
}
|
||||||
}, [checkoutCompleted, hasSubscription, stopPolling]);
|
},
|
||||||
|
[checkoutCompleted, hasSubscription, stopPolling]
|
||||||
|
);
|
||||||
|
|
||||||
if (loading) return null;
|
if (loading) return null;
|
||||||
|
|
||||||
|
@@ -1,14 +1,16 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { IJSONObject } from '@automatisch/types';
|
import { IJSONObject } from 'types';
|
||||||
|
|
||||||
import { GET_CONFIG } from 'graphql/queries/get-config.ee';
|
import { GET_CONFIG } from 'graphql/queries/get-config.ee';
|
||||||
|
|
||||||
type QueryResponse = {
|
type QueryResponse = {
|
||||||
getConfig: IJSONObject;
|
getConfig: IJSONObject;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default function useConfig(keys?: string[]) {
|
export default function useConfig(keys?: string[]) {
|
||||||
const { data, loading } = useQuery<QueryResponse>(GET_CONFIG, { variables: { keys } });
|
const { data, loading } = useQuery<QueryResponse>(GET_CONFIG, {
|
||||||
|
variables: { keys },
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
config: data?.getConfig,
|
config: data?.getConfig,
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { IUser } from '@automatisch/types';
|
import { IUser } from 'types';
|
||||||
|
|
||||||
import { GET_CURRENT_USER } from 'graphql/queries/get-current-user';
|
import { GET_CURRENT_USER } from 'graphql/queries/get-current-user';
|
||||||
|
|
||||||
|
@@ -4,11 +4,7 @@ import { useFormContext } from 'react-hook-form';
|
|||||||
import set from 'lodash/set';
|
import set from 'lodash/set';
|
||||||
import type { UseFormReturn } from 'react-hook-form';
|
import type { UseFormReturn } from 'react-hook-form';
|
||||||
import isEqual from 'lodash/isEqual';
|
import isEqual from 'lodash/isEqual';
|
||||||
import type {
|
import type { IField, IFieldDropdownSource, IJSONObject } from 'types';
|
||||||
IField,
|
|
||||||
IFieldDropdownSource,
|
|
||||||
IJSONObject,
|
|
||||||
} from '@automatisch/types';
|
|
||||||
|
|
||||||
import { GET_DYNAMIC_DATA } from 'graphql/queries/get-dynamic-data';
|
import { GET_DYNAMIC_DATA } from 'graphql/queries/get-dynamic-data';
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@ import type {
|
|||||||
IField,
|
IField,
|
||||||
IFieldDropdownAdditionalFields,
|
IFieldDropdownAdditionalFields,
|
||||||
IJSONObject,
|
IJSONObject,
|
||||||
} from '@automatisch/types';
|
} from 'types';
|
||||||
|
|
||||||
import { GET_DYNAMIC_FIELDS } from 'graphql/queries/get-dynamic-fields';
|
import { GET_DYNAMIC_FIELDS } from 'graphql/queries/get-dynamic-fields';
|
||||||
|
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { TInvoice } from '@automatisch/types';
|
import { TInvoice } from 'types';
|
||||||
|
|
||||||
import { GET_INVOICES } from 'graphql/queries/get-invoices.ee';
|
import { GET_INVOICES } from 'graphql/queries/get-invoices.ee';
|
||||||
|
|
||||||
type UseInvoicesReturn = {
|
type UseInvoicesReturn = {
|
||||||
invoices: TInvoice[],
|
invoices: TInvoice[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -13,6 +13,6 @@ export default function useInvoices(): UseInvoicesReturn {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
invoices: data?.getInvoices || [],
|
invoices: data?.getInvoices || [],
|
||||||
loading: loading
|
loading: loading,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import type { Notification } from '@automatisch/types';
|
import type { Notification } from 'types';
|
||||||
|
|
||||||
import { GET_NOTIFICATIONS } from 'graphql/queries/get-notifications';
|
import { GET_NOTIFICATIONS } from 'graphql/queries/get-notifications';
|
||||||
|
|
||||||
type UseNotificationsReturn = {
|
type UseNotificationsReturn = {
|
||||||
notifications: Notification[];
|
notifications: Notification[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default function useNotifications(): UseNotificationsReturn {
|
export default function useNotifications(): UseNotificationsReturn {
|
||||||
const { data, loading } = useQuery(GET_NOTIFICATIONS);
|
const { data, loading } = useQuery(GET_NOTIFICATIONS);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
|
|
||||||
import { TPaymentPlan } from '@automatisch/types';
|
import { TPaymentPlan } from 'types';
|
||||||
import { GET_PAYMENT_PLANS } from 'graphql/queries/get-payment-plans.ee';
|
import { GET_PAYMENT_PLANS } from 'graphql/queries/get-payment-plans.ee';
|
||||||
|
|
||||||
type UsePaymentPlansReturn = {
|
type UsePaymentPlansReturn = {
|
||||||
@@ -13,6 +13,6 @@ export default function usePaymentPlans(): UsePaymentPlansReturn {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
plans: data?.getPaymentPlans || [],
|
plans: data?.getPaymentPlans || [],
|
||||||
loading
|
loading,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { IPermissionCatalog } from '@automatisch/types';
|
import { IPermissionCatalog } from 'types';
|
||||||
|
|
||||||
import { GET_PERMISSION_CATALOG } from 'graphql/queries/get-permission-catalog.ee';
|
import { GET_PERMISSION_CATALOG } from 'graphql/queries/get-permission-catalog.ee';
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useLazyQuery } from '@apollo/client';
|
import { useLazyQuery } from '@apollo/client';
|
||||||
import { IRole } from '@automatisch/types';
|
import { IRole } from 'types';
|
||||||
|
|
||||||
import { GET_ROLE } from 'graphql/queries/get-role.ee';
|
import { GET_ROLE } from 'graphql/queries/get-role.ee';
|
||||||
|
|
||||||
|
@@ -1,17 +1,19 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { IRole } from '@automatisch/types';
|
import { IRole } from 'types';
|
||||||
|
|
||||||
import { GET_ROLES } from 'graphql/queries/get-roles.ee';
|
import { GET_ROLES } from 'graphql/queries/get-roles.ee';
|
||||||
|
|
||||||
type QueryResponse = {
|
type QueryResponse = {
|
||||||
getRoles: IRole[];
|
getRoles: IRole[];
|
||||||
}
|
};
|
||||||
|
|
||||||
export default function useRoles() {
|
export default function useRoles() {
|
||||||
const { data, loading } = useQuery<QueryResponse>(GET_ROLES, { context: { autoSnackbar: false } });
|
const { data, loading } = useQuery<QueryResponse>(GET_ROLES, {
|
||||||
|
context: { autoSnackbar: false },
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
roles: data?.getRoles || [],
|
roles: data?.getRoles || [],
|
||||||
loading
|
loading,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { QueryResult, useQuery } from '@apollo/client';
|
import { QueryResult, useQuery } from '@apollo/client';
|
||||||
|
|
||||||
import { TSamlAuthProvider } from '@automatisch/types';
|
import { TSamlAuthProvider } from 'types';
|
||||||
import { GET_SAML_AUTH_PROVIDER } from 'graphql/queries/get-saml-auth-provider';
|
import { GET_SAML_AUTH_PROVIDER } from 'graphql/queries/get-saml-auth-provider';
|
||||||
|
|
||||||
type UseSamlAuthProviderReturn = {
|
type UseSamlAuthProviderReturn = {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useLazyQuery } from '@apollo/client';
|
import { useLazyQuery } from '@apollo/client';
|
||||||
import { TSamlAuthProviderRole } from '@automatisch/types';
|
import { TSamlAuthProviderRole } from 'types';
|
||||||
|
|
||||||
import { GET_SAML_AUTH_PROVIDER_ROLE_MAPPINGS } from 'graphql/queries/get-saml-auth-provider-role-mappings';
|
import { GET_SAML_AUTH_PROVIDER_ROLE_MAPPINGS } from 'graphql/queries/get-saml-auth-provider-role-mappings';
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
|
|
||||||
import { TSamlAuthProvider } from '@automatisch/types';
|
import { TSamlAuthProvider } from 'types';
|
||||||
import { LIST_SAML_AUTH_PROVIDERS } from 'graphql/queries/list-saml-auth-providers.ee';
|
import { LIST_SAML_AUTH_PROVIDERS } from 'graphql/queries/list-saml-auth-providers.ee';
|
||||||
|
|
||||||
type UseSamlAuthProvidersReturn = {
|
type UseSamlAuthProvidersReturn = {
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useLazyQuery } from '@apollo/client';
|
import { useLazyQuery } from '@apollo/client';
|
||||||
import { IUser } from '@automatisch/types';
|
import { IUser } from 'types';
|
||||||
|
|
||||||
import { GET_USER } from 'graphql/queries/get-user';
|
import { GET_USER } from 'graphql/queries/get-user';
|
||||||
|
|
||||||
type QueryResponse = {
|
type QueryResponse = {
|
||||||
getUser: IUser;
|
getUser: IUser;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default function useUser(userId?: string) {
|
export default function useUser(userId?: string) {
|
||||||
const [getUser, { data, loading }] = useLazyQuery<QueryResponse>(GET_USER);
|
const [getUser, { data, loading }] = useLazyQuery<QueryResponse>(GET_USER);
|
||||||
@@ -15,14 +15,14 @@ export default function useUser(userId?: string) {
|
|||||||
if (userId) {
|
if (userId) {
|
||||||
getUser({
|
getUser({
|
||||||
variables: {
|
variables: {
|
||||||
id: userId
|
id: userId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [userId]);
|
}, [userId]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user: data?.getUser,
|
user: data?.getUser,
|
||||||
loading
|
loading,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { IUser } from '@automatisch/types';
|
import { IUser } from 'types';
|
||||||
|
|
||||||
import { GET_USERS } from 'graphql/queries/get-users';
|
import { GET_USERS } from 'graphql/queries/get-users';
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@ import Grid from '@mui/material/Grid';
|
|||||||
import CircularProgress from '@mui/material/CircularProgress';
|
import CircularProgress from '@mui/material/CircularProgress';
|
||||||
import Divider from '@mui/material/Divider';
|
import Divider from '@mui/material/Divider';
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { IApp } from '@automatisch/types';
|
import { IApp } from 'types';
|
||||||
|
|
||||||
import PageTitle from 'components/PageTitle';
|
import PageTitle from 'components/PageTitle';
|
||||||
import Container from 'components/Container';
|
import Container from 'components/Container';
|
||||||
|
@@ -6,7 +6,7 @@ import Grid from '@mui/material/Grid';
|
|||||||
import Divider from '@mui/material/Divider';
|
import Divider from '@mui/material/Divider';
|
||||||
import CircularProgress from '@mui/material/CircularProgress';
|
import CircularProgress from '@mui/material/CircularProgress';
|
||||||
import AddIcon from '@mui/icons-material/Add';
|
import AddIcon from '@mui/icons-material/Add';
|
||||||
import type { IApp } from '@automatisch/types';
|
import type { IApp } from 'types';
|
||||||
|
|
||||||
import Can from 'components/Can';
|
import Can from 'components/Can';
|
||||||
import NoResultFound from 'components/NoResultFound';
|
import NoResultFound from 'components/NoResultFound';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { useMutation } from '@apollo/client';
|
import { useMutation } from '@apollo/client';
|
||||||
import { TSamlAuthProvider, TSamlAuthProviderRole } from '@automatisch/types';
|
import { TSamlAuthProvider, TSamlAuthProviderRole } from 'types';
|
||||||
import LoadingButton from '@mui/lab/LoadingButton';
|
import LoadingButton from '@mui/lab/LoadingButton';
|
||||||
import Divider from '@mui/material/Divider';
|
import Divider from '@mui/material/Divider';
|
||||||
import Stack from '@mui/material/Stack';
|
import Stack from '@mui/material/Stack';
|
||||||
@@ -65,8 +65,8 @@ function RoleMappings({ provider, providerLoading }: RoleMappingsProps) {
|
|||||||
enqueueSnackbar(formatMessage('roleMappingsForm.successfullySaved'), {
|
enqueueSnackbar(formatMessage('roleMappingsForm.successfullySaved'), {
|
||||||
variant: 'success',
|
variant: 'success',
|
||||||
SnackbarProps: {
|
SnackbarProps: {
|
||||||
'data-test': 'snackbar-update-role-mappings-success'
|
'data-test': 'snackbar-update-role-mappings-success',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { useFieldArray, useFormContext } from 'react-hook-form';
|
import { useFieldArray, useFormContext } from 'react-hook-form';
|
||||||
import { IRole } from '@automatisch/types';
|
import { IRole } from 'types';
|
||||||
import MuiTextField from '@mui/material/TextField';
|
import MuiTextField from '@mui/material/TextField';
|
||||||
import Stack from '@mui/material/Stack';
|
import Stack from '@mui/material/Stack';
|
||||||
import DeleteIcon from '@mui/icons-material/Delete';
|
import DeleteIcon from '@mui/icons-material/Delete';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { QueryResult, useMutation } from '@apollo/client';
|
import { QueryResult, useMutation } from '@apollo/client';
|
||||||
import { IRole, TSamlAuthProvider } from '@automatisch/types';
|
import { IRole, TSamlAuthProvider } from 'types';
|
||||||
import LoadingButton from '@mui/lab/LoadingButton';
|
import LoadingButton from '@mui/lab/LoadingButton';
|
||||||
import Stack from '@mui/material/Stack';
|
import Stack from '@mui/material/Stack';
|
||||||
import MuiTextField from '@mui/material/TextField';
|
import MuiTextField from '@mui/material/TextField';
|
||||||
@@ -94,8 +94,8 @@ function SamlConfiguration({
|
|||||||
enqueueSnackbar(formatMessage('authenticationForm.successfullySaved'), {
|
enqueueSnackbar(formatMessage('authenticationForm.successfullySaved'), {
|
||||||
variant: 'success',
|
variant: 'success',
|
||||||
SnackbarProps: {
|
SnackbarProps: {
|
||||||
'data-test': 'snackbar-save-saml-provider-success'
|
'data-test': 'snackbar-save-saml-provider-success',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error('Failed while saving!');
|
throw new Error('Failed while saving!');
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { useMutation } from '@apollo/client';
|
import { useMutation } from '@apollo/client';
|
||||||
import { IRole, IUser } from '@automatisch/types';
|
import { IRole, IUser } from 'types';
|
||||||
import LoadingButton from '@mui/lab/LoadingButton';
|
import LoadingButton from '@mui/lab/LoadingButton';
|
||||||
import Grid from '@mui/material/Grid';
|
import Grid from '@mui/material/Grid';
|
||||||
import Stack from '@mui/material/Stack';
|
import Stack from '@mui/material/Stack';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { useMutation } from '@apollo/client';
|
import { useMutation } from '@apollo/client';
|
||||||
import { IRole, IUser } from '@automatisch/types';
|
import { IRole, IUser } from 'types';
|
||||||
import LoadingButton from '@mui/lab/LoadingButton';
|
import LoadingButton from '@mui/lab/LoadingButton';
|
||||||
import Grid from '@mui/material/Grid';
|
import Grid from '@mui/material/Grid';
|
||||||
import Skeleton from '@mui/material/Skeleton';
|
import Skeleton from '@mui/material/Skeleton';
|
||||||
|
@@ -5,7 +5,7 @@ import Grid from '@mui/material/Grid';
|
|||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import AlertTitle from '@mui/material/AlertTitle';
|
import AlertTitle from '@mui/material/AlertTitle';
|
||||||
import Alert from '@mui/material/Alert';
|
import Alert from '@mui/material/Alert';
|
||||||
import type { IExecutionStep } from '@automatisch/types';
|
import type { IExecutionStep } from 'types';
|
||||||
|
|
||||||
import useFormatMessage from 'hooks/useFormatMessage';
|
import useFormatMessage from 'hooks/useFormatMessage';
|
||||||
import ExecutionHeader from 'components/ExecutionHeader';
|
import ExecutionHeader from 'components/ExecutionHeader';
|
||||||
|
@@ -7,7 +7,7 @@ import CircularProgress from '@mui/material/CircularProgress';
|
|||||||
import Divider from '@mui/material/Divider';
|
import Divider from '@mui/material/Divider';
|
||||||
import Pagination from '@mui/material/Pagination';
|
import Pagination from '@mui/material/Pagination';
|
||||||
import PaginationItem from '@mui/material/PaginationItem';
|
import PaginationItem from '@mui/material/PaginationItem';
|
||||||
import type { IExecution } from '@automatisch/types';
|
import type { IExecution } from 'types';
|
||||||
|
|
||||||
import NoResultFound from 'components/NoResultFound';
|
import NoResultFound from 'components/NoResultFound';
|
||||||
import ExecutionRow from 'components/ExecutionRow';
|
import ExecutionRow from 'components/ExecutionRow';
|
||||||
|
@@ -9,7 +9,7 @@ import CircularProgress from '@mui/material/CircularProgress';
|
|||||||
import Divider from '@mui/material/Divider';
|
import Divider from '@mui/material/Divider';
|
||||||
import Pagination from '@mui/material/Pagination';
|
import Pagination from '@mui/material/Pagination';
|
||||||
import PaginationItem from '@mui/material/PaginationItem';
|
import PaginationItem from '@mui/material/PaginationItem';
|
||||||
import type { IFlow } from '@automatisch/types';
|
import type { IFlow } from 'types';
|
||||||
|
|
||||||
import Can from 'components/Can';
|
import Can from 'components/Can';
|
||||||
import FlowRow from 'components/FlowRow';
|
import FlowRow from 'components/FlowRow';
|
||||||
|
493
packages/web/src/types/index.d.ts
vendored
Normal file
493
packages/web/src/types/index.d.ts
vendored
Normal file
@@ -0,0 +1,493 @@
|
|||||||
|
import type { AxiosInstance, AxiosRequestConfig } from 'axios';
|
||||||
|
export type IHttpClient = AxiosInstance;
|
||||||
|
import type { Request } from 'express';
|
||||||
|
|
||||||
|
// Type definitions for automatisch
|
||||||
|
|
||||||
|
export type IJSONValue =
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null
|
||||||
|
| IJSONObject
|
||||||
|
| IJSONArray;
|
||||||
|
export type IJSONArray = Array<IJSONValue>;
|
||||||
|
export interface IJSONObject {
|
||||||
|
[x: string]: IJSONValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IConnection {
|
||||||
|
id: string;
|
||||||
|
key: string;
|
||||||
|
data: string;
|
||||||
|
formattedData?: IJSONObject;
|
||||||
|
userId: string;
|
||||||
|
verified: boolean;
|
||||||
|
count?: number;
|
||||||
|
flowCount?: number;
|
||||||
|
appData?: IApp;
|
||||||
|
createdAt: string;
|
||||||
|
reconnectable?: boolean;
|
||||||
|
appAuthClientId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IExecutionStep {
|
||||||
|
id: string;
|
||||||
|
executionId: string;
|
||||||
|
stepId: IStep['id'];
|
||||||
|
step: IStep;
|
||||||
|
dataIn: IJSONObject;
|
||||||
|
dataOut: IJSONObject;
|
||||||
|
errorDetails: IJSONObject;
|
||||||
|
status: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IExecution {
|
||||||
|
id: string;
|
||||||
|
flowId: string;
|
||||||
|
flow: IFlow;
|
||||||
|
testRun: boolean;
|
||||||
|
status: 'success' | 'failure';
|
||||||
|
executionSteps: IExecutionStep[];
|
||||||
|
updatedAt: string | Date;
|
||||||
|
createdAt: string | Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IStep {
|
||||||
|
id: string;
|
||||||
|
name?: string;
|
||||||
|
flowId: string;
|
||||||
|
key?: string;
|
||||||
|
appKey?: string;
|
||||||
|
iconUrl: string;
|
||||||
|
webhookUrl?: string;
|
||||||
|
type: 'action' | 'trigger';
|
||||||
|
connectionId?: string;
|
||||||
|
status: string;
|
||||||
|
position: number;
|
||||||
|
parameters: IJSONObject;
|
||||||
|
connection?: Partial<IConnection>;
|
||||||
|
flow: IFlow;
|
||||||
|
executionSteps: IExecutionStep[];
|
||||||
|
// FIXME: remove this property once execution steps are properly exposed via queries
|
||||||
|
output?: IJSONObject;
|
||||||
|
appData?: IApp;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IFlow {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
userId: string;
|
||||||
|
active: boolean;
|
||||||
|
status: 'paused' | 'published' | 'draft';
|
||||||
|
steps: IStep[];
|
||||||
|
createdAt: string | Date;
|
||||||
|
updatedAt: string | Date;
|
||||||
|
remoteWebhookId: string;
|
||||||
|
lastInternalId: () => Promise<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUser {
|
||||||
|
id: string;
|
||||||
|
fullName: string;
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
connections: IConnection[];
|
||||||
|
flows: IFlow[];
|
||||||
|
steps: IStep[];
|
||||||
|
role: IRole;
|
||||||
|
permissions: IPermission[];
|
||||||
|
createdAt: string | Date;
|
||||||
|
updatedAt: string | Date;
|
||||||
|
trialExpiryDate: string | Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRole {
|
||||||
|
id: string;
|
||||||
|
key: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
isAdmin: boolean;
|
||||||
|
permissions: IPermission[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPermission {
|
||||||
|
id: string;
|
||||||
|
action: string;
|
||||||
|
subject: string;
|
||||||
|
conditions: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPermissionCatalog {
|
||||||
|
actions: { label: string; key: string; subjects: string[] }[];
|
||||||
|
subjects: { label: string; key: string }[];
|
||||||
|
conditions: { label: string; key: string }[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IConfig {
|
||||||
|
id: string;
|
||||||
|
key: string;
|
||||||
|
value: IJSONObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IFieldDropdown {
|
||||||
|
key: string;
|
||||||
|
label: string;
|
||||||
|
type: 'dropdown';
|
||||||
|
required: boolean;
|
||||||
|
readOnly?: boolean;
|
||||||
|
value?: string | boolean;
|
||||||
|
placeholder?: string | null;
|
||||||
|
description?: string;
|
||||||
|
docUrl?: string;
|
||||||
|
clickToCopy?: boolean;
|
||||||
|
variables?: boolean;
|
||||||
|
dependsOn?: string[];
|
||||||
|
options?: IFieldDropdownOption[];
|
||||||
|
source?: IFieldDropdownSource;
|
||||||
|
additionalFields?: IFieldDropdownAdditionalFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IFieldDropdownSource {
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
arguments: {
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
export interface IFieldDropdownAdditionalFields {
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
arguments: {
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IFieldDropdownOption {
|
||||||
|
label: string;
|
||||||
|
value: boolean | string | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IFieldText {
|
||||||
|
key: string;
|
||||||
|
label: string;
|
||||||
|
type: 'string';
|
||||||
|
required?: boolean;
|
||||||
|
readOnly?: boolean;
|
||||||
|
value?: string;
|
||||||
|
placeholder?: string | null;
|
||||||
|
description?: string;
|
||||||
|
docUrl?: string;
|
||||||
|
clickToCopy?: boolean;
|
||||||
|
variables?: boolean;
|
||||||
|
dependsOn?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IFieldDynamic {
|
||||||
|
key: string;
|
||||||
|
label: string;
|
||||||
|
type: 'dynamic';
|
||||||
|
required?: boolean;
|
||||||
|
readOnly?: boolean;
|
||||||
|
description?: string;
|
||||||
|
value?: Record<string, unknown>[];
|
||||||
|
fields: (IFieldDropdown | IFieldText)[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IField = IFieldDropdown | IFieldText | IFieldDynamic;
|
||||||
|
|
||||||
|
export interface IAuthenticationStepField {
|
||||||
|
name: string;
|
||||||
|
value: string | null;
|
||||||
|
properties?: {
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAuthenticationStep {
|
||||||
|
type: 'mutation' | 'openWithPopup';
|
||||||
|
name: string;
|
||||||
|
arguments: IAuthenticationStepField[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApp {
|
||||||
|
name: string;
|
||||||
|
key: string;
|
||||||
|
iconUrl: string;
|
||||||
|
docUrl?: string;
|
||||||
|
authDocUrl: string;
|
||||||
|
primaryColor: string;
|
||||||
|
supportsConnections: boolean;
|
||||||
|
apiBaseUrl: string;
|
||||||
|
baseUrl: string;
|
||||||
|
auth?: IAuth;
|
||||||
|
connectionCount?: number;
|
||||||
|
flowCount?: number;
|
||||||
|
beforeRequest?: TBeforeRequest[];
|
||||||
|
dynamicData?: IDynamicData;
|
||||||
|
dynamicFields?: IDynamicFields;
|
||||||
|
triggers?: ITrigger[];
|
||||||
|
actions?: IAction[];
|
||||||
|
connections?: IConnection[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TBeforeRequest = {
|
||||||
|
($: IGlobalVariable, requestConfig: AxiosRequestConfig): AxiosRequestConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface IDynamicData {
|
||||||
|
[index: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDynamicFields {
|
||||||
|
[index: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAuth {
|
||||||
|
generateAuthUrl?($: IGlobalVariable): Promise<void>;
|
||||||
|
verifyCredentials?($: IGlobalVariable): Promise<void>;
|
||||||
|
isStillVerified?($: IGlobalVariable): Promise<boolean>;
|
||||||
|
refreshToken?($: IGlobalVariable): Promise<void>;
|
||||||
|
verifyWebhook?($: IGlobalVariable): Promise<boolean>;
|
||||||
|
isRefreshTokenRequested?: boolean;
|
||||||
|
fields?: IField[];
|
||||||
|
authenticationSteps?: IAuthenticationStep[];
|
||||||
|
reconnectionSteps?: IAuthenticationStep[];
|
||||||
|
sharedAuthenticationSteps?: IAuthenticationStep[];
|
||||||
|
sharedReconnectionSteps?: IAuthenticationStep[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITriggerOutput {
|
||||||
|
data: ITriggerItem[];
|
||||||
|
error?: IJSONObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITriggerItem {
|
||||||
|
raw: IJSONObject;
|
||||||
|
meta: {
|
||||||
|
internalId: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IBaseTrigger {
|
||||||
|
name: string;
|
||||||
|
key: string;
|
||||||
|
type?: 'webhook' | 'polling';
|
||||||
|
showWebhookUrl?: boolean;
|
||||||
|
pollInterval?: number;
|
||||||
|
description: string;
|
||||||
|
useSingletonWebhook?: boolean;
|
||||||
|
singletonWebhookRefValueParameter?: string;
|
||||||
|
getInterval?(parameters: IStep['parameters']): string;
|
||||||
|
run?($: IGlobalVariable): Promise<void>;
|
||||||
|
testRun?($: IGlobalVariable): Promise<void>;
|
||||||
|
registerHook?($: IGlobalVariable): Promise<void>;
|
||||||
|
unregisterHook?($: IGlobalVariable): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRawTrigger extends IBaseTrigger {
|
||||||
|
arguments?: IField[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITrigger extends IBaseTrigger {
|
||||||
|
substeps?: ISubstep[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IActionOutput {
|
||||||
|
data: IActionItem;
|
||||||
|
error?: IJSONObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IActionItem {
|
||||||
|
raw: IJSONObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IBaseAction {
|
||||||
|
name: string;
|
||||||
|
key: string;
|
||||||
|
description: string;
|
||||||
|
run?($: IGlobalVariable): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRawAction extends IBaseAction {
|
||||||
|
arguments?: IField[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAction extends IBaseAction {
|
||||||
|
substeps?: ISubstep[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAuthentication {
|
||||||
|
client: unknown;
|
||||||
|
verifyCredentials(): Promise<IJSONObject>;
|
||||||
|
isStillVerified(): Promise<boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISubstep {
|
||||||
|
key: string;
|
||||||
|
name: string;
|
||||||
|
arguments?: IField[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IHttpClientParams = {
|
||||||
|
$: IGlobalVariable;
|
||||||
|
baseURL?: string;
|
||||||
|
beforeRequest?: TBeforeRequest[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type IGlobalVariable = {
|
||||||
|
auth: {
|
||||||
|
set: (args: IJSONObject) => Promise<null>;
|
||||||
|
data: IJSONObject;
|
||||||
|
};
|
||||||
|
app?: IApp;
|
||||||
|
http?: IHttpClient;
|
||||||
|
request?: IRequest;
|
||||||
|
flow?: {
|
||||||
|
id: string;
|
||||||
|
lastInternalId: string;
|
||||||
|
isAlreadyProcessed?: (internalId: string) => boolean;
|
||||||
|
remoteWebhookId?: string;
|
||||||
|
setRemoteWebhookId?: (remoteWebhookId: string) => Promise<void>;
|
||||||
|
};
|
||||||
|
step?: {
|
||||||
|
id: string;
|
||||||
|
appKey: string;
|
||||||
|
parameters: IJSONObject;
|
||||||
|
};
|
||||||
|
nextStep?: {
|
||||||
|
id: string;
|
||||||
|
appKey: string;
|
||||||
|
parameters: IJSONObject;
|
||||||
|
};
|
||||||
|
execution?: {
|
||||||
|
id: string;
|
||||||
|
testRun: boolean;
|
||||||
|
exit: () => void;
|
||||||
|
};
|
||||||
|
getLastExecutionStep?: () => Promise<IExecutionStep>;
|
||||||
|
webhookUrl?: string;
|
||||||
|
singletonWebhookUrl?: string;
|
||||||
|
triggerOutput?: ITriggerOutput;
|
||||||
|
actionOutput?: IActionOutput;
|
||||||
|
pushTriggerItem?: (triggerItem: ITriggerItem) => void;
|
||||||
|
setActionItem?: (actionItem: IActionItem) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TPaymentPlan = {
|
||||||
|
price: string;
|
||||||
|
name: string;
|
||||||
|
limit: string;
|
||||||
|
productId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TSubscription = {
|
||||||
|
status: string;
|
||||||
|
monthlyQuota: {
|
||||||
|
title: string;
|
||||||
|
action: BillingCardAction;
|
||||||
|
};
|
||||||
|
nextBillDate: {
|
||||||
|
title: string;
|
||||||
|
action: BillingCardAction;
|
||||||
|
};
|
||||||
|
nextBillAmount: {
|
||||||
|
title: string;
|
||||||
|
action: BillingCardAction;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type TBillingCardAction = TBillingTextCardAction | TBillingLinkCardAction;
|
||||||
|
|
||||||
|
type TBillingTextCardAction = {
|
||||||
|
type: 'text';
|
||||||
|
text: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TBillingLinkCardAction = {
|
||||||
|
type: 'link';
|
||||||
|
text: string;
|
||||||
|
src: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TInvoice = {
|
||||||
|
id: number;
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
payout_date: string;
|
||||||
|
receipt_url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TSamlAuthProvider = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
certificate: string;
|
||||||
|
signatureAlgorithm: 'sha1' | 'sha256' | 'sha512';
|
||||||
|
issuer: string;
|
||||||
|
entryPoint: string;
|
||||||
|
firstnameAttributeName: string;
|
||||||
|
surnameAttributeName: string;
|
||||||
|
emailAttributeName: string;
|
||||||
|
roleAttributeName: string;
|
||||||
|
defaultRoleId: string;
|
||||||
|
active: boolean;
|
||||||
|
loginUrl: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TSamlAuthProviderRole = {
|
||||||
|
id: string;
|
||||||
|
samlAuthProviderId: string;
|
||||||
|
roleId: string;
|
||||||
|
remoteRoleName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type AppConfig = {
|
||||||
|
id: string;
|
||||||
|
key: string;
|
||||||
|
allowCustomConnection: boolean;
|
||||||
|
canConnect: boolean;
|
||||||
|
canCustomConnect: boolean;
|
||||||
|
shared: boolean;
|
||||||
|
disabled: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type AppAuthClient = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
appConfigId: string;
|
||||||
|
authDefaults: string;
|
||||||
|
formattedAuthDefaults: IJSONObject;
|
||||||
|
active: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Notification = {
|
||||||
|
name: string;
|
||||||
|
createdAt: string;
|
||||||
|
documentationUrl: string;
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
declare module 'axios' {
|
||||||
|
interface AxiosResponse {
|
||||||
|
httpError?: IJSONObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AxiosRequestConfig {
|
||||||
|
additionalProperties?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ref: https://github.com/axios/axios/issues/5095
|
||||||
|
interface AxiosInstance {
|
||||||
|
create(config?: CreateAxiosDefaults): AxiosInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRequest extends Request {
|
||||||
|
rawBody?: Buffer;
|
||||||
|
currentUser?: IUser;
|
||||||
|
}
|
Reference in New Issue
Block a user