Compare commits

..

16 Commits

Author SHA1 Message Date
Ali BARIN
579638f932 Merge pull request #2210 from automatisch/release/v0.14.0
Update version to 0.14.0
2024-11-18 17:32:18 +01:00
Faruk AYDIN
48871c82a6 Update version to 0.14.0 2024-11-18 15:43:23 +00:00
Ali BARIN
14056c42ef Merge pull request #2211 from automatisch/upgrade-lerna
chore(deps): upgrade lerna with version 8
2024-11-18 16:42:08 +01:00
Ali BARIN
90fe1576de chore(lerna): remove bootstrap command usages 2024-11-18 15:00:49 +00:00
Ali BARIN
d61cf13985 chore(deps): upgrade lerna with version 8 2024-11-18 14:47:54 +00:00
Ali BARIN
dfe6dfd0c6 Merge pull request #2196 from automatisch/AUT-1364
feat: inline login form error and unify Alert font weight
2024-11-18 11:08:58 +01:00
Ali BARIN
c138c7d0e9 Merge pull request #2190 from automatisch/AUT-1347
feat: persist pagination and search value on flows page
2024-11-18 11:07:34 +01:00
Ali BARIN
d542be947e Merge pull request #2186 from automatisch/test-saml-auth-provider
test: Implement tests for saml auth provider url methods
2024-11-15 14:45:46 +01:00
kasia.oczkowska
c76366e72e feat: introduce improvements 2024-11-15 10:37:18 +00:00
kasia.oczkowska
75abfda783 feat: inline login form error and unify Alert font weight 2024-11-14 14:10:07 +00:00
Ali BARIN
f3d8d7d4ad Merge pull request #2191 from automatisch/AUT-1280
feat: make Wordpress instanceUrl field required
2024-11-14 12:31:43 +01:00
Ömer Faruk Aydın
7255eccb22 Merge pull request #2183 from automatisch/aut-1350-updatePassword
test(user): write tests for updatePassword
2024-11-13 19:31:28 +01:00
Ali BARIN
a0decb70cc test(user): write tests for updatePassword 2024-11-13 19:22:04 +01:00
kasia.oczkowska
532f562495 feat: make Wordpress instanceUrl field required 2024-11-13 14:32:16 +00:00
kasia.oczkowska
27e58ae925 feat: persist pagination and search value on flows page 2024-11-13 13:44:05 +00:00
Faruk AYDIN
4867ffcb4b test: Implement tests for saml auth provider url methods 2024-11-12 13:12:00 +01:00
23 changed files with 1816 additions and 2151 deletions

View File

@@ -34,7 +34,6 @@ cd $CURRENT_DIR
echo "Installing and linking dependencies..." echo "Installing and linking dependencies..."
yarn yarn
yarn lerna bootstrap
echo "Migrating database..." echo "Migrating database..."
cd packages/backend cd packages/backend

View File

@@ -38,7 +38,7 @@ jobs:
cache-dependency-path: yarn.lock cache-dependency-path: yarn.lock
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner." - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner." - run: echo "🖥️ The workflow is now ready to test your code on the runner."
- run: yarn --frozen-lockfile && yarn lerna bootstrap - run: yarn --frozen-lockfile
- run: cd packages/backend && yarn start - run: cd packages/backend && yarn start
env: env:
ENCRYPTION_KEY: sample_encryption_key ENCRYPTION_KEY: sample_encryption_key
@@ -58,7 +58,7 @@ jobs:
cache-dependency-path: yarn.lock cache-dependency-path: yarn.lock
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner." - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner." - run: echo "🖥️ The workflow is now ready to test your code on the runner."
- run: yarn --frozen-lockfile && yarn lerna bootstrap - run: yarn --frozen-lockfile
- run: cd packages/backend && yarn start:worker - run: cd packages/backend && yarn start:worker
env: env:
ENCRYPTION_KEY: sample_encryption_key ENCRYPTION_KEY: sample_encryption_key
@@ -78,7 +78,7 @@ jobs:
cache-dependency-path: yarn.lock cache-dependency-path: yarn.lock
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner." - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner." - run: echo "🖥️ The workflow is now ready to test your code on the runner."
- run: yarn --frozen-lockfile && yarn lerna bootstrap - run: yarn --frozen-lockfile
- run: cd packages/web && yarn build - run: cd packages/web && yarn build
env: env:
CI: false CI: false

View File

@@ -59,7 +59,7 @@ jobs:
with: with:
node-version: 18 node-version: 18
- name: Install dependencies - name: Install dependencies
run: yarn && yarn lerna bootstrap run: yarn
- name: Install Playwright Browsers - name: Install Playwright Browsers
run: yarn playwright install --with-deps run: yarn playwright install --with-deps
- name: Build Automatisch web - name: Build Automatisch web

View File

@@ -1,13 +1,11 @@
{ {
"packages": [ "packages": ["packages/*"],
"packages/*" "version": "0.14.0",
],
"version": "0.10.0",
"npmClient": "yarn", "npmClient": "yarn",
"useWorkspaces": true,
"command": { "command": {
"add": { "add": {
"exact": true "exact": true
} }
} },
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
} }

View File

@@ -23,7 +23,7 @@
"eslint": "^8.13.0", "eslint": "^8.13.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"lerna": "^4.0.0", "lerna": "^8.0.0",
"prettier": "^2.5.1" "prettier": "^2.5.1"
}, },
"publishConfig": { "publishConfig": {

View File

@@ -8,7 +8,7 @@ export default {
key: 'instanceUrl', key: 'instanceUrl',
label: 'WordPress instance URL', label: 'WordPress instance URL',
type: 'string', type: 'string',
required: false, required: true,
readOnly: false, readOnly: false,
value: null, value: null,
placeholder: null, placeholder: null,

View File

@@ -52,7 +52,7 @@ const appConfig = {
isDev: appEnv === 'development', isDev: appEnv === 'development',
isTest: appEnv === 'test', isTest: appEnv === 'test',
isProd: appEnv === 'production', isProd: appEnv === 'production',
version: '0.13.1', version: '0.14.0',
postgresDatabase: process.env.POSTGRES_DATABASE || 'automatisch_development', postgresDatabase: process.env.POSTGRES_DATABASE || 'automatisch_development',
postgresSchema: process.env.POSTGRES_SCHEMA || 'public', postgresSchema: process.env.POSTGRES_SCHEMA || 'public',
postgresPort: parseInt(process.env.POSTGRES_PORT || '5432'), postgresPort: parseInt(process.env.POSTGRES_PORT || '5432'),

View File

@@ -10,7 +10,7 @@ describe('GET /api/v1/automatisch/version', () => {
const expectedPayload = { const expectedPayload = {
data: { data: {
version: '0.13.1', version: '0.14.0',
}, },
meta: { meta: {
count: 1, count: 1,

View File

@@ -1,8 +1,9 @@
import { describe, it, expect } from 'vitest'; import { vi, describe, it, expect } from 'vitest';
import SamlAuthProvider from '../models/saml-auth-provider.ee'; import SamlAuthProvider from '../models/saml-auth-provider.ee';
import SamlAuthProvidersRoleMapping from '../models/saml-auth-providers-role-mapping.ee'; import SamlAuthProvidersRoleMapping from '../models/saml-auth-providers-role-mapping.ee';
import Identity from './identity.ee'; import Identity from './identity.ee';
import Base from './base'; import Base from './base';
import appConfig from '../config/app';
describe('SamlAuthProvider model', () => { describe('SamlAuthProvider model', () => {
it('tableName should return correct name', () => { it('tableName should return correct name', () => {
@@ -45,4 +46,39 @@ describe('SamlAuthProvider model', () => {
expect(virtualAttributes).toStrictEqual(expectedAttributes); expect(virtualAttributes).toStrictEqual(expectedAttributes);
}); });
it('loginUrl should return the URL of login', () => {
const samlAuthProvider = new SamlAuthProvider();
samlAuthProvider.issuer = 'sample-issuer';
vi.spyOn(appConfig, 'baseUrl', 'get').mockReturnValue(
'https://automatisch.io'
);
expect(samlAuthProvider.loginUrl).toStrictEqual(
'https://automatisch.io/login/saml/sample-issuer'
);
});
it('loginCallbackUrl should return the URL of login callback', () => {
const samlAuthProvider = new SamlAuthProvider();
samlAuthProvider.issuer = 'sample-issuer';
vi.spyOn(appConfig, 'baseUrl', 'get').mockReturnValue(
'https://automatisch.io'
);
expect(samlAuthProvider.loginCallBackUrl).toStrictEqual(
'https://automatisch.io/login/saml/sample-issuer/callback'
);
});
it('remoteLogoutUrl should return the URL from entrypoint', () => {
const samlAuthProvider = new SamlAuthProvider();
samlAuthProvider.entryPoint = 'https://example.com/saml/logout';
expect(samlAuthProvider.remoteLogoutUrl).toStrictEqual(
'https://example.com/saml/logout'
);
});
}); });

View File

@@ -580,4 +580,28 @@ describe('User model', () => {
expect(refetchedUser.invitationTokenSentAt).toBe(null); expect(refetchedUser.invitationTokenSentAt).toBe(null);
expect(refetchedUser.status).toBe('active'); expect(refetchedUser.status).toBe('active');
}); });
describe('updatePassword', () => {
it('should update password when the given current password matches with the user password', async () => {
const user = await createUser({ password: 'sample-password' });
const updatedUser = await user.updatePassword({
currentPassword: 'sample-password',
password: 'new-password',
});
expect(await updatedUser.login('new-password')).toBe(true);
});
it('should throw validation error when the given current password does not match with the user password', async () => {
const user = await createUser({ password: 'sample-password' });
await expect(
user.updatePassword({
currentPassword: 'wrong-password',
password: 'new-password',
})
).rejects.toThrowError('currentPassword: is incorrect.');
});
});
}); });

View File

@@ -112,7 +112,7 @@ export default function ResetPasswordForm() {
<Alert <Alert
data-test="accept-invitation-form-error" data-test="accept-invitation-form-error"
severity="error" severity="error"
sx={{ mt: 1, fontWeight: 500 }} sx={{ mt: 1 }}
> >
{formatMessage('acceptInvitationForm.invalidToken')} {formatMessage('acceptInvitationForm.invalidToken')}
</Alert> </Alert>

View File

@@ -126,7 +126,7 @@ function AddAppConnection(props) {
</DialogTitle> </DialogTitle>
{authDocUrl && ( {authDocUrl && (
<Alert severity="info" sx={{ fontWeight: 300 }}> <Alert severity="info">
{formatMessage('addAppConnection.callToDocs', { {formatMessage('addAppConnection.callToDocs', {
appName: name, appName: name,
docsLink: generateExternalLink(authDocUrl), docsLink: generateExternalLink(authDocUrl),
@@ -138,7 +138,7 @@ function AddAppConnection(props) {
<Alert <Alert
data-test="add-connection-error" data-test="add-connection-error"
severity="error" severity="error"
sx={{ mt: 1, fontWeight: 500, wordBreak: 'break-all' }} sx={{ mt: 1, wordBreak: 'break-all' }}
> >
{!errorDetails && errorMessage} {!errorDetails && errorMessage}
{errorDetails && ( {errorDetails && (

View File

@@ -32,10 +32,7 @@ function AdminApplicationAuthClientDialog(props) {
<Dialog open={true} onClose={onClose}> <Dialog open={true} onClose={onClose}>
<DialogTitle>{title}</DialogTitle> <DialogTitle>{title}</DialogTitle>
{error && ( {error && (
<Alert <Alert severity="error" sx={{ mt: 1, wordBreak: 'break-all' }}>
severity="error"
sx={{ mt: 1, fontWeight: 500, wordBreak: 'break-all' }}
>
{error.message} {error.message}
</Alert> </Alert>
)} )}

View File

@@ -188,7 +188,7 @@ function InstallationForm() {
)} )}
/> />
{install.isSuccess && ( {install.isSuccess && (
<Alert data-test="success-alert" severity="success" sx={{ mt: 3, fontWeight: 500 }}> <Alert data-test="success-alert" severity="success" sx={{ mt: 3 }}>
{formatMessage('installationForm.success', { {formatMessage('installationForm.success', {
link: (str) => ( link: (str) => (
<Link <Link

View File

@@ -11,16 +11,19 @@ import Form from 'components/Form';
import TextField from 'components/TextField'; import TextField from 'components/TextField';
import useFormatMessage from 'hooks/useFormatMessage'; import useFormatMessage from 'hooks/useFormatMessage';
import useCreateAccessToken from 'hooks/useCreateAccessToken'; import useCreateAccessToken from 'hooks/useCreateAccessToken';
import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar'; import { Alert } from '@mui/material';
function LoginForm() { function LoginForm() {
const isCloud = useCloud(); const isCloud = useCloud();
const navigate = useNavigate(); const navigate = useNavigate();
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const enqueueSnackbar = useEnqueueSnackbar();
const authentication = useAuthentication(); const authentication = useAuthentication();
const { mutateAsync: createAccessToken, isPending: loading } = const {
useCreateAccessToken(); mutateAsync: createAccessToken,
isPending: loading,
error,
isError,
} = useCreateAccessToken();
React.useEffect(() => { React.useEffect(() => {
if (authentication.isAuthenticated) { if (authentication.isAuthenticated) {
@@ -37,23 +40,19 @@ function LoginForm() {
}); });
const { token } = data; const { token } = data;
authentication.updateToken(token); authentication.updateToken(token);
} catch (error) { } catch {}
const errors = error?.response?.data?.errors };
? Object.values(error.response.data.errors)
: [];
if (errors.length) { const renderError = () => {
for (const [error] of errors) { const errors = error?.response?.data?.errors?.general || [
enqueueSnackbar(error, { formatMessage('loginForm.error'),
variant: 'error', ];
});
} return errors.map((error) => (
} else { <Alert severity="error" sx={{ mt: 2 }}>
enqueueSnackbar(error?.message || formatMessage('loginForm.error'), { {error}
variant: 'error', </Alert>
}); ));
}
}
}; };
return ( return (
@@ -106,6 +105,8 @@ function LoginForm() {
</Link> </Link>
)} )}
{isError && renderError()}
<LoadingButton <LoadingButton
type="submit" type="submit"
variant="contained" variant="contained"

View File

@@ -7,7 +7,7 @@ import FormControl from '@mui/material/FormControl';
import SearchIcon from '@mui/icons-material/Search'; import SearchIcon from '@mui/icons-material/Search';
import useFormatMessage from 'hooks/useFormatMessage'; import useFormatMessage from 'hooks/useFormatMessage';
export default function SearchInput({ onChange }) { export default function SearchInput({ onChange, defaultValue = '' }) {
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
return ( return (
<FormControl variant="outlined" fullWidth> <FormControl variant="outlined" fullWidth>
@@ -16,6 +16,7 @@ export default function SearchInput({ onChange }) {
</InputLabel> </InputLabel>
<OutlinedInput <OutlinedInput
defaultValue={defaultValue}
id="search-input" id="search-input"
type="text" type="text"
size="medium" size="medium"
@@ -34,4 +35,5 @@ export default function SearchInput({ onChange }) {
SearchInput.propTypes = { SearchInput.propTypes = {
onChange: PropTypes.func, onChange: PropTypes.func,
defaultValue: PropTypes.string,
}; };

View File

@@ -84,10 +84,7 @@ function TestSubstep(props) {
}} }}
> >
{hasError && ( {hasError && (
<Alert <Alert severity="error" sx={{ mb: 2, width: '100%' }}>
severity="error"
sx={{ mb: 2, fontWeight: 500, width: '100%' }}
>
<pre style={{ margin: 0, whiteSpace: 'pre-wrap' }}> <pre style={{ margin: 0, whiteSpace: 'pre-wrap' }}>
{JSON.stringify(errorDetails, null, 2)} {JSON.stringify(errorDetails, null, 2)}
</pre> </pre>
@@ -104,13 +101,11 @@ function TestSubstep(props) {
severity="warning" severity="warning"
sx={{ mb: 1, width: '100%' }} sx={{ mb: 1, width: '100%' }}
> >
<AlertTitle sx={{ fontWeight: 700 }}> <AlertTitle>
{formatMessage('flowEditor.noTestDataTitle')} {formatMessage('flowEditor.noTestDataTitle')}
</AlertTitle> </AlertTitle>
<Box sx={{ fontWeight: 400 }}> <Box>{formatMessage('flowEditor.noTestDataMessage')}</Box>
{formatMessage('flowEditor.noTestDataMessage')}
</Box>
</Alert> </Alert>
)} )}

View File

@@ -124,7 +124,6 @@ export default function CreateUser() {
<Alert <Alert
severity="info" severity="info"
color="primary" color="primary"
sx={{ fontWeight: '500' }}
data-test="invitation-email-info-alert" data-test="invitation-email-info-alert"
> >
{formatMessage('createUser.invitationEmailInfo', { {formatMessage('createUser.invitationEmailInfo', {

View File

@@ -42,13 +42,9 @@ export default function Execution() {
<Grid container item sx={{ mt: 2, mb: [2, 5] }} rowGap={3}> <Grid container item sx={{ mt: 2, mb: [2, 5] }} rowGap={3}>
{!isExecutionStepsLoading && !data?.pages?.[0].data.length && ( {!isExecutionStepsLoading && !data?.pages?.[0].data.length && (
<Alert severity="warning" sx={{ flex: 1 }}> <Alert severity="warning" sx={{ flex: 1 }}>
<AlertTitle sx={{ fontWeight: 700 }}> <AlertTitle>{formatMessage('execution.noDataTitle')}</AlertTitle>
{formatMessage('execution.noDataTitle')}
</AlertTitle>
<Box sx={{ fontWeight: 400 }}> <Box>{formatMessage('execution.noDataMessage')}</Box>
{formatMessage('execution.noDataMessage')}
</Box>
</Alert> </Alert>
)} )}

View File

@@ -1,5 +1,5 @@
import * as React from 'react'; import * as React from 'react';
import { Link, useSearchParams } from 'react-router-dom'; import { Link, useNavigate, useSearchParams } from 'react-router-dom';
import debounce from 'lodash/debounce'; import debounce from 'lodash/debounce';
import Box from '@mui/material/Box'; import Box from '@mui/material/Box';
import Grid from '@mui/material/Grid'; import Grid from '@mui/material/Grid';
@@ -23,13 +23,18 @@ import useLazyFlows from 'hooks/useLazyFlows';
export default function Flows() { export default function Flows() {
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const navigate = useNavigate();
const [searchParams, setSearchParams] = useSearchParams(); const [searchParams, setSearchParams] = useSearchParams();
const page = parseInt(searchParams.get('page') || '', 10) || 1; const page = parseInt(searchParams.get('page') || '', 10) || 1;
const [flowName, setFlowName] = React.useState(''); const flowName = searchParams.get('flowName') || '';
const [isLoading, setIsLoading] = React.useState(false); const [isLoading, setIsLoading] = React.useState(true);
const currentUserAbility = useCurrentUserAbility(); const currentUserAbility = useCurrentUserAbility();
const { data, mutate: fetchFlows } = useLazyFlows( const {
data,
mutate: fetchFlows,
isSuccess,
} = useLazyFlows(
{ flowName, page }, { flowName, page },
{ {
onSettled: () => { onSettled: () => {
@@ -38,6 +43,36 @@ export default function Flows() {
}, },
); );
const flows = data?.data || [];
const pageInfo = data?.meta;
const hasFlows = flows?.length;
const navigateToLastPage = isSuccess && !hasFlows && page > 1;
const onSearchChange = React.useCallback((event) => {
setSearchParams({ flowName: event.target.value });
}, []);
const getPathWithSearchParams = (page, flowName) => {
const searchParams = new URLSearchParams();
if (page > 1) {
searchParams.set('page', page);
}
if (flowName) {
searchParams.set('flowName', flowName);
}
return { search: searchParams.toString() };
};
const onDuplicateFlow = () => {
if (pageInfo?.currentPage > 1) {
navigate(getPathWithSearchParams(1, flowName));
} else {
fetchFlows();
}
};
const fetchData = React.useMemo( const fetchData = React.useMemo(
() => debounce(fetchFlows, 300), () => debounce(fetchFlows, 300),
[fetchFlows], [fetchFlows],
@@ -54,21 +89,14 @@ export default function Flows() {
}, [fetchData, flowName, page]); }, [fetchData, flowName, page]);
React.useEffect( React.useEffect(
function resetPageOnSearch() { function redirectToLastPage() {
// reset search params which only consists of `page` if (navigateToLastPage) {
setSearchParams({}); navigate(getPathWithSearchParams(pageInfo.totalPages, flowName));
}
}, },
[flowName], [navigateToLastPage],
); );
const flows = data?.data || [];
const pageInfo = data?.meta;
const hasFlows = flows?.length;
const onSearchChange = React.useCallback((event) => {
setFlowName(event.target.value);
}, []);
return ( return (
<Box sx={{ py: 3 }}> <Box sx={{ py: 3 }}>
<Container> <Container>
@@ -78,7 +106,7 @@ export default function Flows() {
</Grid> </Grid>
<Grid item xs={12} sm="auto" order={{ xs: 2, sm: 1 }}> <Grid item xs={12} sm="auto" order={{ xs: 2, sm: 1 }}>
<SearchInput onChange={onSearchChange} /> <SearchInput onChange={onSearchChange} defaultValue={flowName} />
</Grid> </Grid>
<Grid <Grid
@@ -111,7 +139,7 @@ export default function Flows() {
</Grid> </Grid>
<Divider sx={{ mt: [2, 0], mb: 2 }} /> <Divider sx={{ mt: [2, 0], mb: 2 }} />
{isLoading && ( {(isLoading || navigateToLastPage) && (
<CircularProgress sx={{ display: 'block', margin: '20px auto' }} /> <CircularProgress sx={{ display: 'block', margin: '20px auto' }} />
)} )}
{!isLoading && {!isLoading &&
@@ -119,11 +147,11 @@ export default function Flows() {
<FlowRow <FlowRow
key={flow.id} key={flow.id}
flow={flow} flow={flow}
onDuplicateFlow={fetchFlows} onDuplicateFlow={onDuplicateFlow}
onDeleteFlow={fetchFlows} onDeleteFlow={fetchFlows}
/> />
))} ))}
{!isLoading && !hasFlows && ( {!isLoading && !navigateToLastPage && !hasFlows && (
<NoResultFound <NoResultFound
text={formatMessage('flows.noFlows')} text={formatMessage('flows.noFlows')}
{...(currentUserAbility.can('create', 'Flow') && { {...(currentUserAbility.can('create', 'Flow') && {
@@ -131,18 +159,18 @@ export default function Flows() {
})} })}
/> />
)} )}
{!isLoading && pageInfo && pageInfo.totalPages > 1 && ( {!isLoading &&
!navigateToLastPage &&
pageInfo &&
pageInfo.totalPages > 1 && (
<Pagination <Pagination
sx={{ display: 'flex', justifyContent: 'center', mt: 3 }} sx={{ display: 'flex', justifyContent: 'center', mt: 3 }}
page={pageInfo?.currentPage} page={pageInfo?.currentPage}
count={pageInfo?.totalPages} count={pageInfo?.totalPages}
onChange={(event, page) =>
setSearchParams({ page: page.toString() })
}
renderItem={(item) => ( renderItem={(item) => (
<PaginationItem <PaginationItem
component={Link} component={Link}
to={`${item.page === 1 ? '' : `?page=${item.page}`}`} to={getPathWithSearchParams(item.page, flowName)}
{...item} {...item}
/> />
)} )}

View File

@@ -266,8 +266,8 @@ function ProfileSettings() {
</Grid> </Grid>
<Grid item xs={12} justifyContent="flex-end" sx={{ pt: 5 }}> <Grid item xs={12} justifyContent="flex-end" sx={{ pt: 5 }}>
<Alert variant="outlined" severity="error" sx={{ fontWeight: 500 }}> <Alert variant="outlined" severity="error">
<AlertTitle sx={{ fontWeight: 700 }}> <AlertTitle>
{formatMessage('profileSettings.deleteMyAccount')} {formatMessage('profileSettings.deleteMyAccount')}
</AlertTitle> </AlertTitle>

View File

@@ -278,6 +278,20 @@ export const defaultTheme = createTheme({
}), }),
}, },
}, },
MuiAlert: {
styleOverrides: {
root: ({ theme }) => ({
fontWeight: theme.typography.fontWeightRegular,
}),
},
},
MuiAlertTitle: {
styleOverrides: {
root: ({ theme }) => ({
fontWeight: theme.typography.fontWeightBold,
}),
},
},
}, },
}); });
export const mationTheme = createTheme( export const mationTheme = createTheme(

3680
yarn.lock

File diff suppressed because it is too large Load Diff