fix: style

This commit is contained in:
Convly 2024-05-30 13:34:00 +02:00
parent 51ac889697
commit 33413bf56c
17 changed files with 306 additions and 307 deletions

View File

@ -15,14 +15,14 @@ function createContext<ContextValueType extends object | null>(
const Context = ContextSelector.createContext<ContextValueType | undefined>(defaultContext);
const Provider = (props: ContextValueType & { children: React.ReactNode }) => {
const {children, ...context} = props;
const { children, ...context } = props;
// Only re-memoize when prop values change
// eslint-disable-next-line react-hooks/exhaustive-deps
const value = React.useMemo(() => context, Object.values(context)) as ContextValueType;
return <Context.Provider value={value}>{children}</Context.Provider>;
};
const useContext = <Selected, >(
const useContext = <Selected,>(
consumerName: string,
selector: (value: ContextValueType) => Selected
): Selected =>
@ -37,4 +37,4 @@ function createContext<ContextValueType extends object | null>(
return [Provider, useContext] as const;
}
export {createContext};
export { createContext };

View File

@ -11,16 +11,16 @@ import {
Field,
VisuallyHidden,
} from '@strapi/design-system';
import {Cross} from '@strapi/icons';
import {Formik, Form} from 'formik';
import {useIntl} from 'react-intl';
import {styled} from 'styled-components';
import { Cross } from '@strapi/icons';
import { Formik, Form } from 'formik';
import { useIntl } from 'react-intl';
import { styled } from 'styled-components';
import * as yup from 'yup';
import {useAppInfo} from '../features/AppInfo';
import {useAuth} from '../features/Auth';
import {useNotification} from '../features/Notifications';
import {usePersistentState} from '../hooks/usePersistentState';
import { useAppInfo } from '../features/AppInfo';
import { useAuth } from '../features/Auth';
import { useNotification } from '../features/Notifications';
import { usePersistentState } from '../hooks/usePersistentState';
const FieldWrapper = styled(Field.Root)`
height: 3.2rem;
@ -39,21 +39,21 @@ const FieldWrapper = styled(Field.Root)`
> label {
color: inherit;
cursor: pointer;
padding: ${({theme}) => theme.spaces[2]};
padding: ${({ theme }) => theme.spaces[2]};
text-align: center;
vertical-align: middle;
}
&:hover,
&:focus-within {
background-color: ${({theme}) => theme.colors.neutral0};
background-color: ${({ theme }) => theme.colors.neutral0};
}
&:active,
&.selected {
color: ${({theme}) => theme.colors.primary700};
background-color: ${({theme}) => theme.colors.neutral0};
border-color: ${({theme}) => theme.colors.primary700};
color: ${({ theme }) => theme.colors.primary700};
background-color: ${({ theme }) => theme.colors.neutral0};
border-color: ${({ theme }) => theme.colors.primary700};
}
`;
@ -67,7 +67,7 @@ const delays = {
const ratingArray = [...Array(11).keys()];
const checkIfShouldShowSurvey = (settings: NpsSurveySettings) => {
const {enabled, lastResponseDate, firstDismissalDate, lastDismissalDate} = settings;
const { enabled, lastResponseDate, firstDismissalDate, lastDismissalDate } = settings;
// This function goes through all the cases where we'd want to not show the survey:
// 1. If the survey is disabled by strapi, abort mission, don't bother checking the other settings.
@ -130,10 +130,10 @@ const checkIfShouldShowSurvey = (settings: NpsSurveySettings) => {
};
const NpsSurvey = () => {
const {formatMessage} = useIntl();
const {npsSurveySettings, setNpsSurveySettings} = useNpsSurveySettings();
const { formatMessage } = useIntl();
const { npsSurveySettings, setNpsSurveySettings } = useNpsSurveySettings();
const [isFeedbackResponse, setIsFeedbackResponse] = React.useState(false);
const {toggleNotification} = useNotification();
const { toggleNotification } = useNotification();
const currentEnvironment = useAppInfo('NpsSurvey', (state) => state.currentEnvironment);
const strapiVersion = useAppInfo('NpsSurvey', (state) => state.strapiVersion);
@ -164,7 +164,7 @@ const NpsSurvey = () => {
};
}, []);
const {user} = useAuth('NpsSurvey', auth => auth);
const { user } = useAuth('NpsSurvey', (auth) => auth);
if (!displaySurvey) {
return null;
@ -175,9 +175,9 @@ const NpsSurvey = () => {
}
const handleSubmitResponse = async ({
npsSurveyRating,
npsSurveyFeedback,
}: {
npsSurveyRating,
npsSurveyFeedback,
}: {
npsSurveyRating: NpsSurveyMutationBody['rating'];
npsSurveyFeedback: NpsSurveyMutationBody['comment'];
}) => {
@ -216,7 +216,7 @@ const NpsSurvey = () => {
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage({id: 'notification.error', defaultMessage: 'An error occurred'}),
message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),
});
}
};
@ -245,14 +245,14 @@ const NpsSurvey = () => {
return (
<Portal>
<Formik
initialValues={{npsSurveyFeedback: '', npsSurveyRating: null}}
initialValues={{ npsSurveyFeedback: '', npsSurveyRating: null }}
onSubmit={handleSubmitResponse}
validationSchema={yup.object({
npsSurveyFeedback: yup.string(),
npsSurveyRating: yup.number().required(),
})}
>
{({values, handleChange, setFieldValue, isSubmitting}) => (
{({ values, handleChange, setFieldValue, isSubmitting }) => (
<Form name="npsSurveyForm">
<Flex
hasRadius
@ -295,7 +295,7 @@ const NpsSurvey = () => {
defaultMessage: 'Dismiss survey',
})}
>
<Cross/>
<Cross />
</IconButton>
</Flex>
<Flex gap={2} marginTop={2} marginBottom={2} justifyContent="center">
@ -402,7 +402,7 @@ function useNpsSurveySettings() {
/**
* TODO: should this just be an array so we can alias the `usePersistentState` hook?
*/
return {npsSurveySettings, setNpsSurveySettings};
return { npsSurveySettings, setNpsSurveySettings };
}
export {NpsSurvey, useNpsSurveySettings};
export { NpsSurvey, useNpsSurveySettings };

View File

@ -1,22 +1,22 @@
import {Navigate, useLocation, useMatch} from 'react-router-dom';
import { Navigate, useLocation, useMatch } from 'react-router-dom';
import {useAuth} from '../../features/Auth';
import {useEnterprise} from '../../hooks/useEnterprise';
import {useInitQuery} from '../../services/admin';
import { useAuth } from '../../features/Auth';
import { useEnterprise } from '../../hooks/useEnterprise';
import { useInitQuery } from '../../services/admin';
import {Login as LoginCE} from './components/Login';
import {FORMS, FormDictionary} from './constants';
import { Login as LoginCE } from './components/Login';
import { FORMS, FormDictionary } from './constants';
/* -------------------------------------------------------------------------------------------------
* AuthPage
* -----------------------------------------------------------------------------------------------*/
const AuthPage = () => {
const {search} = useLocation();
const { search } = useLocation();
const match = useMatch('/auth/:authType');
const authType = match?.params.authType;
const {data} = useInitQuery();
const {hasAdmin} = data ?? {};
const { data } = useInitQuery();
const { hasAdmin } = data ?? {};
const Login = useEnterprise(
LoginCE,
async () => (await import('../../../../ee/admin/src/pages/AuthPage/components/Login')).LoginEE
@ -35,10 +35,10 @@ const AuthPage = () => {
}
);
const {token} = useAuth('AuthPage', (auth) => auth);
const { token } = useAuth('AuthPage', (auth) => auth);
if (!authType || !forms) {
return <Navigate to="/"/>;
return <Navigate to="/" />;
}
const Component = forms[authType as keyof FormDictionary];
@ -48,7 +48,7 @@ const AuthPage = () => {
// there is already an admin user oo
// the user is already logged in
if (!Component || (hasAdmin && authType === 'register-admin') || token) {
return <Navigate to="/"/>;
return <Navigate to="/" />;
}
// Redirect the user to the register-admin if it is the first user
@ -67,13 +67,13 @@ const AuthPage = () => {
if (Login && authType === 'login') {
// Assign the component to render for the login form
return <Login/>;
return <Login />;
} else if (authType === 'login' && !Login) {
// block rendering until the Login EE component is fully loaded
return null;
}
return <Component hasAdmin={hasAdmin}/>;
return <Component hasAdmin={hasAdmin} />;
};
export {AuthPage};
export { AuthPage };

View File

@ -1,23 +1,23 @@
import * as React from 'react';
import {Box, Button, Flex, Main, Typography, Link} from '@strapi/design-system';
import { Box, Button, Flex, Main, Typography, Link } from '@strapi/design-system';
import camelCase from 'lodash/camelCase';
import {useIntl} from 'react-intl';
import {NavLink, useLocation, useNavigate} from 'react-router-dom';
import { useIntl } from 'react-intl';
import { NavLink, useLocation, useNavigate } from 'react-router-dom';
import * as yup from 'yup';
import {Form} from '../../../components/Form';
import {InputRenderer} from '../../../components/FormInputs/Renderer';
import {Logo} from '../../../components/UnauthenticatedLogo';
import {useAuth} from '../../../features/Auth';
import { Form } from '../../../components/Form';
import { InputRenderer } from '../../../components/FormInputs/Renderer';
import { Logo } from '../../../components/UnauthenticatedLogo';
import { useAuth } from '../../../features/Auth';
import {
UnauthenticatedLayout,
Column,
LayoutContent,
} from '../../../layouts/UnauthenticatedLayout';
import {translatedErrors} from '../../../utils/translatedErrors';
import { translatedErrors } from '../../../utils/translatedErrors';
import type {Login} from '../../../../../shared/contracts/authentication';
import type { Login } from '../../../../../shared/contracts/authentication';
interface LoginProps {
children?: React.ReactNode;
@ -35,14 +35,14 @@ const LOGIN_SCHEMA = yup.object().shape({
rememberMe: yup.bool().nullable(),
});
const Login = ({children}: LoginProps) => {
const Login = ({ children }: LoginProps) => {
const [apiError, setApiError] = React.useState<string>();
const {formatMessage} = useIntl();
const {search: searchString} = useLocation();
const { formatMessage } = useIntl();
const { search: searchString } = useLocation();
const query = React.useMemo(() => new URLSearchParams(searchString), [searchString]);
const navigate = useNavigate();
const {login} = useAuth('Login', (auth) => auth);
const { login } = useAuth('Login', (auth) => auth);
const handleLogin = async (body: Parameters<typeof login>[0]) => {
setApiError(undefined);
@ -71,7 +71,7 @@ const Login = ({children}: LoginProps) => {
<Main>
<LayoutContent>
<Column>
<Logo/>
<Logo />
<Box paddingTop={6} paddingBottom={1}>
<Typography variant="alpha" tag="h1">
{formatMessage({
@ -109,7 +109,7 @@ const Login = ({children}: LoginProps) => {
<Flex direction="column" alignItems="stretch" gap={6}>
{[
{
label: formatMessage({id: 'Auth.form.email.label', defaultMessage: 'Email'}),
label: formatMessage({ id: 'Auth.form.email.label', defaultMessage: 'Email' }),
name: 'email',
placeholder: formatMessage({
id: 'Auth.form.email.placeholder',
@ -139,7 +139,7 @@ const Login = ({children}: LoginProps) => {
<InputRenderer key={field.name} {...field} />
))}
<Button fullWidth type="submit">
{formatMessage({id: 'Auth.form.button.login', defaultMessage: 'Login'})}
{formatMessage({ id: 'Auth.form.button.login', defaultMessage: 'Login' })}
</Button>
</Flex>
</Form>
@ -160,5 +160,5 @@ const Login = ({children}: LoginProps) => {
);
};
export {Login};
export type {LoginProps};
export { Login };
export type { LoginProps };

View File

@ -1,34 +1,34 @@
import * as React from 'react';
import {Box, Button, Flex, Grid, GridItem, Typography, Link} from '@strapi/design-system';
import { Box, Button, Flex, Grid, GridItem, Typography, Link } from '@strapi/design-system';
import omit from 'lodash/omit';
import {useIntl} from 'react-intl';
import {NavLink, Navigate, useNavigate, useMatch, useLocation} from 'react-router-dom';
import {styled} from 'styled-components';
import { useIntl } from 'react-intl';
import { NavLink, Navigate, useNavigate, useMatch, useLocation } from 'react-router-dom';
import { styled } from 'styled-components';
import * as yup from 'yup';
import {ValidationError} from 'yup';
import { ValidationError } from 'yup';
import {
Register as RegisterUser,
RegisterAdmin,
} from '../../../../../shared/contracts/authentication';
import {Form, FormHelpers} from '../../../components/Form';
import {InputRenderer} from '../../../components/FormInputs/Renderer';
import {useGuidedTour} from '../../../components/GuidedTour/Provider';
import {useNpsSurveySettings} from '../../../components/NpsSurvey';
import {Logo} from '../../../components/UnauthenticatedLogo';
import {useAuth} from '../../../features/Auth';
import {useNotification} from '../../../features/Notifications';
import {useTracking} from '../../../features/Tracking';
import {useAPIErrorHandler} from '../../../hooks/useAPIErrorHandler';
import {LayoutContent, UnauthenticatedLayout} from '../../../layouts/UnauthenticatedLayout';
import { Form, FormHelpers } from '../../../components/Form';
import { InputRenderer } from '../../../components/FormInputs/Renderer';
import { useGuidedTour } from '../../../components/GuidedTour/Provider';
import { useNpsSurveySettings } from '../../../components/NpsSurvey';
import { Logo } from '../../../components/UnauthenticatedLogo';
import { useAuth } from '../../../features/Auth';
import { useNotification } from '../../../features/Notifications';
import { useTracking } from '../../../features/Tracking';
import { useAPIErrorHandler } from '../../../hooks/useAPIErrorHandler';
import { LayoutContent, UnauthenticatedLayout } from '../../../layouts/UnauthenticatedLayout';
import {
useGetRegistrationInfoQuery,
useRegisterAdminMutation,
useRegisterUserMutation,
} from '../../../services/auth';
import {isBaseQueryError} from '../../../utils/baseQuery';
import {translatedErrors} from '../../../utils/translatedErrors';
import { isBaseQueryError } from '../../../utils/baseQuery';
import { translatedErrors } from '../../../utils/translatedErrors';
const REGISTER_USER_SCHEMA = yup.object().shape({
firstname: yup.string().trim().required(translatedErrors.required),
@ -38,7 +38,7 @@ const REGISTER_USER_SCHEMA = yup.object().shape({
.min(8, {
id: translatedErrors.minLength.id,
defaultMessage: 'Password must be at least 8 characters',
values: {min: 8},
values: { min: 8 },
})
.matches(/[a-z]/, {
message: {
@ -89,7 +89,7 @@ const REGISTER_ADMIN_SCHEMA = yup.object().shape({
.min(8, {
id: translatedErrors.minLength.id,
defaultMessage: 'Password must be at least 8 characters',
values: {min: 8},
values: { min: 8 },
})
.matches(/[a-z]/, {
message: {
@ -154,26 +154,26 @@ interface RegisterFormValues {
news: boolean;
}
const Register = ({hasAdmin}: RegisterProps) => {
const {toggleNotification} = useNotification();
const Register = ({ hasAdmin }: RegisterProps) => {
const { toggleNotification } = useNotification();
const navigate = useNavigate();
const [submitCount, setSubmitCount] = React.useState(0);
const [apiError, setApiError] = React.useState<string>();
const {trackUsage} = useTracking();
const {formatMessage} = useIntl();
const { trackUsage } = useTracking();
const { formatMessage } = useIntl();
const setSkipped = useGuidedTour('Register', (state) => state.setSkipped);
const {search: searchString} = useLocation();
const { search: searchString } = useLocation();
const query = React.useMemo(() => new URLSearchParams(searchString), [searchString]);
const match = useMatch('/auth/:authType');
const {
_unstableFormatAPIError: formatAPIError,
_unstableFormatValidationErrors: formatValidationErrors,
} = useAPIErrorHandler();
const {setNpsSurveySettings} = useNpsSurveySettings();
const { setNpsSurveySettings } = useNpsSurveySettings();
const registrationToken = query.get('registrationToken');
const {data: userInfo, error} = useGetRegistrationInfoQuery(registrationToken as string, {
const { data: userInfo, error } = useGetRegistrationInfoQuery(registrationToken as string, {
skip: !registrationToken,
});
@ -192,10 +192,10 @@ const Register = ({hasAdmin}: RegisterProps) => {
const [registerAdmin] = useRegisterAdminMutation();
const [registerUser] = useRegisterUserMutation();
const {setToken} = useAuth('Register', auth => auth);
const { setToken } = useAuth('Register', (auth) => auth);
const handleRegisterAdmin = async (
{news, ...body}: RegisterAdmin.Request['body'] & { news: boolean },
{ news, ...body }: RegisterAdmin.Request['body'] & { news: boolean },
setFormErrors: FormHelpers<RegisterFormValues>['setErrors']
) => {
const res = await registerAdmin(body);
@ -203,10 +203,10 @@ const Register = ({hasAdmin}: RegisterProps) => {
if ('data' in res) {
setToken(res.data.token);
const {roles} = res.data.user;
const { roles } = res.data.user;
if (roles) {
const isUserSuperAdmin = roles.find(({code}) => code === 'strapi-super-admin');
const isUserSuperAdmin = roles.find(({ code }) => code === 'strapi-super-admin');
if (isUserSuperAdmin) {
localStorage.setItem('GUIDED_TOUR_SKIPPED', JSON.stringify(false));
@ -217,7 +217,7 @@ const Register = ({hasAdmin}: RegisterProps) => {
if (news) {
// Only enable EE survey if user accepted the newsletter
setNpsSurveySettings((s) => ({...s, enabled: true}));
setNpsSurveySettings((s) => ({ ...s, enabled: true }));
navigate({
pathname: '/usecase',
@ -241,7 +241,7 @@ const Register = ({hasAdmin}: RegisterProps) => {
};
const handleRegisterUser = async (
{news, ...body}: RegisterUser.Request['body'] & { news: boolean },
{ news, ...body }: RegisterUser.Request['body'] & { news: boolean },
setFormErrors: FormHelpers<RegisterFormValues>['setErrors']
) => {
const res = await registerUser(body);
@ -251,7 +251,7 @@ const Register = ({hasAdmin}: RegisterProps) => {
if (news) {
// Only enable EE survey if user accepted the newsletter
setNpsSurveySettings((s) => ({...s, enabled: true}));
setNpsSurveySettings((s) => ({ ...s, enabled: true }));
navigate({
pathname: '/usecase',
@ -278,7 +278,7 @@ const Register = ({hasAdmin}: RegisterProps) => {
!match ||
(match.params.authType !== 'register' && match.params.authType !== 'register-admin')
) {
return <Navigate to="/"/>;
return <Navigate to="/" />;
}
const isAdminRegistration = match.params.authType === 'register-admin';
@ -289,7 +289,7 @@ const Register = ({hasAdmin}: RegisterProps) => {
<UnauthenticatedLayout>
<LayoutContent>
<Flex direction="column" alignItems="center" gap={3}>
<Logo/>
<Logo />
<Typography tag="h1" variant="alpha" textAlign="center">
{formatMessage({
@ -327,10 +327,10 @@ const Register = ({hasAdmin}: RegisterProps) => {
const normalizedData = normalizeData(data);
try {
await schema.validate(normalizedData, {abortEarly: false});
await schema.validate(normalizedData, { abortEarly: false });
if (submitCount > 0 && isAdminRegistration) {
trackUsage('didSubmitWithErrorsFirstAdmin', {count: submitCount.toString()});
trackUsage('didSubmitWithErrorsFirstAdmin', { count: submitCount.toString() });
}
if (normalizedData.registrationToken) {
@ -356,7 +356,7 @@ const Register = ({hasAdmin}: RegisterProps) => {
} catch (err) {
if (err instanceof ValidationError) {
helpers.setErrors(
err.inner.reduce<Record<string, string>>((acc, {message, path}) => {
err.inner.reduce<Record<string, string>>((acc, { message, path }) => {
if (path && typeof message === 'object') {
acc[path] = formatMessage(message);
}
@ -456,7 +456,7 @@ const Register = ({hasAdmin}: RegisterProps) => {
size: 12,
type: 'checkbox' as const,
},
].map(({size, ...field}) => (
].map(({ size, ...field }) => (
<GridItem key={field.name} col={size}>
<InputRenderer {...field} />
</GridItem>
@ -538,8 +538,8 @@ function normalizeData(data: RegisterFormValues) {
}
const A = styled.a`
color: ${({theme}) => theme.colors.primary600};
color: ${({ theme }) => theme.colors.primary600};
`;
export {Register};
export type {RegisterProps};
export { Register };
export type { RegisterProps };

View File

@ -1,24 +1,24 @@
import * as React from 'react';
import {Box, Button, Flex, Main, Typography, Link} from '@strapi/design-system';
import {useIntl} from 'react-intl';
import {NavLink, useNavigate, Navigate, useLocation} from 'react-router-dom';
import { Box, Button, Flex, Main, Typography, Link } from '@strapi/design-system';
import { useIntl } from 'react-intl';
import { NavLink, useNavigate, Navigate, useLocation } from 'react-router-dom';
import * as yup from 'yup';
import {ResetPassword} from '../../../../../shared/contracts/authentication';
import {Form} from '../../../components/Form';
import {InputRenderer} from '../../../components/FormInputs/Renderer';
import {Logo} from '../../../components/UnauthenticatedLogo';
import {useAuth} from '../../../features/Auth';
import {useAPIErrorHandler} from '../../../hooks/useAPIErrorHandler';
import { ResetPassword } from '../../../../../shared/contracts/authentication';
import { Form } from '../../../components/Form';
import { InputRenderer } from '../../../components/FormInputs/Renderer';
import { Logo } from '../../../components/UnauthenticatedLogo';
import { useAuth } from '../../../features/Auth';
import { useAPIErrorHandler } from '../../../hooks/useAPIErrorHandler';
import {
Column,
LayoutContent,
UnauthenticatedLayout,
} from '../../../layouts/UnauthenticatedLayout';
import {useResetPasswordMutation} from '../../../services/auth';
import {isBaseQueryError} from '../../../utils/baseQuery';
import {translatedErrors} from '../../../utils/translatedErrors';
import { useResetPasswordMutation } from '../../../services/auth';
import { isBaseQueryError } from '../../../utils/baseQuery';
import { translatedErrors } from '../../../utils/translatedErrors';
const RESET_PASSWORD_SCHEMA = yup.object().shape({
password: yup
@ -26,7 +26,7 @@ const RESET_PASSWORD_SCHEMA = yup.object().shape({
.min(8, {
id: translatedErrors.minLength.id,
defaultMessage: 'Password must be at least 8 characters',
values: {min: 8},
values: { min: 8 },
})
.matches(/[a-z]/, {
message: {
@ -63,15 +63,15 @@ const RESET_PASSWORD_SCHEMA = yup.object().shape({
});
const ResetPassword = () => {
const {formatMessage} = useIntl();
const { formatMessage } = useIntl();
const navigate = useNavigate();
const {search: searchString} = useLocation();
const { search: searchString } = useLocation();
const query = React.useMemo(() => new URLSearchParams(searchString), [searchString]);
const {_unstableFormatAPIError: formatAPIError} = useAPIErrorHandler();
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
const {setToken} = useAuth('ResetPassword', auth => auth);
const { setToken } = useAuth('ResetPassword', (auth) => auth);
const [resetPassword, {error}] = useResetPasswordMutation();
const [resetPassword, { error }] = useResetPasswordMutation();
const handleSubmit = async (body: ResetPassword.Request['body']) => {
const res = await resetPassword(body);
@ -86,7 +86,7 @@ const ResetPassword = () => {
* then they should just be redirected back to the login page.
*/
if (!query.get('code')) {
return <Navigate to="/auth/login"/>;
return <Navigate to="/auth/login" />;
}
return (
@ -94,7 +94,7 @@ const ResetPassword = () => {
<Main>
<LayoutContent>
<Column>
<Logo/>
<Logo />
<Box paddingTop={6} paddingBottom={7}>
<Typography tag="h1" variant="alpha">
{formatMessage({
@ -108,9 +108,9 @@ const ResetPassword = () => {
{isBaseQueryError(error)
? formatAPIError(error)
: formatMessage({
id: 'notification.error',
defaultMessage: 'An error occurred',
})}
id: 'notification.error',
defaultMessage: 'An error occurred',
})}
</Typography>
) : null}
</Column>
@ -122,7 +122,7 @@ const ResetPassword = () => {
}}
onSubmit={(values) => {
// We know query.code is defined because we check for it above.
handleSubmit({password: values.password, resetPasswordToken: query.get('code')!});
handleSubmit({ password: values.password, resetPasswordToken: query.get('code')! });
}}
validationSchema={RESET_PASSWORD_SCHEMA}
>
@ -166,7 +166,7 @@ const ResetPassword = () => {
<Flex justifyContent="center">
<Box paddingTop={4}>
<Link tag={NavLink} to="/auth/login">
{formatMessage({id: 'Auth.link.ready', defaultMessage: 'Ready to sign in?'})}
{formatMessage({ id: 'Auth.link.ready', defaultMessage: 'Ready to sign in?' })}
</Link>
</Box>
</Flex>
@ -175,4 +175,4 @@ const ResetPassword = () => {
);
};
export {ResetPassword};
export { ResetPassword };

View File

@ -71,7 +71,10 @@ export interface CMAdminConfiguration
}
export type NonRelationLayout = Layouts['edit'][number][number] & {
fieldSchema: Pick<Exclude<Schema.Attribute.AnyAttribute, { type: 'relation' }>, 'pluginOptions' | 'type'>;
fieldSchema: Pick<
Exclude<Schema.Attribute.AnyAttribute, { type: 'relation' }>,
'pluginOptions' | 'type'
>;
/**
* why is this trying to beplural? You don't pluralize metadata.
*

View File

@ -60,7 +60,7 @@ import { getTimezoneOffset } from '../utils/time';
import { getBadgeProps } from './ReleasesPage';
import type { Struct, Internal } from '@strapi/types'
import type { Struct, Internal } from '@strapi/types';
import type {
ReleaseAction,

View File

@ -1,6 +1,6 @@
import {omit, has, toNumber, isNil} from 'lodash/fp';
import { omit, has, toNumber, isNil } from 'lodash/fp';
import {errors, pagination} from '@strapi/utils';
import { errors, pagination } from '@strapi/utils';
interface BasePaginationParams {
withCount?: boolean | 't' | '1' | 'true' | 'f' | '0' | 'false' | 0 | 1;
@ -20,13 +20,13 @@ export type PaginationParams = PagedPagination | OffsetPagination;
type PaginationInfo =
| {
page: number;
pageSize: number;
}
page: number;
pageSize: number;
}
| {
start: number;
limit: number;
};
start: number;
limit: number;
};
/**
* Default limit values from config
@ -71,14 +71,14 @@ const shouldCount = (params: { pagination?: PaginationParams }) => {
};
const getPaginationInfo = (params: { pagination?: PaginationParams }): PaginationInfo => {
const {defaultLimit, maxLimit} = getLimitConfigDefaults();
const { defaultLimit, maxLimit } = getLimitConfigDefaults();
const {start, limit} = pagination.withDefaultPagination(params.pagination || {}, {
defaults: {offset: {limit: defaultLimit}, page: {pageSize: defaultLimit}},
const { start, limit } = pagination.withDefaultPagination(params.pagination || {}, {
defaults: { offset: { limit: defaultLimit }, page: { pageSize: defaultLimit } },
maxLimit: maxLimit || -1,
});
return {start, limit};
return { start, limit };
};
const transformPaginationResponse = (
@ -100,4 +100,4 @@ const transformPaginationResponse = (
return paginationResponse;
};
export {isPagedPagination, shouldCount, getPaginationInfo, transformPaginationResponse};
export { isPagedPagination, shouldCount, getPaginationInfo, transformPaginationResponse };

View File

@ -1,18 +1,18 @@
import fs from 'fs';
import {join} from 'path';
import { join } from 'path';
import sharp from 'sharp';
import {file as fileUtils} from '@strapi/utils';
import { file as fileUtils } from '@strapi/utils';
import {getService} from '../utils';
import { getService } from '../utils';
import type {UploadableFile} from '../types';
import type { UploadableFile } from '../types';
type Dimensions = {
width: number | null;
height: number | null;
};
const {bytesToKbytes} = fileUtils;
const { bytesToKbytes } = fileUtils;
const FORMATS_TO_RESIZE = ['jpeg', 'png', 'webp', 'tiff', 'gif'];
const FORMATS_TO_PROCESS = ['jpeg', 'png', 'webp', 'tiff', 'svg', 'gif', 'avif'];
@ -46,9 +46,9 @@ const getMetadata = (file: UploadableFile): Promise<sharp.Metadata> => {
};
const getDimensions = async (file: UploadableFile): Promise<Dimensions> => {
const {width = null, height = null} = await getMetadata(file);
const { width = null, height = null } = await getMetadata(file);
return {width, height};
return { width, height };
};
const THUMBNAIL_RESIZE_OPTIONS = {
@ -83,7 +83,7 @@ const resizeFileTo = async (
newInfo = await sharp(file.filepath).resize(options).toFile(filePath);
}
const {width, height, size} = newInfo ?? {};
const { width, height, size } = newInfo ?? {};
const newFile: UploadableFile = {
name,
@ -126,10 +126,10 @@ const generateThumbnail = async (file: UploadableFile) => {
*
*/
const optimize = async (file: UploadableFile) => {
const {sizeOptimization = false, autoOrientation = false} =
(await getService('upload').getSettings()) ?? {};
const { sizeOptimization = false, autoOrientation = false } =
(await getService('upload').getSettings()) ?? {};
const {format, size} = await getMetadata(file);
const { format, size } = await getMetadata(file);
if ((sizeOptimization || autoOrientation) && isOptimizableFormat(format)) {
let transformer;
@ -139,7 +139,7 @@ const optimize = async (file: UploadableFile) => {
transformer = sharp(file.filepath);
}
// reduce image quality
transformer[format]({quality: sizeOptimization ? 80 : 100});
transformer[format]({ quality: sizeOptimization ? 80 : 100 });
// rotate image based on EXIF data
if (autoOrientation) {
transformer.rotate();
@ -159,9 +159,9 @@ const optimize = async (file: UploadableFile) => {
newInfo = await transformer.toFile(filePath);
}
const {width: newWidth, height: newHeight, size: newSize} = newInfo ?? {};
const { width: newWidth, height: newHeight, size: newSize } = newInfo ?? {};
const newFile = {...file};
const newFile = { ...file };
newFile.getStream = () => fs.createReadStream(filePath);
newFile.filepath = filePath;
@ -192,7 +192,7 @@ const getBreakpoints = () =>
strapi.config.get<Record<string, number>>('plugin::upload.breakpoints', DEFAULT_BREAKPOINTS);
const generateResponsiveFormats = async (file: UploadableFile) => {
const {responsiveDimensions = false} = (await getService('upload').getSettings()) ?? {};
const { responsiveDimensions = false } = (await getService('upload').getSettings()) ?? {};
if (!responsiveDimensions) return [];
@ -204,7 +204,7 @@ const generateResponsiveFormats = async (file: UploadableFile) => {
const breakpoint = breakpoints[key];
if (breakpointSmallerThan(breakpoint, originalDimensions)) {
return generateBreakpoint(key, {file, breakpoint});
return generateBreakpoint(key, { file, breakpoint });
}
return undefined;
@ -214,7 +214,7 @@ const generateResponsiveFormats = async (file: UploadableFile) => {
const generateBreakpoint = async (
key: string,
{file, breakpoint}: { file: UploadableFile; breakpoint: number }
{ file, breakpoint }: { file: UploadableFile; breakpoint: number }
) => {
const newFile = await resizeFileTo(
file,
@ -234,7 +234,7 @@ const generateBreakpoint = async (
};
};
const breakpointSmallerThan = (breakpoint: number, {width, height}: Dimensions) => {
const breakpointSmallerThan = (breakpoint: number, { width, height }: Dimensions) => {
return breakpoint < (width ?? 0) || breakpoint < (height ?? 0);
};

View File

@ -4,7 +4,7 @@ import crypto from 'crypto';
import fs from 'fs';
import fse from 'fs-extra';
import _ from 'lodash';
import {extension} from 'mime-types';
import { extension } from 'mime-types';
import {
sanitize,
strings,
@ -13,14 +13,14 @@ import {
file as fileUtils,
} from '@strapi/utils';
import type {Core, UID} from '@strapi/types';
import type { Core, UID } from '@strapi/types';
import {FILE_MODEL_UID, ALLOWED_WEBHOOK_EVENTS} from '../constants';
import {getService} from '../utils';
import { FILE_MODEL_UID, ALLOWED_WEBHOOK_EVENTS } from '../constants';
import { getService } from '../utils';
import type {Config, File, InputFile, UploadableFile, FileInfo} from '../types';
import type {ViewConfiguration} from '../controllers/validation/admin/configureView';
import type {Settings} from '../controllers/validation/admin/settings';
import type { Config, File, InputFile, UploadableFile, FileInfo } from '../types';
import type { ViewConfiguration } from '../controllers/validation/admin/configureView';
import type { Settings } from '../controllers/validation/admin/settings';
type User = {
id: string | number;
@ -40,17 +40,17 @@ type Metas = {
tmpWorkingDirectory?: string;
};
const {UPDATED_BY_ATTRIBUTE, CREATED_BY_ATTRIBUTE} = contentTypesUtils.constants;
const {MEDIA_CREATE, MEDIA_UPDATE, MEDIA_DELETE} = ALLOWED_WEBHOOK_EVENTS;
const { UPDATED_BY_ATTRIBUTE, CREATED_BY_ATTRIBUTE } = contentTypesUtils.constants;
const { MEDIA_CREATE, MEDIA_UPDATE, MEDIA_DELETE } = ALLOWED_WEBHOOK_EVENTS;
const {ApplicationError, NotFoundError} = errors;
const {bytesToKbytes} = fileUtils;
const { ApplicationError, NotFoundError } = errors;
const { bytesToKbytes } = fileUtils;
export default ({strapi}: { strapi: Core.Strapi }) => {
export default ({ strapi }: { strapi: Core.Strapi }) => {
const randomSuffix = () => crypto.randomBytes(5).toString('hex');
const generateFileName = (name: string) => {
const baseName = strings.nameToSlug(name, {separator: '_', lowercase: false});
const baseName = strings.nameToSlug(name, { separator: '_', lowercase: false });
return `${baseName}_${randomSuffix()}`;
};
@ -118,11 +118,11 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
data
);
strapi.eventHub.emit(event, {media: sanitizedData});
strapi.eventHub.emit(event, { media: sanitizedData });
}
async function formatFileInfo(
{filename, type, size}: { filename: string; type: string; size: number },
{ filename, type, size }: { filename: string; type: string; size: number },
fileInfo: Partial<FileInfo> = {},
metas: {
refId?: ID;
@ -163,14 +163,14 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
sizeInBytes: size,
};
const {refId, ref, field} = metas;
const { refId, ref, field } = metas;
if (refId && ref && field) {
entity.related = [
{
id: refId,
__type: ref,
__pivot: {field},
__pivot: { field },
},
];
}
@ -207,7 +207,7 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
currentFile.filepath = file.filepath;
currentFile.getStream = () => fs.createReadStream(file.filepath);
const {optimize, isImage, isFaultyImage, isOptimizableImage} = strapi
const { optimize, isImage, isFaultyImage, isOptimizableImage } = strapi
.plugin('upload')
.service('image-manipulation');
@ -233,21 +233,21 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
},
opts?: CommonOptions
) {
const {user} = opts ?? {};
const { user } = opts ?? {};
// create temporary folder to store files for stream manipulation
const tmpWorkingDirectory = await createAndAssignTmpWorkingDirectoryToFiles(files);
let uploadedFiles: any[] = [];
try {
const {fileInfo, ...metas} = data;
const { fileInfo, ...metas } = data;
const fileArray = Array.isArray(files) ? files : [files];
const fileInfoArray = Array.isArray(fileInfo) ? fileInfo : [fileInfo];
const doUpload = async (file: InputFile, fileInfo: FileInfo) => {
const fileData = await enhanceAndValidateFile(file, fileInfo, metas);
return uploadFileAndPersist(fileData, {user});
return uploadFileAndPersist(fileData, { user });
};
uploadedFiles = await Promise.all(
@ -268,11 +268,11 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
* @param {*} fileData
*/
async function uploadImage(fileData: UploadableFile) {
const {getDimensions, generateThumbnail, generateResponsiveFormats, isResizableImage} =
const { getDimensions, generateThumbnail, generateResponsiveFormats, isResizableImage } =
getService('image-manipulation');
// Store width and height of the original image
const {width, height} = await getDimensions(fileData);
const { width, height } = await getDimensions(fileData);
// Make sure this is assigned before calling any upload
// That way it can mutate the width and height
@ -289,7 +289,7 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
// Generate thumbnail and responsive formats
const uploadResponsiveFormat = async (format: { key: string; file: UploadableFile }) => {
const {key, file} = format;
const { key, file } = format;
await getService('provider').upload(file);
_.set(fileData, ['formats', key], file);
};
@ -324,10 +324,10 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
* and responsive formats (if enabled).
*/
async function uploadFileAndPersist(fileData: UploadableFile, opts?: CommonOptions) {
const {user} = opts ?? {};
const { user } = opts ?? {};
const config = strapi.config.get<Config>('plugin::upload');
const {isImage} = getService('image-manipulation');
const { isImage } = getService('image-manipulation');
await getService('provider').checkFileSize(fileData);
@ -340,15 +340,15 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
_.set(fileData, 'provider', config.provider);
// Persist file(s)
return add(fileData, {user});
return add(fileData, { user });
}
async function updateFileInfo(
id: ID,
{name, alternativeText, caption, folder}: FileInfo,
{ name, alternativeText, caption, folder }: FileInfo,
opts?: CommonOptions
) {
const {user} = opts ?? {};
const { user } = opts ?? {};
const dbFile = await findOne(id);
@ -367,19 +367,19 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
folderPath: _.isUndefined(folder) ? dbFile.path : await fileService.getFolderPath(folder),
};
return update(id, newInfos, {user});
return update(id, newInfos, { user });
}
async function replace(
id: ID,
{data, file}: { data: { fileInfo: FileInfo }; file: InputFile },
{ data, file }: { data: { fileInfo: FileInfo }; file: InputFile },
opts?: CommonOptions
) {
const {user} = opts ?? {};
const { user } = opts ?? {};
const config = strapi.config.get<Config>('plugin::upload');
const {isImage} = getService('image-manipulation');
const { isImage } = getService('image-manipulation');
const dbFile = await findOne(id);
if (!dbFile) {
@ -392,7 +392,7 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
let fileData: UploadableFile;
try {
const {fileInfo} = data;
const { fileInfo } = data;
fileData = await enhanceAndValidateFile(file, fileInfo);
// keep a constant hash and extension so the file url doesn't change when the file is replaced
@ -429,13 +429,13 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
await fse.remove(tmpWorkingDirectory);
}
return update(id, fileData, {user});
return update(id, fileData, { user });
}
async function update(id: ID, values: Partial<File>, opts?: CommonOptions) {
const {user} = opts ?? {};
const { user } = opts ?? {};
const fileValues = {...values};
const fileValues = { ...values };
if (user) {
Object.assign(fileValues, {
[UPDATED_BY_ATTRIBUTE]: user.id,
@ -444,7 +444,7 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
sendMediaMetrics(fileValues);
const res = await strapi.db.query(FILE_MODEL_UID).update({where: {id}, data: fileValues});
const res = await strapi.db.query(FILE_MODEL_UID).update({ where: { id }, data: fileValues });
await emitEvent(MEDIA_UPDATE, res);
@ -452,9 +452,9 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
}
async function add(values: any, opts?: CommonOptions) {
const {user} = opts ?? {};
const { user } = opts ?? {};
const fileValues = {...values};
const fileValues = { ...values };
if (user) {
Object.assign(fileValues, {
[UPDATED_BY_ATTRIBUTE]: user.id,
@ -464,7 +464,7 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
sendMediaMetrics(fileValues);
const res = await strapi.db.query(FILE_MODEL_UID).create({data: fileValues});
const res = await strapi.db.query(FILE_MODEL_UID).create({ data: fileValues });
await emitEvent(MEDIA_CREATE, res);
@ -477,7 +477,7 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
});
return strapi.db.query(FILE_MODEL_UID).findOne({
where: {id},
where: { id },
...query,
});
}
@ -513,16 +513,16 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
}
const media = await strapi.db.query(FILE_MODEL_UID).findOne({
where: {id: file.id},
where: { id: file.id },
});
await emitEvent(MEDIA_DELETE, media);
return strapi.db.query(FILE_MODEL_UID).delete({where: {id: file.id}});
return strapi.db.query(FILE_MODEL_UID).delete({ where: { id: file.id } });
}
async function getSettings() {
const res = await strapi.store!({type: 'plugin', name: 'upload', key: 'settings'}).get({});
const res = await strapi.store!({ type: 'plugin', name: 'upload', key: 'settings' }).get({});
return res as Settings | null;
}
@ -534,7 +534,7 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
strapi.telemetry.send('didDisableResponsiveDimensions');
}
return strapi.store!({type: 'plugin', name: 'upload', key: 'settings'}).set({value});
return strapi.store!({ type: 'plugin', name: 'upload', key: 'settings' }).set({ value });
}
async function getConfiguration() {
@ -548,7 +548,7 @@ export default ({strapi}: { strapi: Core.Strapi }) => {
}
function setConfiguration(value: ViewConfiguration) {
return strapi.store!({type: 'plugin', name: 'upload', key: 'view_configuration'}).set({
return strapi.store!({ type: 'plugin', name: 'upload', key: 'view_configuration' }).set({
value,
});
}

View File

@ -1,4 +1,4 @@
import type {File as FormidableFile} from 'formidable';
import type { File as FormidableFile } from 'formidable';
export type InputFile = FormidableFile & {
path?: string;

View File

@ -15,11 +15,11 @@ import {
} from 'lodash/fp';
import traverseFactory from './factory';
import {Attribute} from '../types';
import {isMorphToRelationalAttribute} from '../content-types';
import { Attribute } from '../types';
import { isMorphToRelationalAttribute } from '../content-types';
const isKeyword = (keyword: string) => {
return ({key, attribute}: { key: string; attribute: Attribute }) => {
return ({ key, attribute }: { key: string; attribute: Attribute }) => {
return !attribute && keyword === key;
};
};
@ -31,7 +31,7 @@ const isObj = (value: unknown): value is Record<string, unknown> => isObject(val
const populate = traverseFactory()
// Array of strings ['foo', 'foo.bar'] => map(recurse), then filter out empty items
.intercept(isStringArray, async (visitor, options, populate, {recurse}) => {
.intercept(isStringArray, async (visitor, options, populate, { recurse }) => {
const visitedPopulate = await Promise.all(
populate.map((nestedPopulate) => recurse(visitor, options, nestedPopulate))
);
@ -114,13 +114,13 @@ const populate = traverseFactory()
remove(key, data) {
// eslint-disable-next-line no-unused-vars
const {[key]: ignored, ...rest} = data;
const { [key]: ignored, ...rest } = data;
return rest;
},
set(key, value, data) {
return {...data, [key]: value};
return { ...data, [key]: value };
},
keys(data) {
@ -131,19 +131,19 @@ const populate = traverseFactory()
return data[key];
},
}))
.ignore(({key, attribute}) => {
.ignore(({ key, attribute }) => {
return ['sort', 'filters', 'fields'].includes(key) && !attribute;
})
.on(
// Handle recursion on populate."populate"
isKeyword('populate'),
async ({key, visitor, path, value, schema, getModel}, {set, recurse}) => {
const newValue = await recurse(visitor, {schema, path, getModel}, value);
async ({ key, visitor, path, value, schema, getModel }, { set, recurse }) => {
const newValue = await recurse(visitor, { schema, path, getModel }, value);
set(key, newValue);
}
)
.on(isKeyword('on'), async ({key, visitor, path, value, getModel}, {set, recurse}) => {
.on(isKeyword('on'), async ({ key, visitor, path, value, getModel }, { set, recurse }) => {
const newOn: Record<string, unknown> = {};
if (!isObj(value)) {
@ -152,16 +152,16 @@ const populate = traverseFactory()
for (const [uid, subPopulate] of Object.entries(value)) {
const model = getModel(uid);
const newPath = {...path, raw: `${path.raw}[${uid}]`};
const newPath = { ...path, raw: `${path.raw}[${uid}]` };
newOn[uid] = await recurse(visitor, {schema: model, path: newPath, getModel}, subPopulate);
newOn[uid] = await recurse(visitor, { schema: model, path: newPath, getModel }, subPopulate);
}
set(key, newOn);
})
// Handle populate on relation
.onRelation(
async ({key, value, attribute, visitor, path, schema, getModel}, {set, recurse}) => {
async ({ key, value, attribute, visitor, path, schema, getModel }, { set, recurse }) => {
if (isNil(value)) {
return;
}
@ -173,7 +173,7 @@ const populate = traverseFactory()
}
// If there is a populate fragment defined, traverse it
const newValue = await recurse(visitor, {schema, path, getModel}, {on: value?.on});
const newValue = await recurse(visitor, { schema, path, getModel }, { on: value?.on });
set(key, newValue);
@ -183,13 +183,13 @@ const populate = traverseFactory()
const targetSchemaUID = attribute.target;
const targetSchema = getModel(targetSchemaUID!);
const newValue = await recurse(visitor, {schema: targetSchema, path, getModel}, value);
const newValue = await recurse(visitor, { schema: targetSchema, path, getModel }, value);
set(key, newValue);
}
)
// Handle populate on media
.onMedia(async ({key, path, visitor, value, getModel}, {recurse, set}) => {
.onMedia(async ({ key, path, visitor, value, getModel }, { recurse, set }) => {
if (isNil(value)) {
return;
}
@ -197,31 +197,31 @@ const populate = traverseFactory()
const targetSchemaUID = 'plugin::upload.file';
const targetSchema = getModel(targetSchemaUID);
const newValue = await recurse(visitor, {schema: targetSchema, path, getModel}, value);
const newValue = await recurse(visitor, { schema: targetSchema, path, getModel }, value);
set(key, newValue);
})
// Handle populate on components
.onComponent(async ({key, value, visitor, path, attribute, getModel}, {recurse, set}) => {
.onComponent(async ({ key, value, visitor, path, attribute, getModel }, { recurse, set }) => {
if (isNil(value)) {
return;
}
const targetSchema = getModel(attribute.component);
const newValue = await recurse(visitor, {schema: targetSchema, path, getModel}, value);
const newValue = await recurse(visitor, { schema: targetSchema, path, getModel }, value);
set(key, newValue);
})
// Handle populate on dynamic zones
.onDynamicZone(async ({key, value, schema, visitor, path, getModel}, {set, recurse}) => {
.onDynamicZone(async ({ key, value, schema, visitor, path, getModel }, { set, recurse }) => {
if (isNil(value) || !isObject(value)) {
return;
}
// Handle fragment syntax
if ('on' in value && value.on) {
const newOn = await recurse(visitor, {schema, path, getModel}, {on: value.on});
const newOn = await recurse(visitor, { schema, path, getModel }, { on: value.on });
set(key, newOn);
}

View File

@ -1,8 +1,8 @@
'use strict';
const {createTestBuilder} = require('api-tests/builder');
const {createStrapiInstance} = require('api-tests/strapi');
const {createContentAPIRequest} = require('api-tests/request');
const { createTestBuilder } = require('api-tests/builder');
const { createStrapiInstance } = require('api-tests/strapi');
const { createContentAPIRequest } = require('api-tests/request');
const builder = createTestBuilder();
@ -89,14 +89,14 @@ const fixtures = {
shirtId: 'B',
variantOf: shirtA.id,
similar: [shirtA.id],
morph_many: [{__type: 'api::shirt.shirt', id: shirtA.id}],
morph_many: [{ __type: 'api::shirt.shirt', id: shirtA.id }],
},
{
name: 'Shirt C',
shirtId: 'C',
variantOf: shirtA.id,
similar: [shirtA.id],
morph_one: [{__type: 'api::shirt.shirt', id: shirtA.id}],
morph_one: [{ __type: 'api::shirt.shirt', id: shirtA.id }],
},
];
},
@ -111,7 +111,7 @@ describe('Populate', () => {
.build();
strapi = await createStrapiInstance();
rq = createContentAPIRequest({strapi});
rq = createContentAPIRequest({ strapi });
data = await builder.sanitizedFixtures(strapi);
});
@ -128,7 +128,7 @@ describe('Populate', () => {
variantOf: true,
},
};
const {status, body} = await rq.get(`/${schemas.contentTypes.shirt.pluralName}`, {qs});
const { status, body } = await rq.get(`/${schemas.contentTypes.shirt.pluralName}`, { qs });
expect(status).toBe(200);
expect(body.data).toHaveLength(3);
@ -146,14 +146,14 @@ describe('Populate', () => {
// Check that shirtA contains shirtB and shirtC as variants
expect(shirtA.variants).toStrictEqual(
expect.arrayContaining([
expect.objectContaining({shirtId: 'B', name: 'Shirt B'}),
expect.objectContaining({shirtId: 'C', name: 'Shirt C'}),
expect.objectContaining({ shirtId: 'B', name: 'Shirt B' }),
expect.objectContaining({ shirtId: 'C', name: 'Shirt C' }),
])
);
// Check that shirtB contains shirtA as variantOf
expect(shirtB.variantOf).toStrictEqual(
expect.objectContaining({shirtId: 'A', name: 'Shirt A'}),
expect.objectContaining({ shirtId: 'A', name: 'Shirt A' })
);
});
@ -164,7 +164,7 @@ describe('Populate', () => {
similarMap: true,
},
};
const {status, body} = await rq.get(`/${schemas.contentTypes.shirt.pluralName}`, {qs});
const { status, body } = await rq.get(`/${schemas.contentTypes.shirt.pluralName}`, { qs });
expect(status).toBe(200);
expect(body.data).toHaveLength(3);
@ -182,22 +182,20 @@ describe('Populate', () => {
// Check that shirtA contains shirtB and shirtC as variants
expect(shirtA.similarMap).toStrictEqual(
expect.arrayContaining([
expect.objectContaining({shirtId: 'B', name: 'Shirt B'}),
expect.objectContaining({shirtId: 'C', name: 'Shirt C'}),
expect.objectContaining({ shirtId: 'B', name: 'Shirt B' }),
expect.objectContaining({ shirtId: 'C', name: 'Shirt C' }),
])
);
// Check that shirtB contains shirtA shirtId
expect(shirtB.similar).toStrictEqual(
expect.arrayContaining([
expect.objectContaining({shirtId: 'A', name: 'Shirt A'}),
])
expect.arrayContaining([expect.objectContaining({ shirtId: 'A', name: 'Shirt A' })])
);
});
test('Populate with attribute named {content_type}_id in parent with morphOne relation', async () => {
const qs = {populate: {morph_one: true}};
const {status, body} = await rq.get(`/${schemas.contentTypes.shirt.pluralName}`, {qs});
const qs = { populate: { morph_one: true } };
const { status, body } = await rq.get(`/${schemas.contentTypes.shirt.pluralName}`, { qs });
expect(status).toBe(200);
expect(body.data).toHaveLength(3);
@ -215,7 +213,7 @@ describe('Populate', () => {
// Check that shirtC contains shirtA as shirtId
expect(shirtC.morph_one).toStrictEqual(
expect.objectContaining({shirtId: 'A', name: 'Shirt A'})
expect.objectContaining({ shirtId: 'A', name: 'Shirt A' })
);
});
@ -223,10 +221,10 @@ describe('Populate', () => {
const qs = {
populate: {
morph_many: true,
morph_to_many: {on: {'api::shirt.shirt': true}},
morph_to_many: { on: { 'api::shirt.shirt': true } },
},
};
const {status, body} = await rq.get(`/${schemas.contentTypes.shirt.pluralName}`, {qs});
const { status, body } = await rq.get(`/${schemas.contentTypes.shirt.pluralName}`, { qs });
expect(status).toBe(200);
expect(body.data).toHaveLength(3);
@ -244,14 +242,12 @@ describe('Populate', () => {
// Check that shirtA contains shirtB with shirtId
// TODO v6: standardize the returned data from morph relationships. morph_to_many returns `[{ ...attributes }]` instead of `data: [{ attributes }]`
expect(shirtA.morph_to_many).toStrictEqual(
expect.arrayContaining([expect.objectContaining({shirtId: 'B', name: 'Shirt B'})])
expect.arrayContaining([expect.objectContaining({ shirtId: 'B', name: 'Shirt B' })])
);
// Check that shirtB contains shirtA with shirtId
expect(shirtB.morph_many).toStrictEqual(
expect.arrayContaining([
expect.objectContaining({shirtId: 'A', name: 'Shirt A'}),
])
expect.arrayContaining([expect.objectContaining({ shirtId: 'A', name: 'Shirt A' })])
);
});
});

View File

@ -2,9 +2,9 @@
// Test an API with all the possible filed types and simple filterings (no deep filtering, no relations)
const _ = require('lodash');
const {createStrapiInstance} = require('api-tests/strapi');
const {createTestBuilder} = require('api-tests/builder');
const {createContentAPIRequest, transformToRESTResource} = require('api-tests/request');
const { createStrapiInstance } = require('api-tests/strapi');
const { createTestBuilder } = require('api-tests/builder');
const { createContentAPIRequest, transformToRESTResource } = require('api-tests/request');
const builder = createTestBuilder();
const data = {
@ -52,8 +52,8 @@ const collector = {
};
const fixtures = {
card: [{name: 'Hugo LLORIS'}, {name: 'Samuel UMTITI'}, {name: 'Lucas HERNANDEZ'}],
collector: ({card}) => [
card: [{ name: 'Hugo LLORIS' }, { name: 'Samuel UMTITI' }, { name: 'Lucas HERNANDEZ' }],
collector: ({ card }) => [
{
name: 'Bernard',
age: 25,
@ -89,7 +89,7 @@ describe('Deep Filtering API', () => {
.build();
strapi = await createStrapiInstance();
rq = await createContentAPIRequest({strapi});
rq = await createContentAPIRequest({ strapi });
Object.assign(
data,
@ -111,7 +111,7 @@ describe('Deep Filtering API', () => {
method: 'GET',
url: '/collectors',
qs: {
filters: {cards: {name: data.card[0].name}},
filters: { cards: { name: data.card[0].name } },
},
});
expect(Array.isArray(res.body.data)).toBe(true);
@ -129,7 +129,7 @@ describe('Deep Filtering API', () => {
method: 'GET',
url: '/collectors',
qs: {
filters: {cards: {name: data.card[1].name}},
filters: { cards: { name: data.card[1].name } },
},
});
@ -277,7 +277,7 @@ describe('Deep Filtering API', () => {
expect(res.body.meta.pagination).toMatchObject({
...pagination,
pageCount: 0,
total: 0
total: 0,
});
expect(Array.isArray(res.body.data)).toBe(true);
expect(res.body.data.length).toBe(0);
@ -290,7 +290,7 @@ describe('Deep Filtering API', () => {
method: 'GET',
url: '/collectors',
qs: {
filters: {collector_friends: {name: data.collector[0].name}},
filters: { collector_friends: { name: data.collector[0].name } },
},
});
expect(res.body.meta.pagination).toMatchObject({

View File

@ -4,12 +4,12 @@ const fs = require('fs');
const path = require('path');
// Helpers.
const {createTestBuilder} = require('api-tests/builder');
const {createStrapiInstance} = require('api-tests/strapi');
const {createContentAPIRequest} = require('api-tests/request');
const { createTestBuilder } = require('api-tests/builder');
const { createStrapiInstance } = require('api-tests/strapi');
const { createContentAPIRequest } = require('api-tests/request');
const builder = createTestBuilder();
const data = {dogs: []};
const data = { dogs: [] };
let strapi;
let rq;
@ -65,7 +65,7 @@ describe('Upload plugin', () => {
.addContentType(todoListModel)
.build();
strapi = await createStrapiInstance();
rq = createContentAPIRequest({strapi});
rq = createContentAPIRequest({ strapi });
});
afterAll(async () => {
@ -103,7 +103,7 @@ describe('Upload plugin', () => {
});
test('Rejects when no files are provided', async () => {
const res = await rq({method: 'POST', url: '/upload', formData: {}});
const res = await rq({ method: 'POST', url: '/upload', formData: {} });
expect(res.statusCode).toBe(400);
});
@ -152,7 +152,7 @@ describe('Upload plugin', () => {
describe('Read', () => {
test('Get files', async () => {
const getRes = await rq({method: 'GET', url: '/upload/files'});
const getRes = await rq({ method: 'GET', url: '/upload/files' });
expect(getRes.statusCode).toBe(200);
expect(getRes.body).toEqual(
@ -196,10 +196,10 @@ describe('Upload plugin', () => {
})
);
await strapi.db.query('api::dog.dog').delete({where: {id: dogEntity.id}});
await strapi.db.query('api::dog.dog').delete({ where: { id: dogEntity.id } });
await strapi.db
.query('plugin::upload.file')
.delete({where: {id: dogEntity.profilePicture.id}});
.delete({ where: { id: dogEntity.profilePicture.id } });
});
});
@ -259,7 +259,7 @@ describe('Upload plugin', () => {
url: '/dogs',
qs: {
filters: {
profilePicture: {$notNull: true},
profilePicture: { $notNull: true },
},
},
});
@ -271,7 +271,7 @@ describe('Upload plugin', () => {
url: '/dogs',
qs: {
filters: {
profilePicture: {$notNull: false},
profilePicture: { $notNull: false },
},
},
});
@ -287,7 +287,7 @@ describe('Upload plugin', () => {
url: '/dogs',
qs: {
filters: {
profilePicture: {$null: true},
profilePicture: { $null: true },
},
},
});
@ -299,7 +299,7 @@ describe('Upload plugin', () => {
url: '/dogs',
qs: {
filters: {
profilePicture: {$null: false},
profilePicture: { $null: false },
},
},
});
@ -343,7 +343,7 @@ describe('Upload plugin', () => {
url: '/dogs',
qs: {
filters: {
profilePicture: {ext: '.jpg'},
profilePicture: { ext: '.jpg' },
},
},
});
@ -355,7 +355,7 @@ describe('Upload plugin', () => {
url: '/dogs',
qs: {
filters: {
profilePicture: {ext: '.pdf'},
profilePicture: { ext: '.pdf' },
},
},
});

View File

@ -1,10 +1,10 @@
'use strict';
const {omit} = require('lodash/fp');
const { omit } = require('lodash/fp');
const {createTestBuilder} = require('api-tests/builder');
const {createStrapiInstance} = require('api-tests/strapi');
const {createAuthRequest} = require('api-tests/request');
const { createTestBuilder } = require('api-tests/builder');
const { createStrapiInstance } = require('api-tests/strapi');
const { createAuthRequest } = require('api-tests/request');
const data = {
locales: [],
@ -42,16 +42,16 @@ describe('CRUD locales', () => {
await builder.addContentType(productModel).build();
strapi = await createStrapiInstance();
rq = await createAuthRequest({strapi});
rq = await createAuthRequest({ strapi });
localeService = strapi.plugin('i18n').service('locales');
});
afterAll(async () => {
await localeService.setDefaultLocale({code: 'en'});
await localeService.setDefaultLocale({ code: 'en' });
// Delete all locales that have been created
await strapi.db.query('plugin::i18n.locale').deleteMany({code: {$ne: 'en'}});
await strapi.db.query('plugin::i18n.locale').deleteMany({ code: { $ne: 'en' } });
await strapi.destroy();
await builder.cleanup();
@ -179,7 +179,7 @@ describe('CRUD locales', () => {
let res = await rq({
url: '/i18n/locales',
method: 'POST',
body: {code: 'bas', name: 'random', isDefault: true},
body: { code: 'bas', name: 'random', isDefault: true },
});
expect(res.statusCode).toBe(200);
@ -189,7 +189,7 @@ describe('CRUD locales', () => {
res = await rq({
url: '/i18n/locales',
method: 'POST',
body: {code: 'en-US', name: 'random', isDefault: true},
body: { code: 'en-US', name: 'random', isDefault: true },
});
expect(res.statusCode).toBe(200);
expect(res.body.isDefault).toBe(true);
@ -313,7 +313,7 @@ describe('CRUD locales', () => {
let res = await rq({
url: `/i18n/locales/${data.locales[0].id}`,
method: 'PUT',
body: {isDefault: true},
body: { isDefault: true },
});
expect(res.statusCode).toBe(200);
@ -322,7 +322,7 @@ describe('CRUD locales', () => {
res = await rq({
url: `/i18n/locales/${data.locales[1].id}`,
method: 'PUT',
body: {isDefault: true},
body: { isDefault: true },
});
expect(res.statusCode).toBe(200);
expect(res.body.isDefault).toBe(true);
@ -341,7 +341,7 @@ describe('CRUD locales', () => {
let res = await rq({
url: `/i18n/locales/${data.locales[0].id}`,
method: 'PUT',
body: {isDefault: true},
body: { isDefault: true },
});
expect(res.statusCode).toBe(200);
@ -350,7 +350,7 @@ describe('CRUD locales', () => {
res = await rq({
url: `/i18n/locales/${data.locales[0].id}`,
method: 'PUT',
body: {isDefault: false},
body: { isDefault: false },
});
expect(res.statusCode).toBe(200);
expect(res.body.isDefault).toBe(true);
@ -362,7 +362,7 @@ describe('CRUD locales', () => {
let res = await rq({
url: `/i18n/locales/${data.locales[0].id}`,
method: 'PUT',
body: {isDefault: true},
body: { isDefault: true },
});
expect(res.statusCode).toBe(200);
@ -399,29 +399,29 @@ describe('CRUD locales', () => {
test('Delete a locale and entities in this locale', async () => {
const {
body: {data: frenchProduct},
body: { data: frenchProduct },
} = await rq({
url: '/content-manager/collection-types/api::product.product',
method: 'POST',
qs: {locale: 'fr-FR'},
body: {name: 'product name'},
qs: { locale: 'fr-FR' },
body: { name: 'product name' },
});
await rq({
url: `/content-manager/collection-types/api::product.product/${frenchProduct.documentId}`,
method: 'PUT',
body: {name: 'product name'},
body: { name: 'product name' },
qs: {
locale: 'en',
},
});
const {
body: {results: createdProducts},
body: { results: createdProducts },
} = await rq({
url: '/content-manager/collection-types/api::product.product',
method: 'GET',
qs: {locale: 'fr-FR'},
qs: { locale: 'fr-FR' },
});
expect(createdProducts).toHaveLength(1);
@ -433,20 +433,20 @@ describe('CRUD locales', () => {
});
const {
body: {results: frenchProducts},
body: { results: frenchProducts },
} = await rq({
url: '/content-manager/collection-types/api::product.product',
method: 'GET',
qs: {locale: 'fr-FR'},
qs: { locale: 'fr-FR' },
});
expect(frenchProducts).toHaveLength(0);
const {
body: {results: englishProducts},
body: { results: englishProducts },
} = await rq({
url: '/content-manager/collection-types/api::product.product',
method: 'GET',
qs: {locale: 'en'},
qs: { locale: 'en' },
});
expect(englishProducts).toHaveLength(1);