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 Alert from '@mui/material/Alert';
|
||||
import Dialog from '@mui/material/Dialog';
|
||||
|
@@ -19,7 +19,7 @@ import InputLabel from '@mui/material/InputLabel';
|
||||
import OutlinedInput from '@mui/material/OutlinedInput';
|
||||
import FormControl from '@mui/material/FormControl';
|
||||
import Box from '@mui/material/Box';
|
||||
import type { IApp } from '@automatisch/types';
|
||||
import type { IApp } from 'types';
|
||||
|
||||
import * as URLS from 'config/urls';
|
||||
import AppIcon from 'components/AppIcon';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import type { IField } from '@automatisch/types';
|
||||
import type { IField } from 'types';
|
||||
import LoadingButton from '@mui/lab/LoadingButton';
|
||||
import Alert from '@mui/material/Alert';
|
||||
import Dialog from '@mui/material/Dialog';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
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 { useMutation } from '@apollo/client';
|
||||
import { CREATE_APP_CONFIG } from 'graphql/mutations/create-app-config';
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
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 { useMutation } from '@apollo/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 type { PopoverProps } from '@mui/material/Popover';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import type { IConnection } from '@automatisch/types';
|
||||
import type { IConnection } from 'types';
|
||||
|
||||
import * as URLS from 'config/urls';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
|
@@ -11,7 +11,7 @@ import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar';
|
||||
import { DateTime } from 'luxon';
|
||||
import * as React from 'react';
|
||||
|
||||
import type { IConnection } from '@automatisch/types';
|
||||
import type { IConnection } from 'types';
|
||||
import ConnectionContextMenu from 'components/AppConnectionContextMenu';
|
||||
import { DELETE_CONNECTION } from 'graphql/mutations/delete-connection';
|
||||
import { TEST_CONNECTION } from 'graphql/queries/test-connection';
|
||||
@@ -83,8 +83,8 @@ function AppConnectionRow(props: AppConnectionRowProps): React.ReactElement {
|
||||
enqueueSnackbar(formatMessage('connection.deletedMessage'), {
|
||||
variant: 'success',
|
||||
SnackbarProps: {
|
||||
'data-test': 'snackbar-delete-connection-success'
|
||||
}
|
||||
'data-test': 'snackbar-delete-connection-success',
|
||||
},
|
||||
});
|
||||
} else if (action.type === 'test') {
|
||||
setVerificationVisible(true);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
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 AppConnectionRow from 'components/AppConnectionRow';
|
||||
import NoResultFound from 'components/NoResultFound';
|
||||
|
@@ -8,7 +8,7 @@ import * as URLS from 'config/urls';
|
||||
import AppFlowRow from 'components/FlowRow';
|
||||
import NoResultFound from 'components/NoResultFound';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
import type { IFlow } from '@automatisch/types';
|
||||
import type { IFlow } from 'types';
|
||||
|
||||
type AppFlowsProps = {
|
||||
appKey: string;
|
||||
|
@@ -7,7 +7,7 @@ import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
|
||||
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
import AppIcon from 'components/AppIcon';
|
||||
import type { IApp } from '@automatisch/types';
|
||||
import type { IApp } from 'types';
|
||||
|
||||
import { CardContent, Typography } from './style';
|
||||
|
||||
|
@@ -7,13 +7,7 @@ import ListItem from '@mui/material/ListItem';
|
||||
import TextField from '@mui/material/TextField';
|
||||
import Autocomplete from '@mui/material/Autocomplete';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import type {
|
||||
IApp,
|
||||
IStep,
|
||||
ISubstep,
|
||||
ITrigger,
|
||||
IAction,
|
||||
} from '@automatisch/types';
|
||||
import type { IApp, IStep, ISubstep, ITrigger, IAction } from 'types';
|
||||
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
import useApps from 'hooks/useApps';
|
||||
|
@@ -6,7 +6,7 @@ import ListItem from '@mui/material/ListItem';
|
||||
import TextField from '@mui/material/TextField';
|
||||
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 AppAuthClientsDialog from 'components/AppAuthClientsDialog/index.ee';
|
||||
import FlowSubstepTitle from 'components/FlowSubstepTitle';
|
||||
|
@@ -1,9 +1,12 @@
|
||||
import * as React from 'react';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
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 type { IFieldDropdownOption } from '@automatisch/types';
|
||||
import type { IFieldDropdownOption } from 'types';
|
||||
|
||||
interface ControlledAutocompleteProps
|
||||
extends AutocompleteProps<IFieldDropdownOption, boolean, boolean, boolean> {
|
||||
@@ -23,8 +26,8 @@ const filterOptions = createFilterOptions<IFieldDropdownOption>({
|
||||
stringify: ({ label, value }) => `
|
||||
${label}
|
||||
${value}
|
||||
`
|
||||
})
|
||||
`,
|
||||
});
|
||||
|
||||
function ControlledAutocomplete(
|
||||
props: ControlledAutocompleteProps
|
||||
|
@@ -3,7 +3,7 @@ import Popper from '@mui/material/Popper';
|
||||
import Tab from '@mui/material/Tab';
|
||||
import * as React from 'react';
|
||||
|
||||
import type { IFieldDropdownOption } from '@automatisch/types';
|
||||
import type { IFieldDropdownOption } from 'types';
|
||||
import Suggestions from 'components/PowerInput/Suggestions';
|
||||
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 ListItemText from '@mui/material/ListItemText';
|
||||
import throttle from 'lodash/throttle';
|
||||
@@ -13,7 +13,7 @@ import { SearchInputWrapper } from './style';
|
||||
interface OptionsProps {
|
||||
data: readonly IFieldDropdownOption[];
|
||||
onOptionClick: (event: React.MouseEvent, option: any) => void;
|
||||
};
|
||||
}
|
||||
|
||||
const SHORT_LIST_LENGTH = 4;
|
||||
const LIST_ITEM_HEIGHT = 64;
|
||||
@@ -21,80 +21,89 @@ const LIST_ITEM_HEIGHT = 64;
|
||||
const computeListHeight = (currentLength: number) => {
|
||||
const numberOfRenderedItems = Math.min(SHORT_LIST_LENGTH, currentLength);
|
||||
return LIST_ITEM_HEIGHT * numberOfRenderedItems;
|
||||
}
|
||||
|
||||
const renderItemFactory = ({ onOptionClick }: Pick<OptionsProps, 'onOptionClick'>) => (props: ListChildComponentProps) => {
|
||||
const { index, style, data } = props;
|
||||
|
||||
const suboption = data[index];
|
||||
|
||||
return (
|
||||
<ListItemButton
|
||||
sx={{ pl: 4 }}
|
||||
divider
|
||||
onClick={(event) => onOptionClick(event, suboption)}
|
||||
data-test="power-input-suggestion-item"
|
||||
key={index}
|
||||
style={style}
|
||||
>
|
||||
<ListItemText
|
||||
primary={suboption.label}
|
||||
primaryTypographyProps={{
|
||||
variant: 'subtitle1',
|
||||
title: 'Property name',
|
||||
sx: { fontWeight: 700 },
|
||||
}}
|
||||
secondary={suboption.value}
|
||||
secondaryTypographyProps={{
|
||||
variant: 'subtitle2',
|
||||
title: 'Sample value',
|
||||
noWrap: true,
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
);
|
||||
};
|
||||
|
||||
const renderItemFactory =
|
||||
({ onOptionClick }: Pick<OptionsProps, 'onOptionClick'>) =>
|
||||
(props: ListChildComponentProps) => {
|
||||
const { index, style, data } = props;
|
||||
|
||||
const suboption = data[index];
|
||||
|
||||
return (
|
||||
<ListItemButton
|
||||
sx={{ pl: 4 }}
|
||||
divider
|
||||
onClick={(event) => onOptionClick(event, suboption)}
|
||||
data-test="power-input-suggestion-item"
|
||||
key={index}
|
||||
style={style}
|
||||
>
|
||||
<ListItemText
|
||||
primary={suboption.label}
|
||||
primaryTypographyProps={{
|
||||
variant: 'subtitle1',
|
||||
title: 'Property name',
|
||||
sx: { fontWeight: 700 },
|
||||
}}
|
||||
secondary={suboption.value}
|
||||
secondaryTypographyProps={{
|
||||
variant: 'subtitle2',
|
||||
title: 'Sample value',
|
||||
noWrap: true,
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
);
|
||||
};
|
||||
|
||||
const Options = (props: OptionsProps) => {
|
||||
const formatMessage = useFormatMessage();
|
||||
const {
|
||||
data,
|
||||
onOptionClick
|
||||
} = props;
|
||||
const [filteredData, setFilteredData] = React.useState<readonly IFieldDropdownOption[]>(
|
||||
data
|
||||
const { data, onOptionClick } = props;
|
||||
const [filteredData, setFilteredData] =
|
||||
React.useState<readonly IFieldDropdownOption[]>(data);
|
||||
|
||||
React.useEffect(
|
||||
function syncOptions() {
|
||||
setFilteredData((filteredData) => {
|
||||
if (filteredData.length === 0 && filteredData.length !== data.length) {
|
||||
return data;
|
||||
}
|
||||
|
||||
return filteredData;
|
||||
});
|
||||
},
|
||||
[data]
|
||||
);
|
||||
|
||||
React.useEffect(function syncOptions() {
|
||||
setFilteredData((filteredData) => {
|
||||
if (filteredData.length === 0 && filteredData.length !== data.length) {
|
||||
return data;
|
||||
}
|
||||
|
||||
return filteredData;
|
||||
})
|
||||
}, [data]);
|
||||
|
||||
const renderItem = React.useMemo(() => renderItemFactory({
|
||||
onOptionClick
|
||||
}), [onOptionClick]);
|
||||
const renderItem = React.useMemo(
|
||||
() =>
|
||||
renderItemFactory({
|
||||
onOptionClick,
|
||||
}),
|
||||
[onOptionClick]
|
||||
);
|
||||
|
||||
const onSearchChange = React.useMemo(
|
||||
() =>
|
||||
throttle((event: React.ChangeEvent) => {
|
||||
const search = (event.target as HTMLInputElement).value.toLowerCase();
|
||||
() =>
|
||||
throttle((event: React.ChangeEvent) => {
|
||||
const search = (event.target as HTMLInputElement).value.toLowerCase();
|
||||
|
||||
if (!search) {
|
||||
setFilteredData(data);
|
||||
return;
|
||||
}
|
||||
if (!search) {
|
||||
setFilteredData(data);
|
||||
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);
|
||||
}, 400),
|
||||
[data]
|
||||
);
|
||||
setFilteredData(newFilteredData);
|
||||
}, 400),
|
||||
[data]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -122,5 +131,4 @@ const Options = (props: OptionsProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default Options;
|
||||
|
@@ -5,7 +5,7 @@ import FormHelperText from '@mui/material/FormHelperText';
|
||||
import { AutocompleteProps } from '@mui/material/Autocomplete';
|
||||
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
|
||||
import ClearIcon from '@mui/icons-material/Clear';
|
||||
import type { IFieldDropdownOption } from '@automatisch/types';
|
||||
import type { IFieldDropdownOption } from 'types';
|
||||
import { ActionButtonsWrapper } from './style';
|
||||
|
||||
import ClickAwayListener from '@mui/base/ClickAwayListener';
|
||||
|
@@ -8,7 +8,7 @@ import IconButton from '@mui/material/IconButton';
|
||||
import RemoveIcon from '@mui/icons-material/Remove';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
|
||||
import { IFieldDynamic } from '@automatisch/types';
|
||||
import { IFieldDynamic } from 'types';
|
||||
import InputCreator from 'components/InputCreator';
|
||||
import { EditorContext } from 'contexts/Editor';
|
||||
|
||||
|
@@ -3,7 +3,7 @@ import { useMutation } from '@apollo/client';
|
||||
import Box from '@mui/material/Box';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
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 { 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 } from 'graphql/mutations/update-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';
|
||||
|
||||
export default function EditorLayout(): React.ReactElement {
|
||||
|
@@ -4,7 +4,7 @@ import Stack from '@mui/material/Stack';
|
||||
import Box from '@mui/material/Box';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import type { IExecution } from '@automatisch/types';
|
||||
import type { IExecution } from 'types';
|
||||
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
|
||||
|
@@ -5,7 +5,7 @@ import CardActionArea from '@mui/material/CardActionArea';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
|
||||
import { DateTime } from 'luxon';
|
||||
import type { IExecution } from '@automatisch/types';
|
||||
import type { IExecution } from 'types';
|
||||
|
||||
import * as URLS from 'config/urls';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
|
@@ -8,7 +8,7 @@ import Tab from '@mui/material/Tab';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
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 SearchableJSONViewer from 'components/SearchableJSONViewer';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import type { IStep } from '@automatisch/types';
|
||||
import type { IStep } from 'types';
|
||||
|
||||
import AppIcon from 'components/AppIcon';
|
||||
import IntermediateStepCount from 'components/IntermediateStepCount';
|
||||
|
@@ -7,7 +7,7 @@ import Chip from '@mui/material/Chip';
|
||||
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import type { IFlow } from '@automatisch/types';
|
||||
import type { IFlow } from 'types';
|
||||
import FlowAppIcons from 'components/FlowAppIcons';
|
||||
import FlowContextMenu from 'components/FlowContextMenu';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
|
@@ -14,13 +14,7 @@ import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import * as yup from 'yup';
|
||||
import type { BaseSchema } from 'yup';
|
||||
import type {
|
||||
IApp,
|
||||
ITrigger,
|
||||
IAction,
|
||||
IStep,
|
||||
ISubstep,
|
||||
} from '@automatisch/types';
|
||||
import type { IApp, ITrigger, IAction, IStep, ISubstep } from 'types';
|
||||
|
||||
import { EditorContext } from 'contexts/Editor';
|
||||
import { StepExecutionsProvider } from 'contexts/StepExecutions';
|
||||
|
@@ -8,7 +8,7 @@ import Divider from '@mui/material/Divider';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import RemoveIcon from '@mui/icons-material/Remove';
|
||||
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 InputCreator from 'components/InputCreator';
|
||||
@@ -19,7 +19,7 @@ type TGroupItem = {
|
||||
operator: string;
|
||||
value: string;
|
||||
id: string;
|
||||
}
|
||||
};
|
||||
|
||||
type TGroup = Record<'and', TGroupItem[]>;
|
||||
|
||||
@@ -31,7 +31,7 @@ const createGroupItem = (): TGroupItem => ({
|
||||
});
|
||||
|
||||
const createGroup = (): TGroup => ({
|
||||
and: [createGroupItem()]
|
||||
and: [createGroupItem()],
|
||||
});
|
||||
|
||||
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 {
|
||||
...argumentOptions,
|
||||
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 {
|
||||
...argumentOptions,
|
||||
required: true,
|
||||
@@ -91,9 +95,7 @@ type FilterConditionsProps = {
|
||||
};
|
||||
|
||||
function FilterConditions(props: FilterConditionsProps): React.ReactElement {
|
||||
const {
|
||||
stepId
|
||||
} = props;
|
||||
const { stepId } = props;
|
||||
const formatMessage = useFormatMessage();
|
||||
const { control, setValue, getValues } = useFormContext();
|
||||
const groups = useWatch({ control, name: 'parameters.or' });
|
||||
@@ -110,7 +112,7 @@ function FilterConditions(props: FilterConditionsProps): React.ReactElement {
|
||||
const appendGroup = React.useCallback(() => {
|
||||
const values = getValues('parameters.or');
|
||||
|
||||
setValue('parameters.or', values.concat(createGroup()))
|
||||
setValue('parameters.or', values.concat(createGroup()));
|
||||
}, []);
|
||||
|
||||
const appendGroupItem = React.useCallback((index) => {
|
||||
@@ -124,65 +126,107 @@ function FilterConditions(props: FilterConditionsProps): React.ReactElement {
|
||||
if (group.length === 1) {
|
||||
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 {
|
||||
setValue(`parameters.or.${groupIndex}.and`, group.filter((groupItem, index) => index !== groupItemIndex));
|
||||
setValue(
|
||||
`parameters.or.${groupIndex}.and`,
|
||||
group.filter((groupItem, index) => index !== groupItemIndex)
|
||||
);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<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) => (
|
||||
<>
|
||||
{groupIndex !== 0 && <Divider />}
|
||||
|
||||
<Typography variant="subtitle2" gutterBottom>
|
||||
{groupIndex === 0 && formatMessage('filterConditions.onlyContinueIf')}
|
||||
{groupIndex !== 0 && formatMessage('filterConditions.orContinueIf')}
|
||||
{groupIndex === 0 &&
|
||||
formatMessage('filterConditions.onlyContinueIf')}
|
||||
{groupIndex !== 0 &&
|
||||
formatMessage('filterConditions.orContinueIf')}
|
||||
</Typography>
|
||||
|
||||
{group?.and?.map((groupItem: TGroupItem, groupItemIndex: number) => (
|
||||
<Stack direction="row" spacing={2} key={`item-${groupItem.id}`}>
|
||||
<Stack 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
|
||||
schema={createStringArgument({ key: `or.${groupIndex}.and.${groupItemIndex}.key`, label: 'Choose field' })}
|
||||
namePrefix="parameters"
|
||||
stepId={stepId}
|
||||
disabled={editorContext.readOnly}
|
||||
/>
|
||||
</Box>
|
||||
{group?.and?.map(
|
||||
(groupItem: TGroupItem, groupItemIndex: number) => (
|
||||
<Stack direction="row" spacing={2} key={`item-${groupItem.id}`}>
|
||||
<Stack
|
||||
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
|
||||
schema={createStringArgument({
|
||||
key: `or.${groupIndex}.and.${groupItemIndex}.key`,
|
||||
label: 'Choose field',
|
||||
})}
|
||||
namePrefix="parameters"
|
||||
stepId={stepId}
|
||||
disabled={editorContext.readOnly}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: 'flex', flex: '1 0 0px', maxWidth: ['100%', '33%'] }}>
|
||||
<InputCreator
|
||||
schema={createDropdownArgument({ key: `or.${groupIndex}.and.${groupItemIndex}.operator`, options: operators, label: 'Choose condition' })}
|
||||
namePrefix="parameters"
|
||||
stepId={stepId}
|
||||
disabled={editorContext.readOnly}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flex: '1 0 0px',
|
||||
maxWidth: ['100%', '33%'],
|
||||
}}
|
||||
>
|
||||
<InputCreator
|
||||
schema={createDropdownArgument({
|
||||
key: `or.${groupIndex}.and.${groupItemIndex}.operator`,
|
||||
options: operators,
|
||||
label: 'Choose condition',
|
||||
})}
|
||||
namePrefix="parameters"
|
||||
stepId={stepId}
|
||||
disabled={editorContext.readOnly}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: 'flex', flex: '1 0 0px', maxWidth: ['100%', '33%'] }}>
|
||||
<InputCreator
|
||||
schema={createStringArgument({ key: `or.${groupIndex}.and.${groupItemIndex}.value`, label: 'Enter text' })}
|
||||
namePrefix="parameters"
|
||||
stepId={stepId}
|
||||
disabled={editorContext.readOnly}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flex: '1 0 0px',
|
||||
maxWidth: ['100%', '33%'],
|
||||
}}
|
||||
>
|
||||
<InputCreator
|
||||
schema={createStringArgument({
|
||||
key: `or.${groupIndex}.and.${groupItemIndex}.value`,
|
||||
label: 'Enter text',
|
||||
})}
|
||||
namePrefix="parameters"
|
||||
stepId={stepId}
|
||||
disabled={editorContext.readOnly}
|
||||
/>
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
<IconButton
|
||||
size="small"
|
||||
edge="start"
|
||||
onClick={() => removeGroupItem(groupIndex, groupItemIndex)}
|
||||
sx={{ width: 61, height: 61 }}
|
||||
>
|
||||
<RemoveIcon />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
|
||||
<IconButton
|
||||
size="small"
|
||||
edge="start"
|
||||
onClick={() => removeGroupItem(groupIndex, groupItemIndex)}
|
||||
sx={{ width: 61, height: 61 }}
|
||||
>
|
||||
<RemoveIcon />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
))}
|
||||
)
|
||||
)}
|
||||
|
||||
<Stack spacing={1} direction="row">
|
||||
<IconButton
|
||||
@@ -194,14 +238,16 @@ function FilterConditions(props: FilterConditionsProps): React.ReactElement {
|
||||
<AddIcon /> And
|
||||
</IconButton>
|
||||
|
||||
{(groups.length - 1) === groupIndex && <IconButton
|
||||
size="small"
|
||||
edge="start"
|
||||
onClick={appendGroup}
|
||||
sx={{ width: 61, height: 61 }}
|
||||
>
|
||||
<AddIcon /> Or
|
||||
</IconButton>}
|
||||
{groups.length - 1 === groupIndex && (
|
||||
<IconButton
|
||||
size="small"
|
||||
edge="start"
|
||||
onClick={appendGroup}
|
||||
sx={{ width: 61, height: 61 }}
|
||||
>
|
||||
<AddIcon /> Or
|
||||
</IconButton>
|
||||
)}
|
||||
</Stack>
|
||||
</>
|
||||
))}
|
||||
|
@@ -4,7 +4,7 @@ import Collapse from '@mui/material/Collapse';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import Button from '@mui/material/Button';
|
||||
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 FlowSubstepTitle from 'components/FlowSubstepTitle';
|
||||
@@ -54,7 +54,7 @@ function FlowSubstep(props: FlowSubstepProps): React.ReactElement {
|
||||
pb: 3,
|
||||
flexDirection: 'column',
|
||||
alignItems: 'flex-start',
|
||||
position: 'relative'
|
||||
position: 'relative',
|
||||
}}
|
||||
>
|
||||
{!!args?.length && (
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import MuiTextField from '@mui/material/TextField';
|
||||
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 useDynamicData from 'hooks/useDynamicData';
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { JSONTree } from 'react-json-tree';
|
||||
import type { IJSONObject } from '@automatisch/types';
|
||||
import type { IJSONObject } from 'types';
|
||||
|
||||
type JSONViewerProps = {
|
||||
data: IJSONObject;
|
||||
|
@@ -14,7 +14,7 @@ import Typography from '@mui/material/Typography';
|
||||
import * as React from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
|
||||
import { IPermissionCatalog } from '@automatisch/types';
|
||||
import { IPermissionCatalog } from 'types';
|
||||
import ControlledCheckbox from 'components/ControlledCheckbox';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
|
||||
@@ -118,7 +118,9 @@ export default function PermissionSettings(props: PermissionSettingsProps) {
|
||||
{action.subjects.includes(subject) && (
|
||||
<ControlledCheckbox
|
||||
name={`${fieldPrefix}.${action.key}.conditions.${condition.key}`}
|
||||
dataTest={`${condition.key}-${action.key.toLowerCase()}-checkbox`}
|
||||
dataTest={`${
|
||||
condition.key
|
||||
}-${action.key.toLowerCase()}-checkbox`}
|
||||
defaultValue={defaultChecked}
|
||||
disabled={
|
||||
getValues(
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { IStep } from '@automatisch/types';
|
||||
import type { IStep } from 'types';
|
||||
import ExpandLess from '@mui/icons-material/ExpandLess';
|
||||
import ExpandMore from '@mui/icons-material/ExpandMore';
|
||||
import Box from '@mui/material/Box';
|
||||
@@ -20,7 +20,7 @@ type SuggestionsProps = {
|
||||
data: {
|
||||
id: string;
|
||||
name: string;
|
||||
output: Record<string, unknown>[]
|
||||
output: Record<string, unknown>[];
|
||||
}[];
|
||||
onSuggestionClick: (variable: any) => void;
|
||||
};
|
||||
@@ -31,69 +31,73 @@ const LIST_ITEM_HEIGHT = 64;
|
||||
const computeListHeight = (currentLength: number) => {
|
||||
const numberOfRenderedItems = Math.min(SHORT_LIST_LENGTH, currentLength);
|
||||
return LIST_ITEM_HEIGHT * numberOfRenderedItems;
|
||||
}
|
||||
};
|
||||
|
||||
const getPartialArray = (array: any[], length = array.length) => {
|
||||
return array.slice(0, length);
|
||||
};
|
||||
|
||||
const renderItemFactory = ({ onSuggestionClick }: Pick<SuggestionsProps, 'onSuggestionClick'>) => (props: ListChildComponentProps) => {
|
||||
const { index, style, data } = props;
|
||||
const renderItemFactory =
|
||||
({ onSuggestionClick }: Pick<SuggestionsProps, 'onSuggestionClick'>) =>
|
||||
(props: ListChildComponentProps) => {
|
||||
const { index, style, data } = props;
|
||||
|
||||
const suboption = data[index];
|
||||
const suboption = data[index];
|
||||
|
||||
return (
|
||||
<ListItemButton
|
||||
sx={{ pl: 4 }}
|
||||
divider
|
||||
onClick={() => onSuggestionClick(suboption)}
|
||||
data-test="power-input-suggestion-item"
|
||||
key={index}
|
||||
style={style}
|
||||
>
|
||||
<ListItemText
|
||||
primary={suboption.label}
|
||||
primaryTypographyProps={{
|
||||
variant: 'subtitle1',
|
||||
title: 'Property name',
|
||||
sx: { fontWeight: 700 },
|
||||
}}
|
||||
secondary={suboption.sampleValue || ''}
|
||||
secondaryTypographyProps={{
|
||||
variant: 'subtitle2',
|
||||
title: 'Sample value',
|
||||
noWrap: true,
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<ListItemButton
|
||||
sx={{ pl: 4 }}
|
||||
divider
|
||||
onClick={() => onSuggestionClick(suboption)}
|
||||
data-test="power-input-suggestion-item"
|
||||
key={index}
|
||||
style={style}
|
||||
>
|
||||
<ListItemText
|
||||
primary={suboption.label}
|
||||
primaryTypographyProps={{
|
||||
variant: 'subtitle1',
|
||||
title: 'Property name',
|
||||
sx: { fontWeight: 700 },
|
||||
}}
|
||||
secondary={suboption.sampleValue || ''}
|
||||
secondaryTypographyProps={{
|
||||
variant: 'subtitle2',
|
||||
title: 'Sample value',
|
||||
noWrap: true,
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
);
|
||||
};
|
||||
|
||||
const Suggestions = (props: SuggestionsProps) => {
|
||||
const formatMessage = useFormatMessage();
|
||||
const {
|
||||
data,
|
||||
onSuggestionClick = () => null
|
||||
} = props;
|
||||
const { data, onSuggestionClick = () => null } = props;
|
||||
const [current, setCurrent] = React.useState<number | null>(0);
|
||||
const [listLength, setListLength] = React.useState<number>(SHORT_LIST_LENGTH);
|
||||
const [filteredData, setFilteredData] = React.useState<any[]>(
|
||||
data
|
||||
const [filteredData, setFilteredData] = React.useState<any[]>(data);
|
||||
|
||||
React.useEffect(
|
||||
function syncOptions() {
|
||||
setFilteredData((filteredData) => {
|
||||
if (filteredData.length === 0 && filteredData.length !== data.length) {
|
||||
return data;
|
||||
}
|
||||
|
||||
return filteredData;
|
||||
});
|
||||
},
|
||||
[data]
|
||||
);
|
||||
|
||||
React.useEffect(function syncOptions() {
|
||||
setFilteredData((filteredData) => {
|
||||
if (filteredData.length === 0 && filteredData.length !== data.length) {
|
||||
return data;
|
||||
}
|
||||
|
||||
return filteredData;
|
||||
})
|
||||
}, [data]);
|
||||
|
||||
const renderItem = React.useMemo(() => renderItemFactory({
|
||||
onSuggestionClick
|
||||
}), [onSuggestionClick]);
|
||||
const renderItem = React.useMemo(
|
||||
() =>
|
||||
renderItemFactory({
|
||||
onSuggestionClick,
|
||||
}),
|
||||
[onSuggestionClick]
|
||||
);
|
||||
|
||||
const expandList = () => {
|
||||
setListLength(Infinity);
|
||||
@@ -122,12 +126,12 @@ const Suggestions = (props: SuggestionsProps) => {
|
||||
return {
|
||||
id: stepWithOutput.id,
|
||||
name: stepWithOutput.name,
|
||||
output: stepWithOutput.output
|
||||
.filter(option => `${option.label}\n${option.sampleValue}`
|
||||
output: stepWithOutput.output.filter((option) =>
|
||||
`${option.label}\n${option.sampleValue}`
|
||||
.toLowerCase()
|
||||
.includes(search.toLowerCase())
|
||||
)
|
||||
}
|
||||
),
|
||||
};
|
||||
})
|
||||
.filter((stepWithOutput) => stepWithOutput.output.length);
|
||||
|
||||
@@ -161,14 +165,27 @@ const Suggestions = (props: SuggestionsProps) => {
|
||||
(current === index ? <ExpandLess /> : <ExpandMore />)}
|
||||
</ListItemButton>
|
||||
|
||||
<Collapse in={current === index || filteredData.length === 1} timeout="auto" unmountOnExit>
|
||||
<Collapse
|
||||
in={current === index || filteredData.length === 1}
|
||||
timeout="auto"
|
||||
unmountOnExit
|
||||
>
|
||||
<FixedSizeList
|
||||
height={computeListHeight(getPartialArray((option.output as any) || [], listLength).length)}
|
||||
height={computeListHeight(
|
||||
getPartialArray((option.output as any) || [], listLength)
|
||||
.length
|
||||
)}
|
||||
width="100%"
|
||||
itemSize={LIST_ITEM_HEIGHT}
|
||||
itemCount={getPartialArray((option.output as any) || [], listLength).length}
|
||||
itemCount={
|
||||
getPartialArray((option.output as any) || [], listLength)
|
||||
.length
|
||||
}
|
||||
overscanCount={2}
|
||||
itemData={getPartialArray((option.output as any) || [], listLength)}
|
||||
itemData={getPartialArray(
|
||||
(option.output as any) || [],
|
||||
listLength
|
||||
)}
|
||||
data-test="power-input-suggestion-group"
|
||||
>
|
||||
{renderItem}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { IStep } from '@automatisch/types';
|
||||
import type { IStep } from 'types';
|
||||
|
||||
const joinBy = (delimiter = '.', ...args: string[]) =>
|
||||
args.filter(Boolean).join(delimiter);
|
||||
@@ -10,7 +10,12 @@ type TProcessPayload = {
|
||||
parentLabel?: string;
|
||||
};
|
||||
|
||||
const process = ({ data, parentKey, index, parentLabel = '' }: TProcessPayload): any[] => {
|
||||
const process = ({
|
||||
data,
|
||||
parentKey,
|
||||
index,
|
||||
parentLabel = '',
|
||||
}: TProcessPayload): any[] => {
|
||||
if (typeof data !== 'object') {
|
||||
return [
|
||||
{
|
||||
@@ -24,27 +29,19 @@ const process = ({ data, parentKey, index, parentLabel = '' }: TProcessPayload):
|
||||
const entries = Object.entries(data);
|
||||
|
||||
return entries.flatMap(([name, sampleValue]) => {
|
||||
const label = joinBy(
|
||||
'.',
|
||||
parentLabel,
|
||||
(index as number)?.toString(),
|
||||
name
|
||||
);
|
||||
const label = joinBy('.', parentLabel, (index as number)?.toString(), name);
|
||||
|
||||
const value = joinBy(
|
||||
'.',
|
||||
parentKey,
|
||||
(index as number)?.toString(),
|
||||
name
|
||||
);
|
||||
const value = joinBy('.', parentKey, (index as number)?.toString(), name);
|
||||
|
||||
if (Array.isArray(sampleValue)) {
|
||||
return sampleValue.flatMap((item, index) => process({
|
||||
data: item,
|
||||
parentKey: value,
|
||||
index,
|
||||
parentLabel: label
|
||||
}));
|
||||
return sampleValue.flatMap((item, index) =>
|
||||
process({
|
||||
data: item,
|
||||
parentKey: value,
|
||||
index,
|
||||
parentLabel: label,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof sampleValue === 'object' && sampleValue !== null) {
|
||||
@@ -77,8 +74,9 @@ export const processStepWithExecutions = (steps: IStep[]): any[] => {
|
||||
.map((step: IStep, index: number) => ({
|
||||
id: step.id,
|
||||
// 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({
|
||||
data: step.executionSteps?.[0]?.dataOut || {},
|
||||
parentKey: `step.${step.id}`,
|
||||
|
@@ -3,7 +3,7 @@ import throttle from 'lodash/throttle';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import { Box, Typography } from '@mui/material';
|
||||
|
||||
import { IJSONObject } from '@automatisch/types';
|
||||
import { IJSONObject } from 'types';
|
||||
import JSONViewer from 'components/JSONViewer';
|
||||
import SearchInput from 'components/SearchInput';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { Text, Descendant } from 'slate';
|
||||
import { withHistory } from 'slate-history';
|
||||
import { ReactEditor, withReact } from 'slate-react';
|
||||
import { IFieldDropdownOption } from '@automatisch/types';
|
||||
import { IFieldDropdownOption } from 'types';
|
||||
|
||||
import type {
|
||||
CustomEditor,
|
||||
|
@@ -13,7 +13,7 @@ import { EXECUTE_FLOW } from 'graphql/mutations/execute-flow';
|
||||
import JSONViewer from 'components/JSONViewer';
|
||||
import WebhookUrlInfo from 'components/WebhookUrlInfo';
|
||||
import FlowSubstepTitle from 'components/FlowSubstepTitle';
|
||||
import type { IStep, ISubstep } from '@automatisch/types';
|
||||
import type { IStep, ISubstep } from 'types';
|
||||
|
||||
type TestSubstepProps = {
|
||||
substep: ISubstep;
|
||||
@@ -62,7 +62,7 @@ function TestSubstep(props: TestSubstepProps): React.ReactElement {
|
||||
EXECUTE_FLOW,
|
||||
{
|
||||
refetchQueries: ['GetStepWithTestExecutions'],
|
||||
context: { autoSnackbar: false }
|
||||
context: { autoSnackbar: false },
|
||||
}
|
||||
);
|
||||
const response = data?.executeFlow?.data;
|
||||
|
@@ -5,7 +5,7 @@ import get from 'lodash/get';
|
||||
import set from 'lodash/set';
|
||||
import * as React from 'react';
|
||||
|
||||
import { IJSONObject } from '@automatisch/types';
|
||||
import { IJSONObject } from 'types';
|
||||
import useConfig from 'hooks/useConfig';
|
||||
import useAutomatischInfo from 'hooks/useAutomatischInfo';
|
||||
import { defaultTheme, mationTheme } from 'styles/theme';
|
||||
|
@@ -11,7 +11,7 @@ import Divider from '@mui/material/Divider';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
import { TBillingCardAction } from '@automatisch/types';
|
||||
import { TBillingCardAction } from 'types';
|
||||
import TrialOverAlert from 'components/TrialOverAlert/index.ee';
|
||||
import SubscriptionCancelledAlert from 'components/SubscriptionCancelledAlert/index.ee';
|
||||
import CheckoutCompletedAlert from 'components/CheckoutCompletedAlert/index.ee';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import type { IStep } from '@automatisch/types';
|
||||
import type { IStep } from 'types';
|
||||
|
||||
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 MUTATIONS from 'graphql/mutations';
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import template from 'lodash/template';
|
||||
import type { IAuthenticationStepField, IJSONObject } from '@automatisch/types';
|
||||
import type { IAuthenticationStepField, IJSONObject } from 'types';
|
||||
|
||||
const interpolate = /{([\s\S]+?)}/g;
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { IRole, IPermission } from '@automatisch/types';
|
||||
import { IRole, IPermission } from 'types';
|
||||
|
||||
type ComputeAction = {
|
||||
conditions: Record<string, boolean>;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import template from 'lodash/template';
|
||||
import type { IAuthenticationStepField, IJSONObject } from '@automatisch/types';
|
||||
import type { IAuthenticationStepField, IJSONObject } from 'types';
|
||||
|
||||
const interpolate = /{([\s\S]+?)}/g;
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { IJSONObject } from '@automatisch/types';
|
||||
import { IJSONObject } from 'types';
|
||||
import set from 'lodash/set';
|
||||
|
||||
export default function nestObject<T = IJSONObject>(
|
||||
|
@@ -1,5 +1,9 @@
|
||||
import { PureAbility, fieldPatternMatcher, mongoQueryMatcher } from '@casl/ability';
|
||||
import { IUser } from '@automatisch/types';
|
||||
import {
|
||||
PureAbility,
|
||||
fieldPatternMatcher,
|
||||
mongoQueryMatcher,
|
||||
} from '@casl/ability';
|
||||
import { IUser } from 'types';
|
||||
|
||||
// Must be kept in sync with `packages/backend/src/helpers/user-ability.ts`!
|
||||
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
|
||||
const options = {
|
||||
conditionsMatcher: mongoQueryMatcher,
|
||||
fieldMatcher: fieldPatternMatcher
|
||||
fieldMatcher: fieldPatternMatcher,
|
||||
};
|
||||
|
||||
if (!role || !permissions) {
|
||||
|
@@ -1,22 +1,16 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { IApp } from '@automatisch/types';
|
||||
import { IApp } from 'types';
|
||||
|
||||
import { GET_APP } from 'graphql/queries/get-app';
|
||||
|
||||
type QueryResponse = {
|
||||
getApp: IApp;
|
||||
}
|
||||
};
|
||||
|
||||
export default function useApp(key: string) {
|
||||
const {
|
||||
data,
|
||||
loading
|
||||
} = useQuery<QueryResponse>(
|
||||
GET_APP,
|
||||
{
|
||||
variables: { key }
|
||||
}
|
||||
);
|
||||
const { data, loading } = useQuery<QueryResponse>(GET_APP, {
|
||||
variables: { key },
|
||||
});
|
||||
const app = data?.getApp;
|
||||
|
||||
return {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { useLazyQuery } from '@apollo/client';
|
||||
import { AppAuthClient } from '@automatisch/types';
|
||||
import { AppAuthClient } from 'types';
|
||||
import * as React from 'react';
|
||||
|
||||
import { GET_APP_AUTH_CLIENT } from 'graphql/queries/get-app-auth-client.ee';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { useLazyQuery } from '@apollo/client';
|
||||
import { AppAuthClient } from '@automatisch/types';
|
||||
import { AppAuthClient } from 'types';
|
||||
import * as React from 'react';
|
||||
|
||||
import { GET_APP_AUTH_CLIENTS } from 'graphql/queries/get-app-auth-clients.ee';
|
||||
|
@@ -1,23 +1,17 @@
|
||||
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';
|
||||
|
||||
type QueryResponse = {
|
||||
getAppConfig: AppConfig;
|
||||
}
|
||||
};
|
||||
|
||||
export default function useAppConfig(key: string) {
|
||||
const {
|
||||
data,
|
||||
loading
|
||||
} = useQuery<QueryResponse>(
|
||||
GET_APP_CONFIG,
|
||||
{
|
||||
variables: { key },
|
||||
context: { autoSnackbar: false }
|
||||
}
|
||||
);
|
||||
const { data, loading } = useQuery<QueryResponse>(GET_APP_CONFIG, {
|
||||
variables: { key },
|
||||
context: { autoSnackbar: false },
|
||||
});
|
||||
const appConfig = data?.getAppConfig;
|
||||
|
||||
return {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { IApp } from '@automatisch/types';
|
||||
import { IApp } from 'types';
|
||||
|
||||
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 { processStep } from 'helpers/authenticationSteps';
|
||||
@@ -10,14 +10,18 @@ type UseAuthenticateAppParams = {
|
||||
appAuthClientId?: string;
|
||||
useShared?: boolean;
|
||||
connectionId?: string;
|
||||
}
|
||||
};
|
||||
|
||||
type AuthenticatePayload = {
|
||||
fields?: Record<string, string>;
|
||||
appAuthClientId?: string;
|
||||
}
|
||||
};
|
||||
|
||||
function getSteps(auth: IApp['auth'], hasConnection: boolean, useShared: boolean) {
|
||||
function getSteps(
|
||||
auth: IApp['auth'],
|
||||
hasConnection: boolean,
|
||||
useShared: boolean
|
||||
) {
|
||||
if (hasConnection) {
|
||||
if (useShared) {
|
||||
return auth?.sharedReconnectionSteps;
|
||||
@@ -34,26 +38,17 @@ function getSteps(auth: IApp['auth'], hasConnection: boolean, useShared: boolean
|
||||
}
|
||||
|
||||
export default function useAuthenticateApp(payload: UseAuthenticateAppParams) {
|
||||
const {
|
||||
appKey,
|
||||
appAuthClientId,
|
||||
connectionId,
|
||||
useShared = false,
|
||||
} = payload;
|
||||
const { appKey, appAuthClientId, connectionId, useShared = false } = payload;
|
||||
const { app } = useApp(appKey);
|
||||
const [
|
||||
authenticationInProgress,
|
||||
setAuthenticationInProgress
|
||||
] = React.useState(false);
|
||||
const [authenticationInProgress, setAuthenticationInProgress] =
|
||||
React.useState(false);
|
||||
const steps = getSteps(app?.auth, !!connectionId, useShared);
|
||||
|
||||
const authenticate = React.useMemo(() => {
|
||||
if (!steps?.length) return;
|
||||
|
||||
return async function authenticate(payload: AuthenticatePayload = {}) {
|
||||
const {
|
||||
fields,
|
||||
} = payload;
|
||||
const { fields } = payload;
|
||||
setAuthenticationInProgress(true);
|
||||
|
||||
const response: Record<string, any> = {
|
||||
@@ -62,7 +57,7 @@ export default function useAuthenticateApp(payload: UseAuthenticateAppParams) {
|
||||
connection: {
|
||||
id: connectionId,
|
||||
},
|
||||
fields
|
||||
fields,
|
||||
};
|
||||
|
||||
let stepIndex = 0;
|
||||
@@ -90,7 +85,7 @@ export default function useAuthenticateApp(payload: UseAuthenticateAppParams) {
|
||||
|
||||
setAuthenticationInProgress(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
}, [steps, appKey, appAuthClientId, connectionId]);
|
||||
|
||||
return {
|
||||
|
@@ -2,15 +2,21 @@ import * as React from 'react';
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
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';
|
||||
|
||||
function transform(billingAndUsageData: NonNullable<UseBillingAndUsageDataReturn>) {
|
||||
function transform(
|
||||
billingAndUsageData: NonNullable<UseBillingAndUsageDataReturn>
|
||||
) {
|
||||
const nextBillDate = billingAndUsageData.subscription.nextBillDate;
|
||||
const nextBillDateTitle = nextBillDate.title;
|
||||
const nextBillDateTitleDateObject = DateTime.fromMillis(Number(nextBillDateTitle));
|
||||
const formattedNextBillDateTitle = nextBillDateTitleDateObject.isValid ? nextBillDateTitleDateObject.toFormat('LLL dd, yyyy') : nextBillDateTitle;
|
||||
const nextBillDateTitleDateObject = DateTime.fromMillis(
|
||||
Number(nextBillDateTitle)
|
||||
);
|
||||
const formattedNextBillDateTitle = nextBillDateTitleDateObject.isValid
|
||||
? nextBillDateTitleDateObject.toFormat('LLL dd, yyyy')
|
||||
: nextBillDateTitle;
|
||||
|
||||
return {
|
||||
...billingAndUsageData,
|
||||
@@ -19,8 +25,8 @@ function transform(billingAndUsageData: NonNullable<UseBillingAndUsageDataReturn
|
||||
nextBillDate: {
|
||||
...billingAndUsageData.subscription.nextBillDate,
|
||||
title: formattedNextBillDateTitle,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -28,27 +34,35 @@ type UseBillingAndUsageDataReturn = {
|
||||
subscription: TSubscription;
|
||||
usage: {
|
||||
task: number;
|
||||
}
|
||||
};
|
||||
} | null;
|
||||
|
||||
export default function useBillingAndUsageData(): UseBillingAndUsageDataReturn {
|
||||
const location = useLocation();
|
||||
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 hasSubscription = !!data?.getBillingAndUsage?.subscription?.status;
|
||||
|
||||
React.useEffect(function pollDataUntilSubscriptionIsCreated() {
|
||||
if (checkoutCompleted && !hasSubscription) {
|
||||
startPolling(1000);
|
||||
}
|
||||
}, [checkoutCompleted, hasSubscription, startPolling]);
|
||||
React.useEffect(
|
||||
function pollDataUntilSubscriptionIsCreated() {
|
||||
if (checkoutCompleted && !hasSubscription) {
|
||||
startPolling(1000);
|
||||
}
|
||||
},
|
||||
[checkoutCompleted, hasSubscription, startPolling]
|
||||
);
|
||||
|
||||
React.useEffect(function stopPollingWhenSubscriptionIsCreated() {
|
||||
if (checkoutCompleted && hasSubscription) {
|
||||
stopPolling();
|
||||
}
|
||||
}, [checkoutCompleted, hasSubscription, stopPolling]);
|
||||
React.useEffect(
|
||||
function stopPollingWhenSubscriptionIsCreated() {
|
||||
if (checkoutCompleted && hasSubscription) {
|
||||
stopPolling();
|
||||
}
|
||||
},
|
||||
[checkoutCompleted, hasSubscription, stopPolling]
|
||||
);
|
||||
|
||||
if (loading) return null;
|
||||
|
||||
|
@@ -1,14 +1,16 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { IJSONObject } from '@automatisch/types';
|
||||
import { IJSONObject } from 'types';
|
||||
|
||||
import { GET_CONFIG } from 'graphql/queries/get-config.ee';
|
||||
|
||||
type QueryResponse = {
|
||||
getConfig: IJSONObject;
|
||||
}
|
||||
};
|
||||
|
||||
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 {
|
||||
config: data?.getConfig,
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { IUser } from '@automatisch/types';
|
||||
import { IUser } from 'types';
|
||||
|
||||
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 type { UseFormReturn } from 'react-hook-form';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import type {
|
||||
IField,
|
||||
IFieldDropdownSource,
|
||||
IJSONObject,
|
||||
} from '@automatisch/types';
|
||||
import type { IField, IFieldDropdownSource, IJSONObject } from 'types';
|
||||
|
||||
import { GET_DYNAMIC_DATA } from 'graphql/queries/get-dynamic-data';
|
||||
|
||||
|
@@ -8,7 +8,7 @@ import type {
|
||||
IField,
|
||||
IFieldDropdownAdditionalFields,
|
||||
IJSONObject,
|
||||
} from '@automatisch/types';
|
||||
} from 'types';
|
||||
|
||||
import { GET_DYNAMIC_FIELDS } from 'graphql/queries/get-dynamic-fields';
|
||||
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { TInvoice } from '@automatisch/types';
|
||||
import { TInvoice } from 'types';
|
||||
|
||||
import { GET_INVOICES } from 'graphql/queries/get-invoices.ee';
|
||||
|
||||
type UseInvoicesReturn = {
|
||||
invoices: TInvoice[],
|
||||
invoices: TInvoice[];
|
||||
loading: boolean;
|
||||
};
|
||||
|
||||
@@ -13,6 +13,6 @@ export default function useInvoices(): UseInvoicesReturn {
|
||||
|
||||
return {
|
||||
invoices: data?.getInvoices || [],
|
||||
loading: loading
|
||||
loading: loading,
|
||||
};
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
import type { Notification } from '@automatisch/types';
|
||||
import type { Notification } from 'types';
|
||||
|
||||
import { GET_NOTIFICATIONS } from 'graphql/queries/get-notifications';
|
||||
|
||||
type UseNotificationsReturn = {
|
||||
notifications: Notification[];
|
||||
loading: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export default function useNotifications(): UseNotificationsReturn {
|
||||
const { data, loading } = useQuery(GET_NOTIFICATIONS);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
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';
|
||||
|
||||
type UsePaymentPlansReturn = {
|
||||
@@ -13,6 +13,6 @@ export default function usePaymentPlans(): UsePaymentPlansReturn {
|
||||
|
||||
return {
|
||||
plans: data?.getPaymentPlans || [],
|
||||
loading
|
||||
loading,
|
||||
};
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
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';
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { useLazyQuery } from '@apollo/client';
|
||||
import { IRole } from '@automatisch/types';
|
||||
import { IRole } from 'types';
|
||||
|
||||
import { GET_ROLE } from 'graphql/queries/get-role.ee';
|
||||
|
||||
|
@@ -1,17 +1,19 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { IRole } from '@automatisch/types';
|
||||
import { IRole } from 'types';
|
||||
|
||||
import { GET_ROLES } from 'graphql/queries/get-roles.ee';
|
||||
|
||||
type QueryResponse = {
|
||||
getRoles: IRole[];
|
||||
}
|
||||
};
|
||||
|
||||
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 {
|
||||
roles: data?.getRoles || [],
|
||||
loading
|
||||
loading,
|
||||
};
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
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';
|
||||
|
||||
type UseSamlAuthProviderReturn = {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
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';
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
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';
|
||||
|
||||
type UseSamlAuthProvidersReturn = {
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import * as React from 'react';
|
||||
import { useLazyQuery } from '@apollo/client';
|
||||
import { IUser } from '@automatisch/types';
|
||||
import { IUser } from 'types';
|
||||
|
||||
import { GET_USER } from 'graphql/queries/get-user';
|
||||
|
||||
type QueryResponse = {
|
||||
getUser: IUser;
|
||||
}
|
||||
};
|
||||
|
||||
export default function useUser(userId?: string) {
|
||||
const [getUser, { data, loading }] = useLazyQuery<QueryResponse>(GET_USER);
|
||||
@@ -15,14 +15,14 @@ export default function useUser(userId?: string) {
|
||||
if (userId) {
|
||||
getUser({
|
||||
variables: {
|
||||
id: userId
|
||||
}
|
||||
id: userId,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [userId]);
|
||||
|
||||
return {
|
||||
user: data?.getUser,
|
||||
loading
|
||||
loading,
|
||||
};
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { IUser } from '@automatisch/types';
|
||||
import { IUser } from 'types';
|
||||
|
||||
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 Divider from '@mui/material/Divider';
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { IApp } from '@automatisch/types';
|
||||
import { IApp } from 'types';
|
||||
|
||||
import PageTitle from 'components/PageTitle';
|
||||
import Container from 'components/Container';
|
||||
|
@@ -6,7 +6,7 @@ import Grid from '@mui/material/Grid';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import CircularProgress from '@mui/material/CircularProgress';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
import type { IApp } from '@automatisch/types';
|
||||
import type { IApp } from 'types';
|
||||
|
||||
import Can from 'components/Can';
|
||||
import NoResultFound from 'components/NoResultFound';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { useMutation } from '@apollo/client';
|
||||
import { TSamlAuthProvider, TSamlAuthProviderRole } from '@automatisch/types';
|
||||
import { TSamlAuthProvider, TSamlAuthProviderRole } from 'types';
|
||||
import LoadingButton from '@mui/lab/LoadingButton';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import Stack from '@mui/material/Stack';
|
||||
@@ -65,8 +65,8 @@ function RoleMappings({ provider, providerLoading }: RoleMappingsProps) {
|
||||
enqueueSnackbar(formatMessage('roleMappingsForm.successfullySaved'), {
|
||||
variant: 'success',
|
||||
SnackbarProps: {
|
||||
'data-test': 'snackbar-update-role-mappings-success'
|
||||
}
|
||||
'data-test': 'snackbar-update-role-mappings-success',
|
||||
},
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { useFieldArray, useFormContext } from 'react-hook-form';
|
||||
import { IRole } from '@automatisch/types';
|
||||
import { IRole } from 'types';
|
||||
import MuiTextField from '@mui/material/TextField';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { QueryResult, useMutation } from '@apollo/client';
|
||||
import { IRole, TSamlAuthProvider } from '@automatisch/types';
|
||||
import { IRole, TSamlAuthProvider } from 'types';
|
||||
import LoadingButton from '@mui/lab/LoadingButton';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import MuiTextField from '@mui/material/TextField';
|
||||
@@ -94,8 +94,8 @@ function SamlConfiguration({
|
||||
enqueueSnackbar(formatMessage('authenticationForm.successfullySaved'), {
|
||||
variant: 'success',
|
||||
SnackbarProps: {
|
||||
'data-test': 'snackbar-save-saml-provider-success'
|
||||
}
|
||||
'data-test': 'snackbar-save-saml-provider-success',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
throw new Error('Failed while saving!');
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { useMutation } from '@apollo/client';
|
||||
import { IRole, IUser } from '@automatisch/types';
|
||||
import { IRole, IUser } from 'types';
|
||||
import LoadingButton from '@mui/lab/LoadingButton';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Stack from '@mui/material/Stack';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { useMutation } from '@apollo/client';
|
||||
import { IRole, IUser } from '@automatisch/types';
|
||||
import { IRole, IUser } from 'types';
|
||||
import LoadingButton from '@mui/lab/LoadingButton';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Skeleton from '@mui/material/Skeleton';
|
||||
|
@@ -5,7 +5,7 @@ import Grid from '@mui/material/Grid';
|
||||
import Box from '@mui/material/Box';
|
||||
import AlertTitle from '@mui/material/AlertTitle';
|
||||
import Alert from '@mui/material/Alert';
|
||||
import type { IExecutionStep } from '@automatisch/types';
|
||||
import type { IExecutionStep } from 'types';
|
||||
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
import ExecutionHeader from 'components/ExecutionHeader';
|
||||
|
@@ -7,7 +7,7 @@ import CircularProgress from '@mui/material/CircularProgress';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import Pagination from '@mui/material/Pagination';
|
||||
import PaginationItem from '@mui/material/PaginationItem';
|
||||
import type { IExecution } from '@automatisch/types';
|
||||
import type { IExecution } from 'types';
|
||||
|
||||
import NoResultFound from 'components/NoResultFound';
|
||||
import ExecutionRow from 'components/ExecutionRow';
|
||||
|
@@ -9,7 +9,7 @@ import CircularProgress from '@mui/material/CircularProgress';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import Pagination from '@mui/material/Pagination';
|
||||
import PaginationItem from '@mui/material/PaginationItem';
|
||||
import type { IFlow } from '@automatisch/types';
|
||||
import type { IFlow } from 'types';
|
||||
|
||||
import Can from 'components/Can';
|
||||
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