refactor(web): replace CRA with Vite

This commit is contained in:
Ali BARIN
2025-04-28 16:16:11 +00:00
parent 1f6010bdea
commit f9772b6305
74 changed files with 2054 additions and 7400 deletions

View File

@@ -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,
};

View File

@@ -43,7 +43,7 @@ function AdminApplicationSettings({ appKey }) {
'data-test': 'snackbar-save-admin-apps-settings-success',
},
});
} catch (error) {
} catch {
throw new Error('Failed while saving!');
}
};

View File

@@ -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'), {

View File

@@ -24,7 +24,6 @@ import useCurrentUserAbility from 'hooks/useCurrentUserAbility';
import Footer from './Footer';
function createDrawerLinks({
canCreateFlows,
canReadRole,
canReadUser,
canUpdateConfig,

View File

@@ -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,
};

View File

@@ -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) }),
]),
};

View File

@@ -43,7 +43,7 @@ function AppConnectionRow(props) {
{ connectionId: id },
{
onSettled: () => {
setTimeout(() => setVerificationVisible(false), 3000);
window.setTimeout(() => setVerificationVisible(false), 3000);
},
},
);

View File

@@ -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,

View File

@@ -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';

View File

@@ -20,7 +20,7 @@ function CodeEditor(props) {
'data-test': dataTest,
} = props;
const handleEditorOnMount = (editor, monaco) => {
const handleEditorOnMount = (editor) => {
editorRef.current = editor;
editor.onDidContentSizeChange((event) => {

View File

@@ -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({

View File

@@ -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();

View File

@@ -89,7 +89,7 @@ function ControlledCustomAutocomplete(props) {
};
const resizeObserver = React.useMemo(function syncCustomOptionsPosition() {
return new ResizeObserver(() => {
return new window.ResizeObserver(() => {
forceUpdate();
});
}, []);

View File

@@ -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,

View File

@@ -39,7 +39,9 @@ function DeleteApiTokenButton(props) {
},
},
);
} catch {}
} catch (error) {
console.error(error);
}
}, [deleteApiToken]);
const handleClose = () => {

View File

@@ -43,7 +43,9 @@ function DeleteRoleButton(props) {
'data-test': 'snackbar-delete-role-success',
},
});
} catch {}
} catch (error) {
console.error(error);
}
}, [deleteRole, enqueueSnackbar, formatMessage]);
const handleClose = () => {

View File

@@ -39,7 +39,9 @@ function DeleteUserButton(props) {
'data-test': 'snackbar-delete-user-success',
},
});
} catch {}
} catch (error) {
console.error(error);
}
}, [deleteUser]);
const handleClose = () => {

View File

@@ -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;

View File

@@ -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({

View File

@@ -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,

View File

@@ -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,
}));

View File

@@ -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,

View File

@@ -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'));

View File

@@ -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,

View File

@@ -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'));

View File

@@ -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" />;

View File

@@ -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,

View File

@@ -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 {

View File

@@ -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';

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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}
>

View File

@@ -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}>

View File

@@ -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}

View File

@@ -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>
));

View File

@@ -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;

View File

@@ -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}

View File

@@ -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,

View File

@@ -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();

View File

@@ -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>
));

View File

@@ -23,7 +23,7 @@ export default function SplitButton(props) {
setOpen((prevOpen) => !prevOpen);
};
const handleClose = (event) => {
const handleClose = () => {
setOpen(false);
};

View File

@@ -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 {

View File

@@ -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',
};

View File

@@ -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);

View File

@@ -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));
};

View File

@@ -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>;

View File

@@ -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'],
});
},

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -92,7 +92,7 @@ function useDynamicData(stepId, schema) {
lastComputedVariables.current = variables;
return variables;
} catch (err) {
} catch {
return null;
}
}

View File

@@ -61,7 +61,7 @@ function useDynamicFields(stepId, schema) {
}
lastComputedVariables.current = variables;
return variables;
} catch (err) {
} catch {
return null;
}
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -1,4 +1,3 @@
import userAbility from 'helpers/userAbility';
import useCurrentUser from 'hooks/useCurrentUser';
export default function useIsCurrentUserAdmin() {

View File

@@ -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();

View File

@@ -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();

View File

@@ -61,7 +61,7 @@ function AdminTemplates() {
defaultValues={{ enableTemplates: config?.data.enableTemplates }}
noValidate
automaticValidation={false}
render={({ formState: { errors, isDirty } }) => (
render={() => (
<Switch
name="enableTemplates"
disabled={isUpdateConfigPending}

View File

@@ -30,7 +30,9 @@ export default function CreateFlow() {
const flowId = response.data?.id;
navigateToEditor(flowId);
} catch {}
} catch (error) {
console.error(error);
}
}
initiate();

View File

@@ -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,
});

View File

@@ -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,
});

View File

@@ -87,7 +87,7 @@ export default function UserInterface() {
'data-test': 'snackbar-update-user-interface-success',
},
});
} catch (error) {
} catch {
throw new Error('Failed while updating!');
}
};

View File

@@ -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;

View File

@@ -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';

View File

@@ -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';