refactor(web): replace CRA with Vite
This commit is contained in:
@@ -69,7 +69,7 @@ AccountDropdownMenu.propTypes = {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
anchorEl: PropTypes.oneOfType([
|
||||
PropTypes.func,
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(Element) }),
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(window.Element) }),
|
||||
]),
|
||||
id: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ function AdminApplicationSettings({ appKey }) {
|
||||
'data-test': 'snackbar-save-admin-apps-settings-success',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
} catch {
|
||||
throw new Error('Failed while saving!');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -37,18 +37,17 @@ function AdminApplicationUpdateOAuthClient(props) {
|
||||
if (!adminOAuthClient) {
|
||||
return;
|
||||
}
|
||||
const { name, active, ...formattedAuthDefaults } = values;
|
||||
|
||||
setAuthDefaultsUpdatePending(true);
|
||||
await updateOAuthClient({
|
||||
formattedAuthDefaults,
|
||||
}).finally(() => {
|
||||
|
||||
await updateOAuthClient(values.formattedAuthDefaults).finally(() => {
|
||||
setAuthDefaultsUpdatePending(false);
|
||||
});
|
||||
|
||||
setDefaultValues((prev) => ({
|
||||
name: prev.name,
|
||||
active: prev.active,
|
||||
...formattedAuthDefaults,
|
||||
...values.formattedAuthDefaults,
|
||||
}));
|
||||
|
||||
enqueueSnackbar(formatMessage('updateOAuthClient.success'), {
|
||||
|
||||
@@ -24,7 +24,6 @@ import useCurrentUserAbility from 'hooks/useCurrentUserAbility';
|
||||
import Footer from './Footer';
|
||||
|
||||
function createDrawerLinks({
|
||||
canCreateFlows,
|
||||
canReadRole,
|
||||
canReadUser,
|
||||
canUpdateConfig,
|
||||
|
||||
@@ -57,7 +57,7 @@ AdminTemplateContextMenu.propTypes = {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
anchorEl: PropTypes.oneOfType([
|
||||
PropTypes.func,
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(Element) }),
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(window.Element) }),
|
||||
]).isRequired,
|
||||
};
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ ContextMenu.propTypes = {
|
||||
onMenuItemClick: PropTypes.func.isRequired,
|
||||
anchorEl: PropTypes.oneOfType([
|
||||
PropTypes.func,
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(Element) }),
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(window.Element) }),
|
||||
]),
|
||||
};
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ function AppConnectionRow(props) {
|
||||
{ connectionId: id },
|
||||
{
|
||||
onSettled: () => {
|
||||
setTimeout(() => setVerificationVisible(false), 3000);
|
||||
window.setTimeout(() => setVerificationVisible(false), 3000);
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
@@ -17,8 +17,9 @@ import FlowSubstepTitle from 'components/FlowSubstepTitle';
|
||||
import { StepPropType, SubstepPropType } from 'propTypes/propTypes';
|
||||
import useTriggers from 'hooks/useTriggers';
|
||||
import useActions from 'hooks/useActions';
|
||||
import appConfig from 'config/app.js';
|
||||
|
||||
const useNewFlowEditor = process.env.REACT_APP_USE_NEW_FLOW_EDITOR === 'true';
|
||||
const useNewFlowEditor = appConfig.useNewFlowEditor;
|
||||
|
||||
const optionGenerator = (app) => ({
|
||||
label: app.name,
|
||||
|
||||
@@ -24,8 +24,9 @@ import useAppConnections from 'hooks/useAppConnections';
|
||||
import useTestConnection from 'hooks/useTestConnection';
|
||||
import useOAuthClients from 'hooks/useOAuthClients';
|
||||
import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar';
|
||||
import appConfig from 'config/app.js';
|
||||
|
||||
const useNewFlowEditor = process.env.REACT_APP_USE_NEW_FLOW_EDITOR === 'true';
|
||||
const useNewFlowEditor = appConfig.useNewFlowEditor;
|
||||
|
||||
const ADD_CONNECTION_VALUE = 'ADD_CONNECTION';
|
||||
const ADD_SHARED_CONNECTION_VALUE = 'ADD_SHARED_CONNECTION';
|
||||
|
||||
@@ -20,7 +20,7 @@ function CodeEditor(props) {
|
||||
'data-test': dataTest,
|
||||
} = props;
|
||||
|
||||
const handleEditorOnMount = (editor, monaco) => {
|
||||
const handleEditorOnMount = (editor) => {
|
||||
editorRef.current = editor;
|
||||
|
||||
editor.onDidContentSizeChange((event) => {
|
||||
|
||||
@@ -78,7 +78,7 @@ CustomOptions.propTypes = {
|
||||
open: PropTypes.bool.isRequired,
|
||||
anchorEl: PropTypes.oneOfType([
|
||||
PropTypes.func,
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(Element) }),
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(window.Element) }),
|
||||
]),
|
||||
data: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
|
||||
@@ -55,9 +55,10 @@ Item.propTypes = {
|
||||
onOptionClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
const renderItemFactory =
|
||||
({ onOptionClick }) =>
|
||||
(props) => <Item onOptionClick={onOptionClick} {...props} />;
|
||||
const renderItemFactory = ({ onOptionClick }) =>
|
||||
function RenderItem(props) {
|
||||
return <Item onOptionClick={onOptionClick} {...props} />;
|
||||
};
|
||||
|
||||
const Options = (props) => {
|
||||
const formatMessage = useFormatMessage();
|
||||
|
||||
@@ -89,7 +89,7 @@ function ControlledCustomAutocomplete(props) {
|
||||
};
|
||||
|
||||
const resizeObserver = React.useMemo(function syncCustomOptionsPosition() {
|
||||
return new ResizeObserver(() => {
|
||||
return new window.ResizeObserver(() => {
|
||||
forceUpdate();
|
||||
});
|
||||
}, []);
|
||||
|
||||
@@ -4,8 +4,6 @@ import { AdapterLuxon } from '@mui/x-date-pickers/AdapterLuxon';
|
||||
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
|
||||
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
|
||||
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
|
||||
export default function DatePickerInput({
|
||||
onChange,
|
||||
defaultValue = '',
|
||||
@@ -15,7 +13,6 @@ export default function DatePickerInput({
|
||||
maxDate,
|
||||
}) {
|
||||
const intl = useIntl();
|
||||
const formatMessage = useFormatMessage();
|
||||
|
||||
const props = {
|
||||
label,
|
||||
|
||||
@@ -39,7 +39,9 @@ function DeleteApiTokenButton(props) {
|
||||
},
|
||||
},
|
||||
);
|
||||
} catch {}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}, [deleteApiToken]);
|
||||
|
||||
const handleClose = () => {
|
||||
|
||||
@@ -43,7 +43,9 @@ function DeleteRoleButton(props) {
|
||||
'data-test': 'snackbar-delete-role-success',
|
||||
},
|
||||
});
|
||||
} catch {}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}, [deleteRole, enqueueSnackbar, formatMessage]);
|
||||
|
||||
const handleClose = () => {
|
||||
|
||||
@@ -39,7 +39,9 @@ function DeleteUserButton(props) {
|
||||
'data-test': 'snackbar-delete-user-success',
|
||||
},
|
||||
});
|
||||
} catch {}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}, [deleteUser]);
|
||||
|
||||
const handleClose = () => {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { Drawer as BaseDrawer } from './style';
|
||||
|
||||
const iOS =
|
||||
typeof navigator !== 'undefined' &&
|
||||
/iPad|iPhone|iPod/.test(navigator.userAgent);
|
||||
/iPad|iPhone|iPod/.test(window.navigator.userAgent);
|
||||
|
||||
function Drawer(props) {
|
||||
const { links = [], bottomLinks = [], ...drawerProps } = props;
|
||||
|
||||
@@ -27,8 +27,9 @@ import useUpdateFlow from 'hooks/useUpdateFlow';
|
||||
import useUpdateFlowStatus from 'hooks/useUpdateFlowStatus';
|
||||
import FlowFolder from './FlowFolder';
|
||||
import { TopBar } from './style';
|
||||
import appConfig from 'config/app.js';
|
||||
|
||||
const useNewFlowEditor = process.env.REACT_APP_USE_NEW_FLOW_EDITOR === 'true';
|
||||
const useNewFlowEditor = appConfig.useNewFlowEditor;
|
||||
|
||||
export default function EditorLayout() {
|
||||
const { flowId } = useParams();
|
||||
@@ -48,7 +49,7 @@ export default function EditorLayout() {
|
||||
});
|
||||
};
|
||||
|
||||
const onExportFlow = async (name) => {
|
||||
const onExportFlow = async () => {
|
||||
const flowExport = await exportFlow();
|
||||
|
||||
downloadJsonAsFile({
|
||||
|
||||
@@ -17,7 +17,7 @@ export default function Edge({
|
||||
const { flowActive, onStepAdd, isCreateStepPending } =
|
||||
useContext(EdgesContext);
|
||||
|
||||
const [edgePath, labelX, labelY] = getStraightPath({
|
||||
const [, labelX, labelY] = getStraightPath({
|
||||
sourceX,
|
||||
sourceY,
|
||||
targetX,
|
||||
|
||||
@@ -8,7 +8,7 @@ export const NodeWrapper = styled(Box)(({ theme }) => ({
|
||||
padding: theme.spacing(0, 2.5),
|
||||
}));
|
||||
|
||||
export const NodeInnerWrapper = styled(Box)(({ theme }) => ({
|
||||
export const NodeInnerWrapper = styled(Box)(() => ({
|
||||
maxWidth: 900,
|
||||
flex: 1,
|
||||
}));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Stack } from '@mui/material';
|
||||
import { styled } from '@mui/material/styles';
|
||||
|
||||
export const EditorWrapper = styled(Stack)(({ theme }) => ({
|
||||
export const EditorWrapper = styled(Stack)(() => ({
|
||||
flexGrow: 1,
|
||||
'& > div': {
|
||||
flexGrow: 1,
|
||||
|
||||
@@ -7,20 +7,16 @@ import {
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
Typography,
|
||||
useMediaQuery,
|
||||
} from '@mui/material';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { DateTime } from 'luxon';
|
||||
import { useState } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
|
||||
import Can from 'components/Can';
|
||||
import DatePickerInput from 'components/DatePickerInput';
|
||||
import useExecutionFilters from 'hooks/useExecutionFilters';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
|
||||
export default function ExecutionFilters({ onFilterChange }) {
|
||||
export default function ExecutionFilters() {
|
||||
const theme = useTheme();
|
||||
const formatMessage = useFormatMessage();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||
|
||||
@@ -185,7 +185,7 @@ ContextMenu.propTypes = {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
anchorEl: PropTypes.oneOfType([
|
||||
PropTypes.func,
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(Element) }),
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(window.Element) }),
|
||||
]).isRequired,
|
||||
onDuplicateFlow: PropTypes.func,
|
||||
appKey: PropTypes.string,
|
||||
|
||||
@@ -6,19 +6,17 @@ import {
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
Typography,
|
||||
useMediaQuery,
|
||||
Collapse,
|
||||
} from '@mui/material';
|
||||
import FilterAltIcon from '@mui/icons-material/FilterAlt';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
|
||||
import Can from 'components/Can';
|
||||
import useCurrentUserRuleConditions from 'hooks/useCurrentUserRuleConditions';
|
||||
import useFlowFilters from 'hooks/useFlowFilters';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
|
||||
export default function FlowFilters({ onFilterChange }) {
|
||||
export default function FlowFilters() {
|
||||
const theme = useTheme();
|
||||
const formatMessage = useFormatMessage();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||
|
||||
@@ -43,8 +43,9 @@ import useActions from 'hooks/useActions';
|
||||
import useTriggerSubsteps from 'hooks/useTriggerSubsteps';
|
||||
import useActionSubsteps from 'hooks/useActionSubsteps';
|
||||
import useStepWithTestExecutions from 'hooks/useStepWithTestExecutions';
|
||||
import appConfig from 'config/app.js';
|
||||
|
||||
const useNewFlowEditor = process.env.REACT_APP_USE_NEW_FLOW_EDITOR === 'true';
|
||||
const useNewFlowEditor = appConfig.useNewFlowEditor;
|
||||
|
||||
const validIcon = <CheckCircleIcon color="success" />;
|
||||
const errorIcon = <ErrorIcon color="error" />;
|
||||
|
||||
@@ -48,7 +48,7 @@ FlowStepContextMenu.propTypes = {
|
||||
onDelete: PropTypes.func,
|
||||
anchorEl: PropTypes.oneOfType([
|
||||
PropTypes.func,
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(Element) }),
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(window.Element) }),
|
||||
]),
|
||||
deletable: PropTypes.bool.isRequired,
|
||||
flowId: PropTypes.string.isRequired,
|
||||
|
||||
@@ -10,8 +10,9 @@ import FlowSubstepTitle from 'components/FlowSubstepTitle';
|
||||
import InputCreator from 'components/InputCreator';
|
||||
import FilterConditions from './FilterConditions';
|
||||
import { StepPropType, SubstepPropType } from 'propTypes/propTypes';
|
||||
import appConfig from 'config/app.js';
|
||||
|
||||
const useNewFlowEditor = process.env.REACT_APP_USE_NEW_FLOW_EDITOR === 'true';
|
||||
const useNewFlowEditor = appConfig.useNewFlowEditor;
|
||||
|
||||
function FlowSubstep(props) {
|
||||
const {
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Link, useSearchParams, useNavigate } from 'react-router-dom';
|
||||
import Box from '@mui/material/Box';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Card from '@mui/material/Card';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
@@ -24,7 +23,6 @@ import useFormatMessage from 'hooks/useFormatMessage';
|
||||
import useFolders from 'hooks/useFolders';
|
||||
import useDeleteFolder from 'hooks/useDeleteFolder';
|
||||
import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar';
|
||||
import objectifyUrlSearchParams from 'helpers/objectifyUrlSearchParams';
|
||||
import useFlowFilters from 'hooks/useFlowFilters';
|
||||
|
||||
import { ListItemIcon } from './style';
|
||||
|
||||
@@ -87,7 +87,7 @@ function Form(props) {
|
||||
return (
|
||||
<FormProvider {...methods}>
|
||||
<form
|
||||
onSubmit={methods.handleSubmit(async (data, event) => {
|
||||
onSubmit={methods.handleSubmit(async (data) => {
|
||||
try {
|
||||
return await onSubmit?.(data);
|
||||
} catch (errors) {
|
||||
|
||||
@@ -55,10 +55,10 @@ function ImportFlowDialog(props) {
|
||||
}
|
||||
};
|
||||
|
||||
const handleImportFlow = (event) => {
|
||||
const handleImportFlow = () => {
|
||||
if (!selectedFile) return;
|
||||
|
||||
const fileReader = new FileReader();
|
||||
const fileReader = new window.FileReader();
|
||||
|
||||
fileReader.onload = async function readFileLoaded(e) {
|
||||
const flowData = parseFlowFile(e.target.result);
|
||||
|
||||
@@ -6,7 +6,7 @@ import englishMessages from 'locales/en.json';
|
||||
const IntlProvider = ({ children }) => {
|
||||
return (
|
||||
<BaseIntlProvider
|
||||
locale={navigator.language.split('-')[0]}
|
||||
locale={window.navigator.language.split('-')[0]}
|
||||
defaultLocale="en"
|
||||
messages={englishMessages}
|
||||
>
|
||||
|
||||
@@ -2,13 +2,10 @@ import styled from '@emotion/styled';
|
||||
import Box from '@mui/material/Box';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import Link from '@mui/material/Link';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import SvgIcon from '@mui/material/SvgIcon';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
import useAutomatischConfig from 'hooks/useAutomatischConfig';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
import useVersion from 'hooks/useVersion';
|
||||
|
||||
const LogoImage = styled('img')(() => ({
|
||||
maxWidth: 'auto',
|
||||
@@ -16,7 +13,7 @@ const LogoImage = styled('img')(() => ({
|
||||
}));
|
||||
|
||||
const LayoutFooter = () => {
|
||||
const { data: config, isPending: isConfigPending } = useAutomatischConfig();
|
||||
const { data: config } = useAutomatischConfig();
|
||||
const formatMessage = useFormatMessage();
|
||||
|
||||
if (config?.data.enableFooter !== true) return null;
|
||||
@@ -34,22 +31,20 @@ const LayoutFooter = () => {
|
||||
href: config.data.footerTosUrl,
|
||||
text: formatMessage('footer.tosLinkText'),
|
||||
},
|
||||
|
||||
{
|
||||
key: 'privacy-policy',
|
||||
show: !!config.data.footerPrivacyPolicyUrl,
|
||||
href: config.data.footerPrivacyPolicyUrl,
|
||||
text: formatMessage('footer.privacyPolicyLinkText'),
|
||||
},
|
||||
|
||||
{
|
||||
key: 'imprint',
|
||||
show: !!config.data.footerImprintUrl,
|
||||
href: config.data.footerImprintUrl,
|
||||
text: formatMessage('footer.imprintLinkText'),
|
||||
},
|
||||
,
|
||||
];
|
||||
|
||||
return (
|
||||
<Box mt="auto" position="sticky" bottom={0}>
|
||||
<Box bgcolor="common.white" mt={4}>
|
||||
|
||||
@@ -15,7 +15,7 @@ function ListItemLink(props) {
|
||||
React.forwardRef(function InLineLink(linkProps, ref) {
|
||||
try {
|
||||
// challenge the link to check if it's absolute URL
|
||||
new URL(to); // should throw an error if it's not an absolute URL
|
||||
new window.URL(to); // should throw an error if it's not an absolute URL
|
||||
return (
|
||||
<a
|
||||
{...linkProps}
|
||||
|
||||
@@ -40,7 +40,9 @@ function LoginForm() {
|
||||
});
|
||||
const { token } = data;
|
||||
authentication.updateToken(token);
|
||||
} catch {}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const renderError = () => {
|
||||
@@ -49,7 +51,7 @@ function LoginForm() {
|
||||
];
|
||||
|
||||
return errors.map((error) => (
|
||||
<Alert severity="error" sx={{ mt: 2 }}>
|
||||
<Alert key={error} severity="error" sx={{ mt: 2 }}>
|
||||
{error}
|
||||
</Alert>
|
||||
));
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import { ReactComponent as MationLogoSvg } from './assets/mation-logo.svg';
|
||||
import MationLogoSvg from './assets/mation-logo.svg';
|
||||
|
||||
const MationLogo = () => {
|
||||
return <MationLogoSvg />;
|
||||
return <img src={MationLogoSvg} alt="Mation Logo" />;
|
||||
};
|
||||
|
||||
export default MationLogo;
|
||||
|
||||
@@ -3,22 +3,11 @@ import { useFormContext } from 'react-hook-form';
|
||||
import PropTypes from 'prop-types';
|
||||
import ControlledCheckbox from 'components/ControlledCheckbox';
|
||||
|
||||
const AllEntitiesPermissions = ({
|
||||
action,
|
||||
subject,
|
||||
disabled,
|
||||
name,
|
||||
syncIsCreator,
|
||||
}) => {
|
||||
const { getValues, formState, resetField } = useFormContext();
|
||||
const AllEntitiesPermissions = ({ action, subject, disabled, name }) => {
|
||||
const { getValues, resetField } = useFormContext();
|
||||
|
||||
const fieldName = `${name}.${subject.key}.${action.key}.allEntities`;
|
||||
const defaultValue =
|
||||
formState.defaultValues?.[name]?.[subject.key]?.[action.key].allEntities;
|
||||
const ownEntitiesFieldName = `${name}.${subject.key}.${action.key}.ownEntities`;
|
||||
const ownEntitiesFieldTouched =
|
||||
formState.touchedFields?.[name]?.[subject.key]?.[action.key]
|
||||
?.ownEntities === true;
|
||||
|
||||
const currentValue = getValues(fieldName);
|
||||
|
||||
@@ -28,16 +17,6 @@ const AllEntitiesPermissions = ({
|
||||
}
|
||||
}, [ownEntitiesFieldName, currentValue]);
|
||||
|
||||
const handleSyncIsCreator = (newValue) => {
|
||||
if (syncIsCreator && defaultValue === false && !ownEntitiesFieldTouched) {
|
||||
resetField(ownEntitiesFieldName, { defaultValue: newValue });
|
||||
}
|
||||
|
||||
if (newValue === true) {
|
||||
resetField(ownEntitiesFieldName, { defaultValue: true });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ControlledCheckbox
|
||||
disabled={disabled}
|
||||
|
||||
@@ -42,7 +42,7 @@ Popper.propTypes = {
|
||||
open: PropTypes.bool.isRequired,
|
||||
anchorEl: PropTypes.oneOfType([
|
||||
PropTypes.func,
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(Element) }),
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(window.Element) }),
|
||||
]),
|
||||
data: PropTypes.array.isRequired,
|
||||
onSuggestionClick: PropTypes.func,
|
||||
|
||||
@@ -28,11 +28,10 @@ const getPartialArray = (array, length = array.length) => {
|
||||
return array.slice(0, length);
|
||||
};
|
||||
|
||||
const renderItemFactory =
|
||||
({ onSuggestionClick }) =>
|
||||
(props) => (
|
||||
<SuggestionItem {...props} onSuggestionClick={onSuggestionClick} />
|
||||
);
|
||||
const renderItemFactory = ({ onSuggestionClick }) =>
|
||||
function RenderItem(props) {
|
||||
return <SuggestionItem {...props} onSuggestionClick={onSuggestionClick} />;
|
||||
};
|
||||
|
||||
const Suggestions = (props) => {
|
||||
const formatMessage = useFormatMessage();
|
||||
|
||||
@@ -50,7 +50,9 @@ export default function ResetPasswordForm() {
|
||||
},
|
||||
});
|
||||
navigate(URLS.LOGIN);
|
||||
} catch {}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const renderError = () => {
|
||||
@@ -63,7 +65,7 @@ export default function ResetPasswordForm() {
|
||||
];
|
||||
|
||||
return errors.map((error) => (
|
||||
<Alert severity="error" sx={{ mt: 2 }}>
|
||||
<Alert key={error} severity="error" sx={{ mt: 2 }}>
|
||||
{error}
|
||||
</Alert>
|
||||
));
|
||||
|
||||
@@ -23,7 +23,7 @@ export default function SplitButton(props) {
|
||||
setOpen((prevOpen) => !prevOpen);
|
||||
};
|
||||
|
||||
const handleClose = (event) => {
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
|
||||
@@ -15,8 +15,9 @@ import WebhookUrlInfo from 'components/WebhookUrlInfo';
|
||||
import FlowSubstepTitle from 'components/FlowSubstepTitle';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { StepPropType, SubstepPropType } from 'propTypes/propTypes';
|
||||
import appConfig from 'config/app.js';
|
||||
|
||||
const useNewFlowEditor = process.env.REACT_APP_USE_NEW_FLOW_EDITOR === 'true';
|
||||
const useNewFlowEditor = appConfig.useNewFlowEditor;
|
||||
|
||||
function TestSubstep(props) {
|
||||
const {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
const backendUrl = process.env.REACT_APP_BACKEND_URL;
|
||||
const backendUrl = import.meta.env.VITE_BACKEND_URL;
|
||||
|
||||
const computeUrl = (url, backendUrl) => {
|
||||
/**
|
||||
* In case `backendUrl` is a host, we append the url to it.
|
||||
**/
|
||||
try {
|
||||
return new URL(url, backendUrl).toString();
|
||||
} catch (e) {
|
||||
return new window.URL(url, backendUrl).toString();
|
||||
} catch {
|
||||
/*
|
||||
* In case `backendUrl` is not qualified, we utilize `url` alone.
|
||||
**/
|
||||
@@ -15,8 +15,9 @@ const computeUrl = (url, backendUrl) => {
|
||||
};
|
||||
|
||||
const config = {
|
||||
baseUrl: process.env.REACT_APP_BASE_URL,
|
||||
baseUrl: import.meta.env.VITE_BASE_URL,
|
||||
restApiUrl: computeUrl('/internal/api', backendUrl),
|
||||
useNewFlowEditor: import.meta.env.VITE_USE_NEW_FLOW_EDITOR === 'true',
|
||||
supportEmailAddress: 'support@automatisch.io',
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
const parseUrlSearchParams = (event) => {
|
||||
const searchParams = new URLSearchParams(event.data.payload.search);
|
||||
const hashParams = new URLSearchParams(event.data.payload.hash.substring(1));
|
||||
const searchParams = new window.URLSearchParams(event.data.payload.search);
|
||||
const hashParams = new window.URLSearchParams(
|
||||
event.data.payload.hash.substring(1),
|
||||
);
|
||||
const searchParamsObject = getObjectOfEntries(searchParams.entries());
|
||||
const hashParamsObject = getObjectOfEntries(hashParams.entries());
|
||||
|
||||
@@ -33,9 +35,9 @@ export const processPopupMessage = (popup) => {
|
||||
let closeCheckIntervalId;
|
||||
|
||||
if (popup) {
|
||||
closeCheckIntervalId = setInterval(() => {
|
||||
closeCheckIntervalId = window.setInterval(() => {
|
||||
if (popup.closed) {
|
||||
clearInterval(closeCheckIntervalId);
|
||||
window.clearInterval(closeCheckIntervalId);
|
||||
|
||||
reject({ message: 'Error occured while verifying credentials!' });
|
||||
}
|
||||
@@ -51,7 +53,7 @@ export const processPopupMessage = (popup) => {
|
||||
window.removeEventListener('message', messageHandler);
|
||||
|
||||
if (closeCheckIntervalId) {
|
||||
clearInterval(closeCheckIntervalId);
|
||||
window.clearInterval(closeCheckIntervalId);
|
||||
}
|
||||
|
||||
resolve(data);
|
||||
|
||||
@@ -2,13 +2,13 @@ const NAMESPACE = 'automatisch';
|
||||
const makeKey = (key) => `${NAMESPACE}.${key}`;
|
||||
|
||||
export const setItem = (key, value) => {
|
||||
return localStorage.setItem(makeKey(key), value);
|
||||
return window.localStorage.setItem(makeKey(key), value);
|
||||
};
|
||||
|
||||
export const getItem = (key) => {
|
||||
return localStorage.getItem(makeKey(key));
|
||||
return window.localStorage.getItem(makeKey(key));
|
||||
};
|
||||
|
||||
export const removeItem = (key) => {
|
||||
return localStorage.removeItem(makeKey(key));
|
||||
return window.localStorage.removeItem(makeKey(key));
|
||||
};
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import Link from '@mui/material/Link';
|
||||
|
||||
export const generateInternalLink = (link) => (str) => (
|
||||
<Link component={RouterLink} to={link}>
|
||||
{str}
|
||||
</Link>
|
||||
);
|
||||
export const generateInternalLink = (link) =>
|
||||
function LinkVariable(str) {
|
||||
return (
|
||||
<Link component={RouterLink} to={link}>
|
||||
{str}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export const generateExternalLink = (link) => (str) => (
|
||||
<Link href={link} target="_blank">
|
||||
{str}
|
||||
</Link>
|
||||
);
|
||||
export const generateExternalLink = (link) =>
|
||||
function LinkVariable(str) {
|
||||
return (
|
||||
<Link href={link} target="_blank">
|
||||
{str}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export const makeBold = (str) => <strong>{str}</strong>;
|
||||
|
||||
@@ -5,13 +5,13 @@ export default function useAdminDeleteRole(roleId) {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const query = useMutation({
|
||||
mutationFn: async (payload) => {
|
||||
mutationFn: async () => {
|
||||
const { data } = await api.delete(`/v1/admin/roles/${roleId}`);
|
||||
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
onSuccess: async () => {
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ['admin', 'roles'],
|
||||
});
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ const appendTrailingSlash = (url) => {
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Per instance, there may be different documentation. However, the paths are assumed the same.
|
||||
@@ -18,10 +18,12 @@ const appendTrailingSlash = (url) => {
|
||||
*/
|
||||
export default function useDocsUrl(path) {
|
||||
const { data: automatischInfo } = useAutomatischInfo();
|
||||
const docsUrlWithTrailingSlash = appendTrailingSlash(automatischInfo?.docsUrl);
|
||||
const docsUrlWithTrailingSlash = appendTrailingSlash(
|
||||
automatischInfo?.docsUrl,
|
||||
);
|
||||
const docsUrl = docsUrlWithTrailingSlash || 'https://automatisch.io/docs/';
|
||||
|
||||
const absoluteUrl = new URL(path, docsUrl).toString();
|
||||
const absoluteUrl = new window.URL(path, docsUrl).toString();
|
||||
|
||||
return absoluteUrl;
|
||||
}
|
||||
|
||||
@@ -12,11 +12,11 @@ export default function useDownloadJsonAsFile() {
|
||||
replacement: '-',
|
||||
});
|
||||
|
||||
const fileBlob = new Blob([stringifiedContents], {
|
||||
const fileBlob = new window.Blob([stringifiedContents], {
|
||||
type: 'application/json',
|
||||
});
|
||||
|
||||
const fileObjectUrl = URL.createObjectURL(fileBlob);
|
||||
const fileObjectUrl = window.URL.createObjectURL(fileBlob);
|
||||
|
||||
const temporaryDownloadLink = document.createElement('a');
|
||||
temporaryDownloadLink.href = fileObjectUrl;
|
||||
|
||||
@@ -92,7 +92,7 @@ function useDynamicData(stepId, schema) {
|
||||
lastComputedVariables.current = variables;
|
||||
|
||||
return variables;
|
||||
} catch (err) {
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ function useDynamicFields(stepId, schema) {
|
||||
}
|
||||
lastComputedVariables.current = variables;
|
||||
return variables;
|
||||
} catch (err) {
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import api from 'helpers/api';
|
||||
import objectifyUrlSearchParams from 'helpers/objectifyUrlSearchParams';
|
||||
|
||||
export default function useExecutionFilters() {
|
||||
@@ -21,7 +19,8 @@ export default function useExecutionFilters() {
|
||||
const endDateTime = parseInt(endDateTimeString, 10);
|
||||
|
||||
const filterByStatus = (status) => {
|
||||
setSearchParams((current) => {
|
||||
setSearchParams(() => {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { status: currentStatus, ...rest } = searchParamsObject;
|
||||
|
||||
if (status) {
|
||||
@@ -35,7 +34,8 @@ export default function useExecutionFilters() {
|
||||
const filterByStartDateTime = (startDateTime) => {
|
||||
const startDateTimeString = startDateTime?.toMillis();
|
||||
|
||||
setSearchParams((current) => {
|
||||
setSearchParams(() => {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { startDateTime: currentStartDateTime, ...rest } =
|
||||
searchParamsObject;
|
||||
|
||||
@@ -50,7 +50,8 @@ export default function useExecutionFilters() {
|
||||
const filterByEndDateTime = (endDateTime) => {
|
||||
const endDateTimeString = endDateTime?.endOf('day').toMillis();
|
||||
|
||||
setSearchParams((current) => {
|
||||
setSearchParams(() => {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { endDateTime: currentEndDateTime, ...rest } = searchParamsObject;
|
||||
|
||||
if (endDateTimeString) {
|
||||
@@ -65,13 +66,14 @@ export default function useExecutionFilters() {
|
||||
const searchParamsObject = objectifyUrlSearchParams(searchParams);
|
||||
|
||||
if (value === undefined) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { [key]: keyToRemove, ...remainingSearchParams } =
|
||||
searchParamsObject;
|
||||
|
||||
return new URLSearchParams(remainingSearchParams).toString();
|
||||
return new window.URLSearchParams(remainingSearchParams).toString();
|
||||
}
|
||||
|
||||
return new URLSearchParams({
|
||||
return new window.URLSearchParams({
|
||||
...searchParamsObject,
|
||||
[key]: value,
|
||||
}).toString();
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
|
||||
import api from 'helpers/api';
|
||||
import objectifyUrlSearchParams from 'helpers/objectifyUrlSearchParams';
|
||||
|
||||
export default function useFlowFilters() {
|
||||
@@ -14,7 +12,8 @@ export default function useFlowFilters() {
|
||||
searchParamsObject.onlyOwnedFlows === 'true' || undefined;
|
||||
|
||||
const filterByStatus = (status) => {
|
||||
setSearchParams((current) => {
|
||||
setSearchParams(() => {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { status: currentStatus, ...rest } = searchParamsObject;
|
||||
|
||||
if (status) {
|
||||
@@ -26,7 +25,8 @@ export default function useFlowFilters() {
|
||||
};
|
||||
|
||||
const filterByOwnership = (onlyOwnedFlows) => {
|
||||
setSearchParams((current) => {
|
||||
setSearchParams(() => {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { onlyOwnedFlows: currentOnlyOwnedFlows, ...rest } =
|
||||
searchParamsObject;
|
||||
|
||||
@@ -42,13 +42,14 @@ export default function useFlowFilters() {
|
||||
const searchParamsObject = objectifyUrlSearchParams(searchParams);
|
||||
|
||||
if (value === undefined) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { [key]: keyToRemove, ...remainingSearchParams } =
|
||||
searchParamsObject;
|
||||
|
||||
return new URLSearchParams(remainingSearchParams).toString();
|
||||
return new window.URLSearchParams(remainingSearchParams).toString();
|
||||
}
|
||||
|
||||
return new URLSearchParams({
|
||||
return new window.URLSearchParams({
|
||||
...searchParamsObject,
|
||||
[key]: value,
|
||||
}).toString();
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import userAbility from 'helpers/userAbility';
|
||||
import useCurrentUser from 'hooks/useCurrentUser';
|
||||
|
||||
export default function useIsCurrentUserAdmin() {
|
||||
|
||||
@@ -4,10 +4,10 @@ import api from 'helpers/api';
|
||||
import React from 'react';
|
||||
|
||||
export default function useLazyApps({ appName } = {}, { onSuccess } = {}) {
|
||||
const abortControllerRef = React.useRef(new AbortController());
|
||||
const abortControllerRef = React.useRef(new window.AbortController());
|
||||
|
||||
React.useEffect(() => {
|
||||
abortControllerRef.current = new AbortController();
|
||||
abortControllerRef.current = new window.AbortController();
|
||||
|
||||
return () => {
|
||||
abortControllerRef.current?.abort();
|
||||
|
||||
@@ -8,8 +8,7 @@ import MetadataProvider from 'components/MetadataProvider';
|
||||
import { AuthenticationProvider } from 'contexts/Authentication';
|
||||
import QueryClientProvider from 'components/QueryClientProvider';
|
||||
import Router from 'components/Router';
|
||||
import routes from 'routes';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
import routes from './routes';
|
||||
|
||||
// Sets the default locale to English for all luxon DateTime instances created afterwards.
|
||||
Settings.defaultLocale = 'en';
|
||||
@@ -32,8 +31,3 @@ root.render(
|
||||
</SnackbarProvider>
|
||||
</Router>,
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals();
|
||||
|
||||
@@ -61,7 +61,7 @@ function AdminTemplates() {
|
||||
defaultValues={{ enableTemplates: config?.data.enableTemplates }}
|
||||
noValidate
|
||||
automaticValidation={false}
|
||||
render={({ formState: { errors, isDirty } }) => (
|
||||
render={() => (
|
||||
<Switch
|
||||
name="enableTemplates"
|
||||
disabled={isUpdateConfigPending}
|
||||
|
||||
@@ -30,7 +30,9 @@ export default function CreateFlow() {
|
||||
const flowId = response.data?.id;
|
||||
|
||||
navigateToEditor(flowId);
|
||||
} catch {}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
initiate();
|
||||
|
||||
@@ -25,9 +25,6 @@ export default function Executions() {
|
||||
const navigate = useNavigate();
|
||||
const page = parseInt(searchParams.get('page') || '', 10) || 1;
|
||||
const name = searchParams.get('name') || '';
|
||||
const status = searchParams.get('status');
|
||||
const startDateTime = searchParams.get('startDateTime');
|
||||
const endDateTime = searchParams.get('endDateTime');
|
||||
const [searchValue, setSearchValue] = React.useState(name);
|
||||
|
||||
const {
|
||||
@@ -61,7 +58,7 @@ export default function Executions() {
|
||||
const getPathWithSearchParams = (page) => {
|
||||
const searchParamsObject = objectifyUrlSearchParams(searchParams);
|
||||
|
||||
const newSearchParams = new URLSearchParams({
|
||||
const newSearchParams = new window.URLSearchParams({
|
||||
...searchParamsObject,
|
||||
page,
|
||||
});
|
||||
|
||||
@@ -73,7 +73,7 @@ export default function Flows() {
|
||||
const getPathWithSearchParams = (page) => {
|
||||
const searchParamsObject = objectifyUrlSearchParams(searchParams);
|
||||
|
||||
const newSearchParams = new URLSearchParams({
|
||||
const newSearchParams = new window.URLSearchParams({
|
||||
...searchParamsObject,
|
||||
page,
|
||||
});
|
||||
|
||||
@@ -87,7 +87,7 @@ export default function UserInterface() {
|
||||
'data-test': 'snackbar-update-user-interface-success',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
} catch {
|
||||
throw new Error('Failed while updating!');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
const reportWebVitals = (onPerfEntry) => {
|
||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||
getCLS(onPerfEntry);
|
||||
getFID(onPerfEntry);
|
||||
getFCP(onPerfEntry);
|
||||
getLCP(onPerfEntry);
|
||||
getTTFB(onPerfEntry);
|
||||
});
|
||||
}
|
||||
};
|
||||
export default reportWebVitals;
|
||||
@@ -15,7 +15,6 @@ import Application from 'pages/Application';
|
||||
import Executions from 'pages/Executions';
|
||||
import Execution from 'pages/Execution';
|
||||
import Flows from 'pages/Flows';
|
||||
import Flow from 'pages/Flow';
|
||||
import Login from 'pages/Login';
|
||||
import AcceptInvitation from 'pages/AcceptInvitation';
|
||||
import LoginCallback from 'pages/LoginCallback';
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom';
|
||||
Reference in New Issue
Block a user