-
+
{title}
-
+
{actions && (
{actions}
@@ -30,6 +32,7 @@ const Card: React.FC
= (props) => {
)}
{onClick && (
@@ -58,6 +59,7 @@ const SortColumn: React.FC = (props) => {
buttonStyle="none"
className={descClasses.join(' ')}
onClick={() => setSort(desc)}
+ aria-label={t('sortByLabelDirection', { label: getTranslation(label, i18n), direction: t('descending') })}
>
diff --git a/src/admin/components/elements/ViewDescription/index.tsx b/src/admin/components/elements/ViewDescription/index.tsx
index a253f184268..52f79128522 100644
--- a/src/admin/components/elements/ViewDescription/index.tsx
+++ b/src/admin/components/elements/ViewDescription/index.tsx
@@ -2,6 +2,7 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { Props, isComponent } from './types';
import { getTranslation } from '../../../../utilities/getTranslation';
+
import './index.scss';
const ViewDescription: React.FC = (props) => {
diff --git a/src/admin/components/elements/WhereBuilder/index.tsx b/src/admin/components/elements/WhereBuilder/index.tsx
index d215c42b77b..3bf71a4918d 100644
--- a/src/admin/components/elements/WhereBuilder/index.tsx
+++ b/src/admin/components/elements/WhereBuilder/index.tsx
@@ -13,6 +13,7 @@ import { useSearchParams } from '../../utilities/SearchParams';
import validateWhereQuery from './validateWhereQuery';
import { Where } from '../../../../types';
import { getTranslation } from '../../../../utilities/getTranslation';
+import { transformWhereQuery } from './transformWhereQuery';
import './index.scss';
@@ -43,6 +44,10 @@ const reduceFields = (fields, i18n) => flattenTopLevelFields(fields).reduce((red
return reduced;
}, []);
+/**
+ * The WhereBuilder component is used to render the filter controls for a collection's list view.
+ * It is part of the {@link ListControls} component which is used to render the controls (search, filter, where).
+ */
const WhereBuilder: React.FC = (props) => {
const {
collection,
@@ -59,16 +64,30 @@ const WhereBuilder: React.FC = (props) => {
const params = useSearchParams();
const { t, i18n } = useTranslation('general');
+ // This handles initializing the where conditions from the search query (URL). That way, if you pass in
+ // query params to the URL, the where conditions will be initialized from those and displayed in the UI.
+ // Example: /admin/collections/posts?where[or][0][and][0][text][equals]=example%20post
const [conditions, dispatchConditions] = useReducer(reducer, params.where, (whereFromSearch) => {
- if (modifySearchQuery && validateWhereQuery(whereFromSearch)) {
- return whereFromSearch.or;
- }
+ if (modifySearchQuery && whereFromSearch) {
+ if (validateWhereQuery(whereFromSearch)) {
+ return whereFromSearch.or;
+ }
+
+ // Transform the where query to be in the right format. This will transform something simple like [text][equals]=example%20post to the right format
+ const transformedWhere = transformWhereQuery(whereFromSearch);
+
+ if (validateWhereQuery(transformedWhere)) {
+ return transformedWhere.or;
+ }
+ console.warn('Invalid where query in URL. Ignoring.');
+ }
return [];
});
const [reducedFields] = useState(() => reduceFields(collection.fields, i18n));
+ // This handles updating the search query (URL) when the where conditions change
useThrottledEffect(() => {
const currentParams = queryString.parse(history.location.search, { ignoreQueryPrefix: true, depth: 10 }) as { where: Where };
@@ -83,8 +102,11 @@ const WhereBuilder: React.FC = (props) => {
];
}, []) : [];
+ const hasNewWhereConditions = conditions.length > 0;
+
+
const newWhereQuery = {
- ...typeof currentParams?.where === 'object' ? currentParams.where : {},
+ ...typeof currentParams?.where === 'object' && (validateWhereQuery(currentParams?.where) || !hasNewWhereConditions) ? currentParams.where : {},
or: [
...conditions,
...paramsToKeep,
@@ -94,7 +116,6 @@ const WhereBuilder: React.FC = (props) => {
if (handleChange) handleChange(newWhereQuery as Where);
const hasExistingConditions = typeof currentParams?.where === 'object' && 'or' in currentParams.where;
- const hasNewWhereConditions = conditions.length > 0;
if (modifySearchQuery && ((hasExistingConditions && !hasNewWhereConditions) || hasNewWhereConditions)) {
history.replace({
diff --git a/src/admin/components/elements/WhereBuilder/transformWhereQuery.ts b/src/admin/components/elements/WhereBuilder/transformWhereQuery.ts
new file mode 100644
index 00000000000..1edb9a8bcf4
--- /dev/null
+++ b/src/admin/components/elements/WhereBuilder/transformWhereQuery.ts
@@ -0,0 +1,51 @@
+import type { Where } from '../../../../types';
+
+/**
+ * Something like [or][0][and][0][text][equals]=example%20post will work and pass through the validateWhereQuery check.
+ * However, something like [text][equals]=example%20post will not work and will fail the validateWhereQuery check,
+ * even though it is a valid Where query. This needs to be transformed here.
+ */
+export const transformWhereQuery = (whereQuery): Where => {
+ if (!whereQuery) {
+ return {};
+ }
+ // Check if 'whereQuery' has 'or' field but no 'and'. This is the case for "correct" queries
+ if (whereQuery.or && !whereQuery.and) {
+ return {
+ or: whereQuery.or.map((query) => {
+ // ...but if the or query does not have an and, we need to add it
+ if(!query.and) {
+ return {
+ and: [query]
+ }
+ }
+ return query;
+ }),
+ };
+ }
+
+ // Check if 'whereQuery' has 'and' field but no 'or'.
+ if (whereQuery.and && !whereQuery.or) {
+ return {
+ or: [
+ {
+ and: whereQuery.and,
+ },
+ ],
+ };
+ }
+
+ // Check if 'whereQuery' has neither 'or' nor 'and'.
+ if (!whereQuery.or && !whereQuery.and) {
+ return {
+ or: [
+ {
+ and: [whereQuery], // top-level siblings are considered 'and'
+ },
+ ],
+ };
+ }
+
+ // If 'whereQuery' has 'or' and 'and', just return it as it is.
+ return whereQuery;
+};
diff --git a/src/admin/components/elements/WhereBuilder/validateWhereQuery.ts b/src/admin/components/elements/WhereBuilder/validateWhereQuery.ts
index f0f62656fce..f1789e73dcb 100644
--- a/src/admin/components/elements/WhereBuilder/validateWhereQuery.ts
+++ b/src/admin/components/elements/WhereBuilder/validateWhereQuery.ts
@@ -1,8 +1,37 @@
-import { Where } from '../../../../types';
+import type { Operator, Where } from '../../../../types';
+import { validOperators } from '../../../../types/constants';
const validateWhereQuery = (whereQuery): whereQuery is Where => {
if (whereQuery?.or?.length > 0 && whereQuery?.or?.[0]?.and && whereQuery?.or?.[0]?.and?.length > 0) {
- return true;
+ // At this point we know that the whereQuery has 'or' and 'and' fields,
+ // now let's check the structure and content of these fields.
+
+ const isValid = whereQuery.or.every((orQuery) => {
+ if (orQuery.and && Array.isArray(orQuery.and)) {
+ return orQuery.and.every((andQuery) => {
+ if (typeof andQuery !== 'object') {
+ return false;
+ }
+ const andKeys = Object.keys(andQuery);
+ // If there are no keys, it's not a valid WhereField.
+ if (andKeys.length === 0) {
+ return false;
+ }
+ // eslint-disable-next-line no-restricted-syntax
+ for (const key of andKeys) {
+ const operator = Object.keys(andQuery[key])[0];
+ // Check if the key is a valid Operator.
+ if (!operator || !validOperators.includes(operator as Operator)) {
+ return false;
+ }
+ }
+ return true;
+ });
+ }
+ return false;
+ });
+
+ return isValid;
}
return false;
diff --git a/src/admin/components/forms/field-types/Checkbox/Input.tsx b/src/admin/components/forms/field-types/Checkbox/Input.tsx
index 8532a8c6098..f7f18528364 100644
--- a/src/admin/components/forms/field-types/Checkbox/Input.tsx
+++ b/src/admin/components/forms/field-types/Checkbox/Input.tsx
@@ -1,62 +1,74 @@
import React from 'react';
import Check from '../../../icons/Check';
import Label from '../../Label';
+import Line from '../../../icons/Line';
import './index.scss';
const baseClass = 'custom-checkbox';
type CheckboxInputProps = {
- onToggle: React.MouseEventHandler
+ onToggle: React.FormEventHandler
inputRef?: React.MutableRefObject
readOnly?: boolean
checked?: boolean
+ partialChecked?: boolean
name?: string
id?: string
label?: string
+ 'aria-label'?: string
required?: boolean
}
+
export const CheckboxInput: React.FC = (props) => {
const {
onToggle,
checked,
+ partialChecked,
inputRef,
name,
id,
label,
+ 'aria-label': ariaLabel,
readOnly,
required,
} = props;
return (
-
-
-
-
+ )}
+
);
};
diff --git a/src/admin/components/forms/field-types/Checkbox/index.scss b/src/admin/components/forms/field-types/Checkbox/index.scss
index aabd160a24f..3ec3719c8ba 100644
--- a/src/admin/components/forms/field-types/Checkbox/index.scss
+++ b/src/admin/components/forms/field-types/Checkbox/index.scss
@@ -4,10 +4,6 @@
position: relative;
margin-bottom: $baseline;
- input[type=checkbox] {
- display: none;
- }
-
.tooltip:not([aria-hidden="true"]) {
right: auto;
position: relative;
@@ -22,74 +18,69 @@
.custom-checkbox {
+ display: inline-flex;
+
label {
padding-bottom: 0;
+ padding-left: base(.5);
}
+
+ &:hover {
+ cursor: pointer;
- input {
- // hidden HTML checkbox
- position: absolute;
- top: 0;
- left: 0;
- opacity: 0;
+ svg {
+ opacity: 0.2;
+ }
}
&__input {
- // visible checkbox
@include formInput;
+ display: flex;
padding: 0;
line-height: 0;
position: relative;
width: $baseline;
height: $baseline;
- margin-right: base(.5);
- svg {
+ & input[type="checkbox"] {
+ width: 100%;
+ height: 100%;
+ padding: 0;
+ margin: 0;
opacity: 0;
+ border-radius: 0;
+ z-index: 1;
+ cursor: pointer;
}
- }
- &--read-only {
- .custom-checkbox__input {
- background-color: var(--theme-elevation-100);
- }
-
- label {
- color: var(--theme-elevation-400);
+ &:focus-within {
+ box-shadow: 0 0 3px 3px var(--theme-success-400);
}
}
- button {
- @extend %btn-reset;
- display: flex;
- align-items: center;
- cursor: pointer;
-
- &:focus,
- &:active {
- outline: none;
- }
+ &__icon {
+ position: absolute;
- &:focus {
- .custom-checkbox__input {
- box-shadow: 0 0 3px 3px var(--theme-success-400);
- }
+ svg {
+ opacity: 0;
}
+ }
- &:hover {
+ &--checked {
+ .custom-checkbox__icon {
svg {
- opacity: .2;
+ opacity: 1;
}
}
}
- &--checked {
- button {
- .custom-checkbox__input {
- svg {
- opacity: 1;
- }
- }
+ &--read-only {
+ .custom-checkbox__input {
+ background-color: var(--theme-elevation-100);
+ }
+
+ label {
+ color: var(--theme-elevation-400);
}
}
}
diff --git a/src/admin/components/forms/field-types/Number/index.tsx b/src/admin/components/forms/field-types/Number/index.tsx
index 27837a11689..0c62af22111 100644
--- a/src/admin/components/forms/field-types/Number/index.tsx
+++ b/src/admin/components/forms/field-types/Number/index.tsx
@@ -10,9 +10,9 @@ import { Props } from './types';
import { getTranslation } from '../../../../../utilities/getTranslation';
import { Option } from '../../../elements/ReactSelect/types';
import ReactSelect from '../../../elements/ReactSelect';
+import { isNumber } from '../../../../../utilities/isNumber';
import './index.scss';
-import { isNumber } from '../../../../../utilities/isNumber';
const NumberField: React.FC
= (props) => {
const {
@@ -145,7 +145,7 @@ const NumberField: React.FC = (props) => {
isClearable
filterOption={(option, rawInput) => {
// eslint-disable-next-line no-restricted-globals
- return isNumber(rawInput)
+ return isNumber(rawInput);
}}
numberOnly
/>
diff --git a/src/admin/components/forms/field-types/Relationship/select-components/MultiValueLabel/index.tsx b/src/admin/components/forms/field-types/Relationship/select-components/MultiValueLabel/index.tsx
index 5aadcd34fcb..9b7fb300b0c 100644
--- a/src/admin/components/forms/field-types/Relationship/select-components/MultiValueLabel/index.tsx
+++ b/src/admin/components/forms/field-types/Relationship/select-components/MultiValueLabel/index.tsx
@@ -6,6 +6,7 @@ import Tooltip from '../../../../../elements/Tooltip';
import Edit from '../../../../../icons/Edit';
import { useAuth } from '../../../../../utilities/Auth';
import { Option } from '../../types';
+
import './index.scss';
const baseClass = 'relationship--multi-value-label';
diff --git a/src/admin/components/forms/field-types/RichText/elements/link/LinkDrawer/index.tsx b/src/admin/components/forms/field-types/RichText/elements/link/LinkDrawer/index.tsx
index 6a6195c0999..b3c03f97129 100644
--- a/src/admin/components/forms/field-types/RichText/elements/link/LinkDrawer/index.tsx
+++ b/src/admin/components/forms/field-types/RichText/elements/link/LinkDrawer/index.tsx
@@ -6,11 +6,11 @@ import FormSubmit from '../../../../../Submit';
import { Props } from './types';
import fieldTypes from '../../../..';
import RenderFields from '../../../../../RenderFields';
-
-import './index.scss';
import useHotkey from '../../../../../../../hooks/useHotkey';
import { useEditDepth } from '../../../../../../utilities/EditDepth';
+import './index.scss';
+
const baseClass = 'rich-text-link-edit-modal';
export const LinkDrawer: React.FC = ({
diff --git a/src/admin/components/views/Account/Default.tsx b/src/admin/components/views/Account/Default.tsx
index 1ea8c0df673..662da8a3ac7 100644
--- a/src/admin/components/views/Account/Default.tsx
+++ b/src/admin/components/views/Account/Default.tsx
@@ -130,9 +130,11 @@ const DefaultAccount: React.FC = (props) => {
{t('general:payloadSettings')}
(language.value === i18n.language))}
options={languageOptions}
onChange={({ value }) => (i18n.changeLanguage(value))}
diff --git a/src/admin/components/views/Dashboard/Default.tsx b/src/admin/components/views/Dashboard/Default.tsx
index 056d6389201..b4b3836c97a 100644
--- a/src/admin/components/views/Dashboard/Default.tsx
+++ b/src/admin/components/views/Dashboard/Default.tsx
@@ -24,7 +24,7 @@ const Dashboard: React.FC = (props) => {
} = props;
const { push } = useHistory();
- const { i18n } = useTranslation('general');
+ const { t, i18n } = useTranslation('general');
const {
routes: {
@@ -77,12 +77,14 @@ const Dashboard: React.FC = (props) => {
{entities.map(({ entity, type }, entityIndex) => {
let title: string;
+ let buttonAriaLabel: string;
let createHREF: string;
let onClick: () => void;
let hasCreatePermission: boolean;
if (type === EntityType.collection) {
title = getTranslation(entity.labels.plural, i18n);
+ buttonAriaLabel = t('showAllLabel', { label: title });
onClick = () => push({ pathname: `${admin}/collections/${entity.slug}` });
createHREF = `${admin}/collections/${entity.slug}/create`;
hasCreatePermission = permissions?.collections?.[entity.slug]?.create?.permission;
@@ -90,6 +92,7 @@ const Dashboard: React.FC = (props) => {
if (type === EntityType.global) {
title = getTranslation(entity.label, i18n);
+ buttonAriaLabel = t('editLabel', { label: getTranslation(entity.label, i18n) });
onClick = () => push({ pathname: `${admin}/globals/${entity.slug}` });
}
@@ -97,8 +100,10 @@ const Dashboard: React.FC = (props) => {
-
= (props) => {
round
buttonStyle="icon-label"
iconStyle="with-border"
+ aria-label={t('createNewLabel', { label: getTranslation(entity.labels.singular, i18n) })}
/>
) : undefined}
/>
diff --git a/src/admin/components/views/ForgotPassword/index.tsx b/src/admin/components/views/ForgotPassword/index.tsx
index 83611870f04..293c115a653 100644
--- a/src/admin/components/views/ForgotPassword/index.tsx
+++ b/src/admin/components/views/ForgotPassword/index.tsx
@@ -11,7 +11,6 @@ import FormSubmit from '../../forms/Submit';
import Button from '../../elements/Button';
import Meta from '../../utilities/Meta';
-
import './index.scss';
const baseClass = 'forgot-password';
diff --git a/src/admin/components/views/ResetPassword/index.tsx b/src/admin/components/views/ResetPassword/index.tsx
index 5ea2518736b..9e5bf5ee29c 100644
--- a/src/admin/components/views/ResetPassword/index.tsx
+++ b/src/admin/components/views/ResetPassword/index.tsx
@@ -13,7 +13,6 @@ import Button from '../../elements/Button';
import Meta from '../../utilities/Meta';
import HiddenInput from '../../forms/field-types/HiddenInput';
-
import './index.scss';
const baseClass = 'reset-password';
diff --git a/src/admin/components/views/collections/List/Default.tsx b/src/admin/components/views/collections/List/Default.tsx
index c0190272b45..eb32be8448f 100644
--- a/src/admin/components/views/collections/List/Default.tsx
+++ b/src/admin/components/views/collections/List/Default.tsx
@@ -100,7 +100,10 @@ const DefaultList: React.FC = (props) => {
{getTranslation(pluralLabel, i18n)}
{hasCreatePermission && (
-
+
{t('createNew')}
)}
diff --git a/src/admin/components/views/collections/List/SelectAll/index.scss b/src/admin/components/views/collections/List/SelectAll/index.scss
deleted file mode 100644
index 573462a8882..00000000000
--- a/src/admin/components/views/collections/List/SelectAll/index.scss
+++ /dev/null
@@ -1,34 +0,0 @@
-@import '../../../../../scss/styles.scss';
-
-.select-all {
- button {
- @extend %btn-reset;
- display: flex;
- align-items: center;
- cursor: pointer;
-
- &:focus:not(:focus-visible),
- &:active {
- outline: none;
- }
-
- &:hover {
- svg {
- opacity: .2;
- }
- }
-
- &:focus-visible {
- outline-offset: var(--accessibility-outline-offset);
- }
- }
-
- &__input {
- @include formInput;
- padding: 0;
- line-height: 0;
- position: relative;
- width: $baseline;
- height: $baseline;
- }
-}
diff --git a/src/admin/components/views/collections/List/SelectAll/index.tsx b/src/admin/components/views/collections/List/SelectAll/index.tsx
index 18b0b3dcb32..bcc3e373e89 100644
--- a/src/admin/components/views/collections/List/SelectAll/index.tsx
+++ b/src/admin/components/views/collections/List/SelectAll/index.tsx
@@ -1,31 +1,22 @@
import React from 'react';
-import { SelectAllStatus, useSelection } from '../SelectionProvider';
-import Check from '../../../../icons/Check';
-import Line from '../../../../icons/Line';
+import { useTranslation } from 'react-i18next';
-import './index.scss';
+import { SelectAllStatus, useSelection } from '../SelectionProvider';
-const baseClass = 'select-all';
+import { CheckboxInput } from '../../../../forms/field-types/Checkbox/Input';
const SelectAll: React.FC = () => {
+ const { t } = useTranslation('general');
const { selectAll, toggleAll } = useSelection();
return (
-
-
-
+ toggleAll()}
+ />
);
};
diff --git a/src/admin/components/views/collections/List/SelectRow/index.tsx b/src/admin/components/views/collections/List/SelectRow/index.tsx
index acae082fe7d..f879c62bcc1 100644
--- a/src/admin/components/views/collections/List/SelectRow/index.tsx
+++ b/src/admin/components/views/collections/List/SelectRow/index.tsx
@@ -1,31 +1,17 @@
import React from 'react';
import { useSelection } from '../SelectionProvider';
-import Check from '../../../../icons/Check';
+import { CheckboxInput } from '../../../../forms/field-types/Checkbox/Input';
import './index.scss';
-const baseClass = 'select-row';
-
const SelectRow: React.FC<{ id: string | number }> = ({ id }) => {
const { selected, setSelection } = useSelection();
return (
-
-
-
+ setSelection(id)}
+ />
);
};
diff --git a/src/admin/components/views/collections/List/index.tsx b/src/admin/components/views/collections/List/index.tsx
index 6b03c653483..10f9b71c0cc 100644
--- a/src/admin/components/views/collections/List/index.tsx
+++ b/src/admin/components/views/collections/List/index.tsx
@@ -16,6 +16,12 @@ import { useSearchParams } from '../../../utilities/SearchParams';
import { TableColumnsProvider } from '../../../elements/TableColumns';
import type { Field } from '../../../../../fields/config/types';
+/**
+ * The ListView component is table which lists the collection's documents.
+ * The default list view can be found at the {@link DefaultList} component.
+ * Users can also create pass their own custom list view component instead
+ * of using the default one.
+ */
const ListView: React.FC = (props) => {
const {
collection,
diff --git a/src/auth/operations/forgotPassword.ts b/src/auth/operations/forgotPassword.ts
index 9fdf665f588..823e7b016b8 100644
--- a/src/auth/operations/forgotPassword.ts
+++ b/src/auth/operations/forgotPassword.ts
@@ -3,6 +3,7 @@ import { Document } from 'mongoose';
import { APIError } from '../../errors';
import { PayloadRequest } from '../../express/types';
import { Collection } from '../../collections/config/types';
+import { buildAfterOperation } from '../../collections/operations/utils';
export type Arguments = {
collection: Collection
@@ -128,6 +129,16 @@ async function forgotPassword(incomingArgs: Arguments): Promise {
await hook({ args, context: req.context });
}, Promise.resolve());
+ // /////////////////////////////////////
+ // afterOperation - Collection
+ // /////////////////////////////////////
+
+ token = await buildAfterOperation({
+ operation: 'forgotPassword',
+ args,
+ result: token,
+ });
+
return token;
}
diff --git a/src/auth/operations/login.ts b/src/auth/operations/login.ts
index 19b30d12830..7ab452a3514 100644
--- a/src/auth/operations/login.ts
+++ b/src/auth/operations/login.ts
@@ -10,6 +10,7 @@ import { User } from '../types';
import { Collection } from '../../collections/config/types';
import { afterRead } from '../../fields/hooks/afterRead';
import unlock from './unlock';
+import { buildAfterOperation } from '../../collections/operations/utils';
import { incrementLoginAttempts } from '../strategies/local/incrementLoginAttempts';
import { authenticateLocalStrategy } from '../strategies/local/authenticate';
import { getFieldsToSign } from './getFieldsToSign';
@@ -206,15 +207,28 @@ async function login(
}) || user;
}, Promise.resolve());
- // /////////////////////////////////////
- // Return results
- // /////////////////////////////////////
- return {
+ let result: Result & { user: GeneratedTypes['collections'][TSlug] } = {
token,
user,
exp: (jwt.decode(token) as jwt.JwtPayload).exp,
};
+
+ // /////////////////////////////////////
+ // afterOperation - Collection
+ // /////////////////////////////////////
+
+ result = await buildAfterOperation({
+ operation: 'login',
+ args,
+ result,
+ });
+
+ // /////////////////////////////////////
+ // Return results
+ // /////////////////////////////////////
+
+ return result;
}
export default login;
diff --git a/src/auth/operations/refresh.ts b/src/auth/operations/refresh.ts
index aef6896606b..6ae63854ed3 100644
--- a/src/auth/operations/refresh.ts
+++ b/src/auth/operations/refresh.ts
@@ -1,11 +1,12 @@
+import url from 'url';
import jwt from 'jsonwebtoken';
import { Response } from 'express';
-import url from 'url';
import { Collection, BeforeOperationHook } from '../../collections/config/types';
import { Forbidden } from '../../errors';
import getCookieExpiration from '../../utilities/getCookieExpiration';
import { Document } from '../../types';
import { PayloadRequest } from '../../express/types';
+import { buildAfterOperation } from '../../collections/operations/utils';
import { getFieldsToSign } from './getFieldsToSign';
export type Result = {
@@ -97,7 +98,7 @@ async function refresh(incomingArgs: Arguments): Promise {
args.res.cookie(`${config.cookiePrefix}-token`, refreshedToken, cookieOptions);
}
- let response: Result = {
+ let result: Result = {
user,
refreshedToken,
exp,
@@ -110,20 +111,31 @@ async function refresh(incomingArgs: Arguments): Promise {
await collectionConfig.hooks.afterRefresh.reduce(async (priorHook, hook) => {
await priorHook;
- response = (await hook({
+ result = (await hook({
req: args.req,
res: args.res,
exp,
token: refreshedToken,
context: args.req.context,
- })) || response;
+ })) || result;
}, Promise.resolve());
+
+ // /////////////////////////////////////
+ // afterOperation - Collection
+ // /////////////////////////////////////
+
+ result = await buildAfterOperation({
+ operation: 'refresh',
+ args,
+ result,
+ });
+
// /////////////////////////////////////
// Return results
// /////////////////////////////////////
- return response;
+ return result;
}
export default refresh;
diff --git a/src/bin/index.ts b/src/bin/index.ts
index 74ae6ae29e4..3806d7825ae 100755
--- a/src/bin/index.ts
+++ b/src/bin/index.ts
@@ -16,7 +16,7 @@ const swcOptions = {
tsx: true,
},
paths: undefined,
- baseUrl: __dirname,
+ baseUrl: path.resolve(),
},
module: {
type: 'commonjs',
diff --git a/src/collections/config/defaults.ts b/src/collections/config/defaults.ts
index fde30c9ecad..7972c72c36a 100644
--- a/src/collections/config/defaults.ts
+++ b/src/collections/config/defaults.ts
@@ -29,6 +29,7 @@ export const defaults = {
afterRead: [],
beforeDelete: [],
afterDelete: [],
+ afterOperation: [],
beforeLogin: [],
afterLogin: [],
afterLogout: [],
diff --git a/src/collections/config/schema.ts b/src/collections/config/schema.ts
index 326c4dc7d3e..aafa79c5392 100644
--- a/src/collections/config/schema.ts
+++ b/src/collections/config/schema.ts
@@ -98,6 +98,7 @@ const collectionSchema = joi.object().keys({
afterRead: joi.array().items(joi.func()),
beforeDelete: joi.array().items(joi.func()),
afterDelete: joi.array().items(joi.func()),
+ afterOperation: joi.array().items(joi.func()),
beforeLogin: joi.array().items(joi.func()),
afterLogin: joi.array().items(joi.func()),
afterLogout: joi.array().items(joi.func()),
diff --git a/src/collections/config/types.ts b/src/collections/config/types.ts
index 46f6fd459f2..043c85eb66c 100644
--- a/src/collections/config/types.ts
+++ b/src/collections/config/types.ts
@@ -12,6 +12,7 @@ import { IncomingUploadType, Upload } from '../../uploads/types';
import { IncomingCollectionVersions, SanitizedCollectionVersions } from '../../versions/types';
import { BuildQueryArgs } from '../../mongoose/buildQuery';
import { CustomPreviewButtonProps, CustomPublishButtonProps, CustomSaveButtonProps, CustomSaveDraftButtonProps } from '../../admin/components/elements/types';
+import { AfterOperationArg, AfterOperationMap } from '../operations/utils';
import type { Props as ListProps } from '../../admin/components/views/collections/List/types';
import type { Props as EditProps } from '../../admin/components/views/collections/Edit/types';
@@ -123,6 +124,13 @@ export type AfterDeleteHook = (args: {
context: RequestContext;
}) => any;
+
+export type AfterOperationHook<
+ T extends TypeWithID = any,
+> = (
+ arg: AfterOperationArg,
+ ) => Promise[keyof AfterOperationMap]>>;
+
export type AfterErrorHook = (err: Error, res: unknown, context: RequestContext) => { response: any, status: number } | void;
export type BeforeLoginHook = (args: {
@@ -314,6 +322,7 @@ export type CollectionConfig = {
afterMe?: AfterMeHook[];
afterRefresh?: AfterRefreshHook[];
afterForgotPassword?: AfterForgotPasswordHook[];
+ afterOperation?: AfterOperationHook[];
};
/**
* Custom rest api endpoints
diff --git a/src/collections/operations/create.ts b/src/collections/operations/create.ts
index 4dad449ecc2..1e29bb53920 100644
--- a/src/collections/operations/create.ts
+++ b/src/collections/operations/create.ts
@@ -22,11 +22,14 @@ import { afterRead } from '../../fields/hooks/afterRead';
import { generateFileData } from '../../uploads/generateFileData';
import { saveVersion } from '../../versions/saveVersion';
import { mapAsync } from '../../utilities/mapAsync';
+import { buildAfterOperation } from './utils';
import { registerLocalStrategy } from '../../auth/strategies/local/register';
const unlinkFile = promisify(fs.unlink);
-export type Arguments = {
+export type CreateUpdateType = { [field: string | number | symbol]: unknown }
+
+export type Arguments = {
collection: Collection
req: PayloadRequest
depth?: number
@@ -318,6 +321,16 @@ async function create(
}) || result;
}, Promise.resolve());
+ // /////////////////////////////////////
+ // afterOperation - Collection
+ // /////////////////////////////////////
+
+ result = await buildAfterOperation({
+ operation: 'create',
+ args,
+ result,
+ });
+
// Remove temp files if enabled, as express-fileupload does not do this automatically
if (config.upload?.useTempFiles && collectionConfig.upload) {
const { files } = req;
diff --git a/src/collections/operations/delete.ts b/src/collections/operations/delete.ts
index 951c4e306ba..551fbd1570a 100644
--- a/src/collections/operations/delete.ts
+++ b/src/collections/operations/delete.ts
@@ -10,6 +10,7 @@ import { Where } from '../../types';
import { afterRead } from '../../fields/hooks/afterRead';
import { deleteCollectionVersions } from '../../versions/deleteCollectionVersions';
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles';
+import { buildAfterOperation } from './utils';
export type Arguments = {
depth?: number
@@ -212,10 +213,22 @@ async function deleteOperation `collection-${collectionConfig.slug}-${id}`) } });
- return {
+ let result = {
docs: awaitedDocs.filter(Boolean),
errors,
};
+
+ // /////////////////////////////////////
+ // afterOperation - Collection
+ // /////////////////////////////////////
+
+ result = await buildAfterOperation({
+ operation: 'delete',
+ args,
+ result,
+ });
+
+ return result;
}
export default deleteOperation;
diff --git a/src/collections/operations/deleteByID.ts b/src/collections/operations/deleteByID.ts
index bc7c895c33a..55c085464d6 100644
--- a/src/collections/operations/deleteByID.ts
+++ b/src/collections/operations/deleteByID.ts
@@ -4,11 +4,12 @@ import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
import { NotFound, Forbidden } from '../../errors';
import executeAccess from '../../auth/executeAccess';
import { BeforeOperationHook, Collection } from '../config/types';
-import { Document, Where } from '../../types';
+import { Document } from '../../types';
import { hasWhereAccessResult } from '../../auth/types';
import { afterRead } from '../../fields/hooks/afterRead';
import { deleteCollectionVersions } from '../../versions/deleteCollectionVersions';
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles';
+import { buildAfterOperation } from './utils';
export type Arguments = {
depth?: number
@@ -174,6 +175,16 @@ async function deleteByID(inc
result = await hook({ req, id, doc: result, context: req.context }) || result;
}, Promise.resolve());
+ // /////////////////////////////////////
+ // afterOperation - Collection
+ // /////////////////////////////////////
+
+ result = await buildAfterOperation({
+ operation: 'deleteByID',
+ args,
+ result,
+ });
+
// /////////////////////////////////////
// 8. Return results
// /////////////////////////////////////
diff --git a/src/collections/operations/find.ts b/src/collections/operations/find.ts
index 750e45eec57..ce7f847f5d3 100644
--- a/src/collections/operations/find.ts
+++ b/src/collections/operations/find.ts
@@ -9,6 +9,7 @@ import { buildSortParam } from '../../mongoose/buildSortParam';
import { AccessResult } from '../../config/types';
import { afterRead } from '../../fields/hooks/afterRead';
import { queryDrafts } from '../../versions/drafts/queryDrafts';
+import { buildAfterOperation } from './utils';
export type Arguments = {
collection: Collection
@@ -226,6 +227,16 @@ async function find>(
})),
};
+ // /////////////////////////////////////
+ // afterOperation - Collection
+ // /////////////////////////////////////
+
+ result = await buildAfterOperation({
+ operation: 'find',
+ args,
+ result,
+ });
+
// /////////////////////////////////////
// Return results
// /////////////////////////////////////
diff --git a/src/collections/operations/findByID.ts b/src/collections/operations/findByID.ts
index e1ff5e28d32..ec71f23bed7 100644
--- a/src/collections/operations/findByID.ts
+++ b/src/collections/operations/findByID.ts
@@ -7,6 +7,7 @@ import { NotFound } from '../../errors';
import executeAccess from '../../auth/executeAccess';
import replaceWithDraftIfAvailable from '../../versions/drafts/replaceWithDraftIfAvailable';
import { afterRead } from '../../fields/hooks/afterRead';
+import { buildAfterOperation } from './utils';
export type Arguments = {
collection: Collection
@@ -173,6 +174,16 @@ async function findByID(
}) || result;
}, Promise.resolve());
+ // /////////////////////////////////////
+ // afterOperation - Collection
+ // /////////////////////////////////////
+
+ result = await buildAfterOperation({
+ operation: 'findByID',
+ args,
+ result,
+ });
+
// /////////////////////////////////////
// Return results
// /////////////////////////////////////
diff --git a/src/collections/operations/update.ts b/src/collections/operations/update.ts
index fd56f5752e1..b11d7e61607 100644
--- a/src/collections/operations/update.ts
+++ b/src/collections/operations/update.ts
@@ -18,8 +18,10 @@ import { AccessResult } from '../../config/types';
import { queryDrafts } from '../../versions/drafts/queryDrafts';
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles';
import { unlinkTempFiles } from '../../uploads/unlinkTempFiles';
+import { buildAfterOperation } from './utils';
+import { CreateUpdateType } from './create';
-export type Arguments = {
+export type Arguments = {
collection: Collection
req: PayloadRequest
where: Where
@@ -350,10 +352,22 @@ async function update(
const awaitedDocs = await Promise.all(promises);
- return {
+ let result = {
docs: awaitedDocs.filter(Boolean),
errors,
};
+
+ // /////////////////////////////////////
+ // afterOperation - Collection
+ // /////////////////////////////////////
+
+ result = await buildAfterOperation({
+ operation: 'update',
+ args,
+ result,
+ });
+
+ return result;
}
export default update;
diff --git a/src/collections/operations/updateByID.ts b/src/collections/operations/updateByID.ts
index 542e133663f..41c27956e0c 100644
--- a/src/collections/operations/updateByID.ts
+++ b/src/collections/operations/updateByID.ts
@@ -18,6 +18,7 @@ import { generateFileData } from '../../uploads/generateFileData';
import { getLatestCollectionVersion } from '../../versions/getLatestCollectionVersion';
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles';
import { unlinkTempFiles } from '../../uploads/unlinkTempFiles';
+import { buildAfterOperation } from './utils';
import { generatePasswordSaltHash } from '../../auth/strategies/local/generatePasswordSaltHash';
export type Arguments = {
@@ -340,6 +341,16 @@ async function updateByID(
}) || result;
}, Promise.resolve());
+ // /////////////////////////////////////
+ // afterOperation - Collection
+ // /////////////////////////////////////
+
+ result = await buildAfterOperation({
+ operation: 'updateByID',
+ args,
+ result,
+ });
+
await unlinkTempFiles({
req,
config,
diff --git a/src/collections/operations/utils.ts b/src/collections/operations/utils.ts
new file mode 100644
index 00000000000..d27974c77d6
--- /dev/null
+++ b/src/collections/operations/utils.ts
@@ -0,0 +1,71 @@
+import find from './find';
+import update from './update';
+import deleteOperation from './delete';
+import create from './create';
+import login from '../../auth/operations/login';
+import refresh from '../../auth/operations/refresh';
+import findByID from './findByID';
+import updateByID from './updateByID';
+import deleteByID from './deleteByID';
+import { AfterOperationHook, TypeWithID } from '../config/types';
+import forgotPassword from '../../auth/operations/forgotPassword';
+
+export type AfterOperationMap<
+ T extends TypeWithID,
+> = {
+ create: typeof create, // todo: pass correct generic
+ find: typeof find,
+ findByID: typeof findByID,
+ update: typeof update, // todo: pass correct generic
+ updateByID: typeof updateByID, // todo: pass correct generic
+ delete: typeof deleteOperation, // todo: pass correct generic
+ deleteByID: typeof deleteByID, // todo: pass correct generic
+ login: typeof login,
+ refresh: typeof refresh,
+ forgotPassword: typeof forgotPassword,
+}
+export type AfterOperationArg =
+ | { operation: 'create'; result: Awaited['create']>>, args: Parameters['create']>[0] }
+ | { operation: 'find'; result: Awaited['find']>>, args: Parameters['find']>[0] }
+ | { operation: 'findByID'; result: Awaited['findByID']>>, args: Parameters['findByID']>[0] }
+ | { operation: 'update'; result: Awaited['update']>>, args: Parameters['update']>[0] }
+ | { operation: 'updateByID'; result: Awaited['updateByID']>>, args: Parameters['updateByID']>[0] }
+ | { operation: 'delete'; result: Awaited['delete']>>, args: Parameters['delete']>[0] }
+ | { operation: 'deleteByID'; result: Awaited['deleteByID']>>, args: Parameters['deleteByID']>[0] }
+ | { operation: 'login'; result: Awaited['login']>>, args: Parameters['login']>[0] }
+ | { operation: 'refresh'; result: Awaited['refresh']>>, args: Parameters['refresh']>[0] }
+ | { operation: 'forgotPassword'; result: Awaited['forgotPassword']>>, args: Parameters['forgotPassword']>[0] };
+
+// export type AfterOperationHook = typeof buildAfterOperation;
+
+export const buildAfterOperation = async <
+ T extends TypeWithID = any,
+ O extends keyof AfterOperationMap = keyof AfterOperationMap
+>
+(
+ operationArgs: AfterOperationArg & { operation: O },
+): Promise[O]>>> => {
+ const {
+ operation,
+ args,
+ result,
+ } = operationArgs;
+
+ let newResult = result;
+
+ await args.collection.config.hooks.afterOperation.reduce(async (priorHook, hook: AfterOperationHook) => {
+ await priorHook;
+
+ const hookResult = await hook({
+ operation,
+ args,
+ result: newResult,
+ } as AfterOperationArg);
+
+ if (hookResult !== undefined) {
+ newResult = hookResult;
+ }
+ }, Promise.resolve());
+
+ return newResult;
+};
diff --git a/src/config/sanitize.ts b/src/config/sanitize.ts
index 8272e236298..4bfee793d8e 100644
--- a/src/config/sanitize.ts
+++ b/src/config/sanitize.ts
@@ -9,54 +9,53 @@ import checkDuplicateCollections from '../utilities/checkDuplicateCollections';
import { defaults } from './defaults';
import getDefaultBundler from '../bundlers/webpack/bundler';
-const sanitizeAdmin = (config: SanitizedConfig): SanitizedConfig['admin'] => {
- const adminConfig = config.admin;
+const sanitizeAdminConfig = (configToSanitize: Config): Partial => {
+ const sanitizedConfig = { ...configToSanitize };
// add default user collection if none provided
- if (!adminConfig?.user) {
- const firstCollectionWithAuth = config.collections.find(({ auth }) => Boolean(auth));
+ if (!sanitizedConfig?.admin?.user) {
+ const firstCollectionWithAuth = sanitizedConfig.collections.find(({ auth }) => Boolean(auth));
if (firstCollectionWithAuth) {
- adminConfig.user = firstCollectionWithAuth.slug;
+ sanitizedConfig.admin.user = firstCollectionWithAuth.slug;
} else {
- adminConfig.user = 'users';
- const sanitizedDefaultUser = sanitizeCollection(config, defaultUserCollection);
- config.collections.push(sanitizedDefaultUser);
+ sanitizedConfig.admin.user = defaultUserCollection.slug;
+ sanitizedConfig.collections.push(defaultUserCollection);
}
}
- if (!config.collections.find(({ slug }) => slug === adminConfig.user)) {
- throw new InvalidConfiguration(`${config.admin.user} is not a valid admin user collection`);
+ if (!sanitizedConfig.collections.find(({ slug }) => slug === sanitizedConfig.admin.user)) {
+ throw new InvalidConfiguration(`${sanitizedConfig.admin.user} is not a valid admin user collection`);
}
// add default bundler if none provided
- if (!adminConfig.bundler) {
- adminConfig.bundler = getDefaultBundler();
+ if (!sanitizedConfig.admin.bundler) {
+ sanitizedConfig.admin.bundler = getDefaultBundler();
}
- return adminConfig;
+ return sanitizedConfig as Partial;
};
-export const sanitizeConfig = (config: Config): SanitizedConfig => {
- const sanitizedConfig: Config = merge(defaults, config, {
+export const sanitizeConfig = (incomingConfig: Config): SanitizedConfig => {
+ const configWithDefaults: Config = merge(defaults, incomingConfig, {
isMergeableObject: isPlainObject,
- }) as Config;
+ });
- sanitizedConfig.admin = sanitizeAdmin(sanitizedConfig as SanitizedConfig);
+ const config: Partial = sanitizeAdminConfig(configWithDefaults);
+ config.collections = config.collections.map((collection) => sanitizeCollection(configWithDefaults, collection));
- sanitizedConfig.collections = sanitizedConfig.collections.map((collection) => sanitizeCollection(sanitizedConfig, collection));
- checkDuplicateCollections(sanitizedConfig.collections);
+ checkDuplicateCollections(config.collections);
- if (sanitizedConfig.globals.length > 0) {
- sanitizedConfig.globals = sanitizeGlobals(sanitizedConfig.collections, sanitizedConfig.globals);
+ if (config.globals.length > 0) {
+ config.globals = sanitizeGlobals(config.collections, config.globals);
}
- if (typeof sanitizedConfig.serverURL === 'undefined') {
- sanitizedConfig.serverURL = '';
+ if (typeof config.serverURL === 'undefined') {
+ config.serverURL = '';
}
- if (sanitizedConfig.serverURL !== '') {
- sanitizedConfig.csrf.push(sanitizedConfig.serverURL);
+ if (config.serverURL !== '') {
+ config.csrf.push(config.serverURL);
}
- return sanitizedConfig as SanitizedConfig;
+ return config as SanitizedConfig;
};
diff --git a/src/fields/hooks/beforeChange/promise.ts b/src/fields/hooks/beforeChange/promise.ts
index 5d7185b4f36..58fdb66731d 100644
--- a/src/fields/hooks/beforeChange/promise.ts
+++ b/src/fields/hooks/beforeChange/promise.ts
@@ -3,10 +3,8 @@ import merge from 'deepmerge';
import { Field, fieldAffectsData, TabAsField, tabHasName } from '../../config/types';
import { Operation } from '../../../types';
import { PayloadRequest, RequestContext } from '../../../express/types';
-import getValueWithDefault from '../../getDefaultValue';
import { traverseFields } from './traverseFields';
import { getExistingRowDoc } from './getExistingRowDoc';
-import { cloneDataFromOriginalDoc } from './cloneDataFromOriginalDoc';
type Args = {
data: Record
@@ -28,8 +26,6 @@ type Args = {
// This function is responsible for the following actions, in order:
// - Run condition
-// - Merge original document data into incoming data
-// - Compute default values for undefined fields
// - Execute field hooks
// - Validate data
// - Transform data for storage
@@ -59,26 +55,6 @@ export const promise = async ({
const operationLocale = req.locale || defaultLocale;
if (fieldAffectsData(field)) {
- if (typeof siblingData[field.name] === 'undefined') {
- // If no incoming data, but existing document data is found, merge it in
- if (typeof siblingDoc[field.name] !== 'undefined') {
- if (field.localized && typeof siblingDocWithLocales[field.name] === 'object' && siblingDocWithLocales[field.name] !== null) {
- siblingData[field.name] = cloneDataFromOriginalDoc(siblingDocWithLocales[field.name][req.locale]);
- } else {
- siblingData[field.name] = cloneDataFromOriginalDoc(siblingDoc[field.name]);
- }
-
- // Otherwise compute default value
- } else if (typeof field.defaultValue !== 'undefined') {
- siblingData[field.name] = await getValueWithDefault({
- value: siblingData[field.name],
- defaultValue: field.defaultValue,
- locale: req.locale,
- user: req.user,
- });
- }
- }
-
// skip validation if the field is localized and the incoming data is null
if (field.localized && operationLocale !== defaultLocale) {
if (['array', 'blocks'].includes(field.type) && siblingData[field.name] === null) {
diff --git a/src/fields/hooks/beforeValidate/promise.ts b/src/fields/hooks/beforeValidate/promise.ts
index 5d6e0aa8bdb..5f206dc3fce 100644
--- a/src/fields/hooks/beforeValidate/promise.ts
+++ b/src/fields/hooks/beforeValidate/promise.ts
@@ -1,6 +1,9 @@
/* eslint-disable no-param-reassign */
import { PayloadRequest, RequestContext } from '../../../express/types';
import { Field, fieldAffectsData, TabAsField, tabHasName, valueIsValueWithRelation } from '../../config/types';
+import getValueWithDefault from '../../getDefaultValue';
+import { cloneDataFromOriginalDoc } from '../beforeChange/cloneDataFromOriginalDoc';
+import { getExistingRowDoc } from '../beforeChange/getExistingRowDoc';
import { traverseFields } from './traverseFields';
type Args = {
@@ -20,6 +23,8 @@ type Args = {
// - Sanitize incoming data
// - Execute field hooks
// - Execute field access control
+// - Merge original document data into incoming data
+// - Compute default values for undefined fields
export const promise = async ({
data,
@@ -189,6 +194,22 @@ export const promise = async ({
delete siblingData[field.name];
}
}
+
+ if (typeof siblingData[field.name] === 'undefined') {
+ // If no incoming data, but existing document data is found, merge it in
+ if (typeof siblingDoc[field.name] !== 'undefined') {
+ siblingData[field.name] = cloneDataFromOriginalDoc(siblingDoc[field.name]);
+
+ // Otherwise compute default value
+ } else if (typeof field.defaultValue !== 'undefined') {
+ siblingData[field.name] = await getValueWithDefault({
+ value: siblingData[field.name],
+ defaultValue: field.defaultValue,
+ locale: req.locale,
+ user: req.user,
+ });
+ }
+ }
}
// Traverse subfields
@@ -231,7 +252,7 @@ export const promise = async ({
overrideAccess,
req,
siblingData: row,
- siblingDoc: siblingDoc[field.name]?.[i] || {},
+ siblingDoc: getExistingRowDoc(row, siblingDoc[field.name]),
context,
}));
});
@@ -258,7 +279,7 @@ export const promise = async ({
overrideAccess,
req,
siblingData: row,
- siblingDoc: siblingDoc[field.name]?.[i] || {},
+ siblingDoc: getExistingRowDoc(row, siblingDoc[field.name]),
context,
}));
}
@@ -291,8 +312,11 @@ export const promise = async ({
let tabSiblingData;
let tabSiblingDoc;
if (tabHasName(field)) {
- tabSiblingData = typeof siblingData[field.name] === 'object' ? siblingData[field.name] : {};
- tabSiblingDoc = typeof siblingDoc[field.name] === 'object' ? siblingDoc[field.name] : {};
+ if (typeof siblingData[field.name] !== 'object') siblingData[field.name] = {};
+ if (typeof siblingDoc[field.name] !== 'object') siblingDoc[field.name] = {};
+
+ tabSiblingData = siblingData[field.name] as Record;
+ tabSiblingDoc = siblingDoc[field.name] as Record;
} else {
tabSiblingData = siblingData;
tabSiblingDoc = siblingDoc;
diff --git a/src/translations/ar.json b/src/translations/ar.json
index 2fe61044d0e..b961b9c5f67 100644
--- a/src/translations/ar.json
+++ b/src/translations/ar.json
@@ -63,8 +63,8 @@
"deletingFile": "حدث خطأ أثناء حذف الملف.",
"deletingTitle": "حدث خطأ أثناء حذف {{title}}. يرجى التحقق من الاتصال الخاص بك والمحاولة مرة أخرى.",
"emailOrPasswordIncorrect": "البريد الإلكتروني أو كلمة المرور المقدمة غير صحيحة.",
- "followingFieldsInvalid_other": "الحقول التالية غير صالحة:",
"followingFieldsInvalid_one": "الحقل التالي غير صالح:",
+ "followingFieldsInvalid_other": "الحقول التالية غير صالحة:",
"incorrectCollection": "مجموعة غير صحيحة",
"invalidFileType": "نوع ملف غير صالح",
"invalidFileTypeValue": "نوع ملف غير صالح: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "تم الحذف بنجاح.",
"deleting": "جاري الحذف...",
"descending": "تنازلي",
+ "deselectAllRows": "إلغاء تحديد جميع الصفوف",
"duplicate": "استنساخ",
"duplicateWithoutSaving": "استنساخ بدون حفظ التغييرات",
"edit": "تعديل",
@@ -181,11 +182,11 @@
"editingLabel_many": "تعديل {{count}} {{label}}",
"editingLabel_one": "تعديل {{count}} {{label}}",
"editingLabel_other": "تعديل {{count}} {{label}}",
- "error": "خطأ",
- "errors": "أخطاء",
"email": "البريد الإلكتروني",
"emailAddress": "عنوان البريد الإلكتروني",
"enterAValue": "أدخل قيمة",
+ "error": "خطأ",
+ "errors": "أخطاء",
"fallbackToDefaultLocale": "الرجوع إلى اللغة الافتراضية",
"filter": "تصفية",
"filterWhere": "تصفية {{label}} حيث",
@@ -222,10 +223,13 @@
"saving": "جاري الحفظ...",
"searchBy": "البحث عن طريق {{label}}",
"selectAll": "تحديد كل {{count}} {{label}}",
+ "selectAllRows": "حدد جميع الصفوف",
"selectValue": "اختيار قيمة",
"selectedCount": "تم تحديد {{count}} {{label}}",
+ "showAllLabel": "عرض كل {{label}}",
"sorryNotFound": "عذرًا - لا يوجد شيء يتوافق مع طلبك.",
"sort": "ترتيب",
+ "sortByLabelDirection": "رتّب حسب {{label}} {{direction}}",
"stayOnThisPage": "البقاء على هذه الصفحة",
"submissionSuccessful": "تمت الإرسال بنجاح.",
"submit": "إرسال",
@@ -346,4 +350,4 @@
"viewingVersions": "عرض النسخ لـ {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "عرض النسخ للـ {{entityLabel}} العام"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/az.json b/src/translations/az.json
index 7ec01e7c13e..23781987969 100644
--- a/src/translations/az.json
+++ b/src/translations/az.json
@@ -65,6 +65,7 @@
"emailOrPasswordIncorrect": "Təqdim olunan e-poçt və ya şifrə yanlışdır.",
"followingFieldsInvalid_many": "Aşağıdakı sahələr yanlışdır:",
"followingFieldsInvalid_one": "Aşağıdakı sahə yanlışdır:",
+ "followingFieldsInvalid_other": "Aşağıdaki sahələr yanlışdır:",
"incorrectCollection": "Yanlış Kolleksiya",
"invalidFileType": "Yanlış fayl növü",
"invalidFileTypeValue": "Yanlış fayl növü: {{value}}",
@@ -173,6 +174,7 @@
"deletedSuccessfully": "Uğurla silindi.",
"deleting": "Silinir...",
"descending": "Azalan",
+ "deselectAllRows": "Bütün sıraları seçimi ləğv edin",
"duplicate": "Dublikat",
"duplicateWithoutSaving": "Dəyişiklikləri saxlamadan dublikatla",
"edit": "Redaktə et",
@@ -222,10 +224,13 @@
"saving": "Saxlanılır...",
"searchBy": "{{label}} ilə axtar",
"selectAll": "Bütün {{count}} {{label}} seç",
+ "selectAllRows": "Bütün sıraları seçin",
"selectValue": "Dəyər seçin",
"selectedCount": "{{count}} {{label}} seçildi",
+ "showAllLabel": "Bütün {{label}}-ı göstər",
"sorryNotFound": "Üzr istəyirik - sizin tələbinizə uyğun heç nə yoxdur.",
"sort": "Sırala",
+ "sortByLabelDirection": "{{label}} {{direction}} ilə sırala",
"stayOnThisPage": "Bu səhifədə qal",
"submissionSuccessful": "Təqdimat uğurlu oldu.",
"submit": "Təqdim et",
diff --git a/src/translations/bg.json b/src/translations/bg.json
index 3c43e3fa06c..259b7db8df5 100644
--- a/src/translations/bg.json
+++ b/src/translations/bg.json
@@ -63,8 +63,8 @@
"deletingFile": "Имаше грешка при изтриването на файла.",
"deletingTitle": "Имаше проблем при изтриването на {{title}}. Моля провери връзката си и опитай отново.",
"emailOrPasswordIncorrect": "Имейлът или паролата не са правилни.",
- "followingFieldsInvalid_other": "Следните полета са некоректни:",
"followingFieldsInvalid_one": "Следното поле е некоректно:",
+ "followingFieldsInvalid_other": "Следните полета са некоректни:",
"incorrectCollection": "Некоректно събиране",
"invalidFileType": "Невалиден тип на файл",
"invalidFileTypeValue": "Невалиден тип на файл: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Изтрито успешно.",
"deleting": "Изтриване...",
"descending": "Низходящо",
+ "deselectAllRows": "Деселектирайте всички редове",
"duplicate": "Дупликирай",
"duplicateWithoutSaving": "Дупликирай без да запазваш промените",
"edit": "Редактирай",
@@ -222,10 +223,13 @@
"saving": "Запазване...",
"searchBy": "Търси по {{label}}",
"selectAll": "Избери всички {{count}} {{label}}",
+ "selectAllRows": "Изберете всички редове",
"selectValue": "Избери стойност",
"selectedCount": "{{count}} {{label}} избрани",
+ "showAllLabel": "Покажи всички {{label}}",
"sorryNotFound": "Съжаляваме-няма нищо, което да отговаря на търсенето ти.",
"sort": "Сортирай",
+ "sortByLabelDirection": "Сортирай по {{label}} {{direction}}",
"stayOnThisPage": "Остани на тази страница",
"submissionSuccessful": "Успешно подаване.",
"submit": "Подай",
@@ -261,6 +265,7 @@
"near": "близко"
},
"upload": {
+ "dragAndDrop": "Дръпни и пусни файл",
"dragAndDropHere": "или дръпни и пусни файла тук",
"fileName": "Име на файла",
"fileSize": "Големина на файла",
@@ -269,7 +274,6 @@
"moreInfo": "Повече информация",
"selectCollectionToBrowse": "Избери колекция, която да разгледаш",
"selectFile": "Избери файл",
- "dragAndDrop": "Дръпни и пусни файл",
"sizes": "Големини",
"width": "Ширина"
},
@@ -327,8 +331,8 @@
"saveDraft": "Запази чернова",
"selectLocales": "Избери локализации за показване",
"selectVersionToCompare": "Избери версия за сравняване",
- "showingVersionsFor": "Показване на версии за:",
"showLocales": "Покажи преводи:",
+ "showingVersionsFor": "Показване на версии за:",
"status": "Статус",
"type": "Тип",
"unpublish": "Скрий",
@@ -346,4 +350,4 @@
"viewingVersions": "Гледане на версии за {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Гледане на версии за глобалния документ {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/cs.json b/src/translations/cs.json
index a301f4e77d9..a84cfb6dcba 100644
--- a/src/translations/cs.json
+++ b/src/translations/cs.json
@@ -63,8 +63,8 @@
"deletingFile": "Při mazání souboru došlo k chybě.",
"deletingTitle": "Při mazání {{title}} došlo k chybě. Zkontrolujte své připojení a zkuste to znovu.",
"emailOrPasswordIncorrect": "Zadaný email nebo heslo není správné.",
- "followingFieldsInvalid_other": "Následující pole jsou neplatná:",
"followingFieldsInvalid_one": "Následující pole je neplatné:",
+ "followingFieldsInvalid_other": "Následující pole jsou neplatná:",
"incorrectCollection": "Nesprávná kolekce",
"invalidFileType": "Neplatný typ souboru",
"invalidFileTypeValue": "Neplatný typ souboru: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Úspěšně odstraněno.",
"deleting": "Odstraňování...",
"descending": "Sestupně",
+ "deselectAllRows": "Zrušte výběr všech řádků",
"duplicate": "Duplikovat",
"duplicateWithoutSaving": "Duplikovat bez uložení změn",
"edit": "Upravit",
@@ -222,10 +223,13 @@
"saving": "Ukládání...",
"searchBy": "Vyhledat podle {{label}}",
"selectAll": "Vybrat vše {{count}} {{label}}",
+ "selectAllRows": "Vyberte všechny řádky",
"selectValue": "Vyberte hodnotu",
"selectedCount": "Vybráno {{count}} {{label}}",
+ "showAllLabel": "Zobrazit všechny {{label}}",
"sorryNotFound": "Je nám líto, ale neexistuje nic, co by odpovídalo vašemu požadavku.",
"sort": "Třídit",
+ "sortByLabelDirection": "Seřadit podle {{label}} {{direction}}",
"stayOnThisPage": "Zůstat na této stránce",
"submissionSuccessful": "Odeslání úspěšné.",
"submit": "Odeslat",
@@ -247,20 +251,21 @@
"welcome": "Vítejte"
},
"operators": {
+ "contains": "obsahuje",
"equals": "rovná se",
- "isNotEqualTo": "není rovno",
- "isIn": "je v",
- "isNotIn": "není in",
"exists": "existuje",
"isGreaterThan": "je větší než",
+ "isGreaterThanOrEqualTo": "je větší nebo rovno",
+ "isIn": "je v",
"isLessThan": "je menší než",
"isLessThanOrEqualTo": "je menší nebo rovno",
- "isGreaterThanOrEqualTo": "je větší nebo rovno",
- "near": "blízko",
"isLike": "je jako",
- "contains": "obsahuje"
+ "isNotEqualTo": "není rovno",
+ "isNotIn": "není in",
+ "near": "blízko"
},
"upload": {
+ "dragAndDrop": "Přetáhněte soubor",
"dragAndDropHere": "nebo sem přetáhněte soubor",
"fileName": "Název souboru",
"fileSize": "Velikost souboru",
@@ -269,7 +274,6 @@
"moreInfo": "Více informací",
"selectCollectionToBrowse": "Vyberte kolekci pro procházení",
"selectFile": "Vyberte soubor",
- "dragAndDrop": "Přetáhněte soubor",
"sizes": "Velikosti",
"width": "Šířka"
},
@@ -346,4 +350,4 @@
"viewingVersions": "Zobrazuji verze pro {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Zobrazuji verze pro globální {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/de.json b/src/translations/de.json
index ab45d0a4c37..fbeabb0b972 100644
--- a/src/translations/de.json
+++ b/src/translations/de.json
@@ -63,8 +63,8 @@
"deletingFile": "Beim Löschen der Datei ist ein Fehler aufgetreten.",
"deletingTitle": "Es gab ein Problem während der Löschung von {{title}}. Bitte überprüfe deine Verbindung und versuche es erneut.",
"emailOrPasswordIncorrect": "Die E-Mail-Adresse oder das Passwort sind nicht korrekt.",
- "followingFieldsInvalid_other": "Die folgenden Felder sind nicht korrekt:",
"followingFieldsInvalid_one": "Das folgende Feld ist nicht korrekt:",
+ "followingFieldsInvalid_other": "Die folgenden Felder sind nicht korrekt:",
"incorrectCollection": "Falsche Sammlung",
"invalidFileType": "Ungültiger Datei-Typ",
"invalidFileTypeValue": "Ungültiger Datei-Typ: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Erfolgreich gelöscht.",
"deleting": "Lösche...",
"descending": "Absteigend",
+ "deselectAllRows": "Alle Zeilen abwählen",
"duplicate": "Duplizieren",
"duplicateWithoutSaving": "Dupliziere ohne Änderungen zu speichern",
"edit": "Bearbeiten",
@@ -184,9 +185,9 @@
"email": "E-Mail",
"emailAddress": "E-Mail-Adresse",
"enterAValue": "Gib einen Wert ein",
- "fallbackToDefaultLocale": "Rückgriff auf das Standardgebietsschema",
"error": "Fehler",
"errors": "Fehler",
+ "fallbackToDefaultLocale": "Rückgriff auf das Standardgebietsschema",
"filter": "Filter",
"filterWhere": "Filter {{label}} wo",
"filters": "Filter",
@@ -222,10 +223,13 @@
"saving": "Speichert...",
"searchBy": "Suche nach {{label}}",
"selectAll": "Alle auswählen {{count}} {{label}}",
+ "selectAllRows": "Wählen Sie alle Zeilen aus",
"selectValue": "Wert auswählen",
"selectedCount": "{{count}} {{label}} ausgewählt",
+ "showAllLabel": "Zeige alle {{label}}",
"sorryNotFound": "Entschuldige, es entspricht nichts deiner Anfrage",
"sort": "Sortieren",
+ "sortByLabelDirection": "Sortieren nach {{label}} {{direction}}",
"stayOnThisPage": "Auf dieser Seite bleiben",
"submissionSuccessful": "Einrichung erfolgreich.",
"submit": "Senden",
@@ -346,4 +350,4 @@
"viewingVersions": "Betrachte Versionen für {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "`Betrachte Versionen für das Globale Dokument {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/en.json b/src/translations/en.json
index 0ef74f751ce..4091b46fc0d 100644
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Deleted successfully.",
"deleting": "Deleting...",
"descending": "Descending",
+ "deselectAllRows": "Deselect all rows",
"duplicate": "Duplicate",
"duplicateWithoutSaving": "Duplicate without saving changes",
"edit": "Edit",
@@ -222,10 +223,13 @@
"saving": "Saving...",
"searchBy": "Search by {{label}}",
"selectAll": "Select all {{count}} {{label}}",
+ "selectAllRows": "Select all rows",
"selectValue": "Select a value",
"selectedCount": "{{count}} {{label}} selected",
+ "showAllLabel": "Show all {{label}}",
"sorryNotFound": "Sorry—there is nothing to correspond with your request.",
"sort": "Sort",
+ "sortByLabelDirection": "Sort by {{label}} {{direction}}",
"stayOnThisPage": "Stay on this page",
"submissionSuccessful": "Submission Successful.",
"submit": "Submit",
diff --git a/src/translations/es.json b/src/translations/es.json
index c8212f4769d..e811099038c 100644
--- a/src/translations/es.json
+++ b/src/translations/es.json
@@ -63,8 +63,8 @@
"deletingFile": "Ocurrió un error al eliminar el archivo.",
"deletingTitle": "Ocurrió un error al eliminar {{title}}. Por favor revisa tu conexión y vuelve a intentarlo.",
"emailOrPasswordIncorrect": "El correo o la contraseña introducida es incorrecta.",
- "followingFieldsInvalid_other": "Los siguientes campos son inválidos:",
"followingFieldsInvalid_one": "El siguiente campo es inválido:",
+ "followingFieldsInvalid_other": "Los siguientes campos son inválidos:",
"incorrectCollection": "Colección Incorrecta",
"invalidFileType": "Tipo de archivo inválido",
"invalidFileTypeValue": "Tipo de archivo inválido: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Borrado exitosamente.",
"deleting": "Eliminando...",
"descending": "Descendente",
+ "deselectAllRows": "Deselecciona todas las filas",
"duplicate": "Duplicar",
"duplicateWithoutSaving": "Duplicar sin guardar cambios",
"edit": "Editar",
@@ -222,10 +223,13 @@
"saving": "Guardando...",
"searchBy": "Buscar por {{label}}",
"selectAll": "Seleccionar todo {{count}} {{label}}",
+ "selectAllRows": "Selecciona todas las filas",
"selectValue": "Selecciona un valor",
"selectedCount": "{{count}} {{label}} seleccionado",
+ "showAllLabel": "Muestra todas {{label}}",
"sorryNotFound": "Lo sentimos. No hay nada que corresponda con tu solicitud.",
"sort": "Ordenar",
+ "sortByLabelDirection": "Ordenar por {{label}} {{direction}}",
"stayOnThisPage": "Permanecer en esta página",
"submissionSuccessful": "Envío realizado correctamente.",
"submit": "Enviar",
@@ -346,4 +350,4 @@
"viewingVersions": "Viendo versiones para {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Viendo versiones para el global {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/fa.json b/src/translations/fa.json
index 5fb08555917..f22f6d75c88 100644
--- a/src/translations/fa.json
+++ b/src/translations/fa.json
@@ -63,8 +63,8 @@
"deletingFile": "هنگام حذف فایل خطایی روی داد.",
"deletingTitle": "هنگام حذف {{title}} خطایی رخ داد. لطفاً وضعیت اتصال اینترنت خود را بررسی کنید.",
"emailOrPasswordIncorrect": "رایانامه یا گذرواژه ارائه شده نادرست است.",
- "followingFieldsInvalid_other": "کادرهای زیر نامعتبر هستند:",
"followingFieldsInvalid_one": "کادر زیر نامعتبر است:",
+ "followingFieldsInvalid_other": "کادرهای زیر نامعتبر هستند:",
"incorrectCollection": "مجموعه نادرست",
"invalidFileType": "نوع رسانه نامعتبر است",
"invalidFileTypeValue": "نوع رسانه نامعتبر: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "با موفقیت حذف شد.",
"deleting": "در حال حذف...",
"descending": "رو به پایین",
+ "deselectAllRows": "تمام سطرها را از انتخاب خارج کنید",
"duplicate": "تکراری",
"duplicateWithoutSaving": "رونوشت بدون ذخیره کردن تغییرات",
"edit": "نگارش",
@@ -222,10 +223,13 @@
"saving": "در حال ذخیره...",
"searchBy": "جستجو بر اساس {{label}}",
"selectAll": "انتخاب همه {{count}} {{label}}",
+ "selectAllRows": "انتخاب تمام سطرها",
"selectValue": "یک مقدار را انتخاب کنید",
"selectedCount": "{{count}} {{label}} انتخاب شد",
+ "showAllLabel": "نمایش همه {{label}}",
"sorryNotFound": "متأسفانه چیزی برای مطابقت با درخواست شما وجود ندارد.",
"sort": "مرتبسازی",
+ "sortByLabelDirection": "مرتب کردن بر اساس {{label}} {{direction}}",
"stayOnThisPage": "ماندن در این برگه",
"submissionSuccessful": "با موفقیت ثبت شد.",
"submit": "فرستادن",
@@ -346,4 +350,4 @@
"viewingVersions": "مشاهده نگارشها برای {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "مشاهده نگارشهای کلی {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/fr.json b/src/translations/fr.json
index a4010c14776..a9b926e488a 100644
--- a/src/translations/fr.json
+++ b/src/translations/fr.json
@@ -63,8 +63,8 @@
"deletingFile": "Une erreur s'est produite lors de la suppression du fichier.",
"deletingTitle": "Une erreur s'est produite lors de la suppression de {{title}}. Veuillez vérifier votre connexion puis réessayer.",
"emailOrPasswordIncorrect": "L'adresse e-mail ou le mot de passe fourni est incorrect.",
- "followingFieldsInvalid_other": "Les champs suivants ne sont pas valides :",
"followingFieldsInvalid_one": "Le champ suivant n'est pas valide :",
+ "followingFieldsInvalid_other": "Les champs suivants ne sont pas valides :",
"incorrectCollection": "Collection incorrecte",
"invalidFileType": "Type de fichier invalide",
"invalidFileTypeValue": "Type de fichier invalide : {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Supprimé(e) avec succès.",
"deleting": "Suppression en cours...",
"descending": "Descendant(e)",
+ "deselectAllRows": "Désélectionner toutes les lignes",
"duplicate": "Dupliquer",
"duplicateWithoutSaving": "Dupliquer sans enregistrer les modifications",
"edit": "Éditer",
@@ -222,10 +223,13 @@
"saving": "Sauvegarde en cours...",
"searchBy": "Rechercher par {{label}}",
"selectAll": "Tout sélectionner {{count}} {{label}}",
+ "selectAllRows": "Sélectionnez toutes les lignes",
"selectValue": "Sélectionnez une valeur",
"selectedCount": "{{count}} {{label}} sélectionné",
+ "showAllLabel": "Afficher tous les {{label}}",
"sorryNotFound": "Désolé, rien ne correspond à votre demande.",
"sort": "Trier",
+ "sortByLabelDirection": "Trier par {{label}} {{direction}}",
"stayOnThisPage": "Rester sur cette page",
"submissionSuccessful": "Soumission réussie.",
"submit": "Soumettre",
@@ -346,4 +350,4 @@
"viewingVersions": "Affichage des versions de ou du {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Affichage des versions globales de ou du {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/hr.json b/src/translations/hr.json
index 39c4317e352..6d02fa444f6 100644
--- a/src/translations/hr.json
+++ b/src/translations/hr.json
@@ -63,8 +63,8 @@
"deletingFile": "Dogodila se pogreška pri brisanju datoteke.",
"deletingTitle": "Dogodila se pogreška pri brisanju {{title}}. Molim provjerite svoju internetsku vezu i pokušajte ponovno.",
"emailOrPasswordIncorrect": "Email ili lozinka netočni.",
- "followingFieldsInvalid_other": "Ova polja su nevaljana:",
"followingFieldsInvalid_one": " Ovo polje je nevaljano:",
+ "followingFieldsInvalid_other": "Ova polja su nevaljana:",
"incorrectCollection": "Nevaljana kolekcija",
"invalidFileType": "Nevaljan tip datoteke",
"invalidFileTypeValue": "Nevaljan tip datoteke: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Uspješno obrisano.",
"deleting": "Brisanje...",
"descending": "Silazno",
+ "deselectAllRows": "Odznači sve redove",
"duplicate": "Duplikat",
"duplicateWithoutSaving": "Dupliciraj bez spremanja promjena",
"edit": "Uredi",
@@ -222,10 +223,13 @@
"saving": "Spremanje...",
"searchBy": "Traži po {{label}}",
"selectAll": "Odaberite sve {{count}} {{label}}",
+ "selectAllRows": "Odaberite sve redove",
"selectValue": "Odaberi vrijednost",
"selectedCount": "{{count}} {{label}} odabrano",
+ "showAllLabel": "Prikaži sve {{label}}",
"sorryNotFound": "Nažalost, ne postoji ništa što odgovara vašem zahtjevu.",
"sort": "Sortiraj",
+ "sortByLabelDirection": "Sortiraj prema {{label}} {{direction}}",
"stayOnThisPage": "Ostani na ovoj stranici",
"submissionSuccessful": "Uspješno slanje",
"submit": "Podnesi",
@@ -346,4 +350,4 @@
"viewingVersions": "Pregled verzija za {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Pregled verzije za globalni {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/hu.json b/src/translations/hu.json
index 4d7f41ddd5c..e9347f082f2 100644
--- a/src/translations/hu.json
+++ b/src/translations/hu.json
@@ -63,8 +63,8 @@
"deletingFile": "Hiba történt a fájl törlésekor.",
"deletingTitle": "Hiba történt a {{title}} törlése közben. Kérjük, ellenőrizze a kapcsolatot, és próbálja meg újra.",
"emailOrPasswordIncorrect": "A megadott e-mail-cím vagy jelszó helytelen.",
- "followingFieldsInvalid_other": "A következő mezők érvénytelenek:",
"followingFieldsInvalid_one": "A következő mező érvénytelen:",
+ "followingFieldsInvalid_other": "A következő mezők érvénytelenek:",
"incorrectCollection": "Helytelen gyűjtemény",
"invalidFileType": "Érvénytelen fájltípus",
"invalidFileTypeValue": "Érvénytelen fájltípus: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Sikeresen törölve.",
"deleting": "Törlés...",
"descending": "Csökkenő",
+ "deselectAllRows": "Jelölje ki az összes sort",
"duplicate": "Duplikálás",
"duplicateWithoutSaving": "Duplikálás a módosítások mentése nélkül",
"edit": "Szerkesztés",
@@ -222,10 +223,13 @@
"saving": "Mentés...",
"searchBy": "Keresés a következő szerint: {{label}}",
"selectAll": "Az összes kijelölése: {{count}} {{label}}",
+ "selectAllRows": "Válassza ki az összes sort",
"selectValue": "Válasszon ki egy értéket",
"selectedCount": "{{count}} {{label}} kiválasztva",
+ "showAllLabel": "Mutasd az összes {{címke}}",
"sorryNotFound": "Sajnáljuk – nincs semmi, ami megfelelne a kérésének.",
"sort": "Rendezés",
+ "sortByLabelDirection": "Rendezés {{label}} {{direction}} szerint",
"stayOnThisPage": "Maradjon ezen az oldalon",
"submissionSuccessful": "Beküldés sikeres.",
"submit": "Beküldés",
@@ -247,20 +251,21 @@
"welcome": "Üdvözöljük"
},
"operators": {
+ "contains": "tartalmaz",
"equals": "egyenlő",
- "isNotEqualTo": "nem egyenlő",
- "isIn": "benne van",
- "isNotIn": "nincs benne",
"exists": "létezik",
"isGreaterThan": "nagyobb, mint",
+ "isGreaterThanOrEqualTo": "nagyobb vagy egyenlő, mint",
+ "isIn": "benne van",
"isLessThan": "kisebb, mint",
"isLessThanOrEqualTo": "kisebb vagy egyenlő, mint",
- "isGreaterThanOrEqualTo": "nagyobb vagy egyenlő, mint",
- "near": "közel",
"isLike": "olyan, mint",
- "contains": "tartalmaz"
+ "isNotEqualTo": "nem egyenlő",
+ "isNotIn": "nincs benne",
+ "near": "közel"
},
"upload": {
+ "dragAndDrop": "Húzzon ide egy fájlt",
"dragAndDropHere": "vagy húzzon ide egy fájlt",
"fileName": "Fájlnév",
"fileSize": "Fájl mérete",
@@ -269,7 +274,6 @@
"moreInfo": "További információ",
"selectCollectionToBrowse": "Válassza ki a böngészni kívánt gyűjteményt",
"selectFile": "Válasszon ki egy fájlt",
- "dragAndDrop": "Húzzon ide egy fájlt",
"sizes": "Méretek",
"width": "Szélesség"
},
@@ -346,4 +350,4 @@
"viewingVersions": "A {{entityLabel}} {{documentTitle}} verzióinak megtekintése",
"viewingVersionsGlobal": "A globális {{entityLabel}} verzióinak megtekintése"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/it.json b/src/translations/it.json
index 6c938f41512..0c60e9e71b3 100644
--- a/src/translations/it.json
+++ b/src/translations/it.json
@@ -63,8 +63,8 @@
"deletingFile": "Si è verificato un errore durante l'eleminazione del file.",
"deletingTitle": "Si è verificato un errore durante l'eliminazione di {{title}}. Per favore controlla la tua connessione e riprova.",
"emailOrPasswordIncorrect": "L'email o la password fornita non è corretta.",
- "followingFieldsInvalid_other": "I seguenti campi non sono validi:",
"followingFieldsInvalid_one": "Il seguente campo non è valido:",
+ "followingFieldsInvalid_other": "I seguenti campi non sono validi:",
"incorrectCollection": "Collezione non corretta",
"invalidFileType": "Tipo di file non valido",
"invalidFileTypeValue": "Tipo di file non valido: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Eliminato con successo.",
"deleting": "Sto eliminando...",
"descending": "Decrescente",
+ "deselectAllRows": "Deseleziona tutte le righe",
"duplicate": "Duplica",
"duplicateWithoutSaving": "Duplica senza salvare le modifiche",
"edit": "Modificare",
@@ -222,10 +223,13 @@
"saving": "Salvo...",
"searchBy": "Cerca per {{label}}",
"selectAll": "Seleziona tutto {{count}} {{label}}",
+ "selectAllRows": "Seleziona tutte le righe",
"selectValue": "Seleziona un valore",
"selectedCount": "{{count}} {{label}} selezionato",
+ "showAllLabel": "Mostra tutti {{label}}",
"sorryNotFound": "Siamo spiacenti, non c'è nulla che corrisponda alla tua richiesta.",
"sort": "Ordina",
+ "sortByLabelDirection": "Ordina per {{label}} {{direction}}",
"stayOnThisPage": "Rimani su questa pagina",
"submissionSuccessful": "Invio riuscito.",
"submit": "Invia",
@@ -346,4 +350,4 @@
"viewingVersions": "Visualizzazione delle versioni per {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "`Visualizzazione delle versioni per {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/ja.json b/src/translations/ja.json
index 17a7ebb6281..fcf1cdd76f3 100644
--- a/src/translations/ja.json
+++ b/src/translations/ja.json
@@ -63,8 +63,8 @@
"deletingFile": "ファイルの削除中にエラーが発生しました。",
"deletingTitle": "{{title}} を削除する際にエラーが発生しました。接続を確認してからもう一度お試しください。",
"emailOrPasswordIncorrect": "メールアドレス、または、パスワードが正しくありません。",
- "followingFieldsInvalid_other": "次のフィールドは無効です:",
"followingFieldsInvalid_one": "次のフィールドは無効です:",
+ "followingFieldsInvalid_other": "次のフィールドは無効です:",
"incorrectCollection": "不正なコレクション",
"invalidFileType": "無効なファイル形式",
"invalidFileTypeValue": "無効なファイル形式: {{value}}",
@@ -173,14 +173,15 @@
"deletedSuccessfully": "正常に削除されました。",
"deleting": "削除しています...",
"descending": "降順",
+ "deselectAllRows": "すべての行の選択を解除します",
"duplicate": "複製",
"duplicateWithoutSaving": "変更を保存せずに複製",
"edit": "編集",
"editLabel": "{{label}} を編集",
+ "editing": "編集",
"editingLabel_many": "{{count}}つの{{label}}を編集しています",
"editingLabel_one": "{{count}}つの{{label}}を編集しています",
"editingLabel_other": "{{count}}つの{{label}}を編集しています",
- "editing": "編集",
"email": "メールアドレス",
"emailAddress": "メールアドレス",
"enterAValue": "値を入力",
@@ -222,10 +223,13 @@
"saving": "保存しています...",
"searchBy": "{{label}} で検索",
"selectAll": "すべての{{count}}つの{{label}}を選択",
+ "selectAllRows": "すべての行を選択します",
"selectValue": "値を選択",
"selectedCount": "{{count}}つの{{label}}を選択中",
+ "showAllLabel": "すべての{{label}}を表示する",
"sorryNotFound": "申し訳ありません。リクエストに対応する内容が見つかりませんでした。",
"sort": "並び替え",
+ "sortByLabelDirection": "{{label}}により並べ替え {{direction}}",
"stayOnThisPage": "この画面にとどまる",
"submissionSuccessful": "送信が成功しました。",
"submit": "送信",
@@ -247,20 +251,21 @@
"welcome": "ようこそ"
},
"operators": {
+ "contains": "含む",
"equals": "等しい",
- "isNotEqualTo": "等しくない",
- "isIn": "あります",
- "isNotIn": "入っていません",
"exists": "存在す",
"isGreaterThan": "より大きい",
+ "isGreaterThanOrEqualTo": "以上",
+ "isIn": "あります",
"isLessThan": "より小さい",
"isLessThanOrEqualTo": "以下",
- "isGreaterThanOrEqualTo": "以上",
- "near": "近く",
"isLike": "のような",
- "contains": "含む"
+ "isNotEqualTo": "等しくない",
+ "isNotIn": "入っていません",
+ "near": "近く"
},
"upload": {
+ "dragAndDrop": "ファイルをドラッグ アンド ドロップする",
"dragAndDropHere": "または、このエリアにファイルをドラッグ & ドロップ",
"fileName": "ファイル名",
"fileSize": "ファイル容量",
@@ -269,7 +274,6 @@
"moreInfo": "詳細を表示",
"selectCollectionToBrowse": "閲覧するコレクションを選択",
"selectFile": "ファイルを選択",
- "dragAndDrop": "ファイルをドラッグ アンド ドロップする",
"sizes": "容量",
"width": "横幅"
},
@@ -293,15 +297,18 @@
"validUploadID": "有効なアップロードIDではありません。"
},
"version": {
+ "aboutToPublishSelection": "選択中のすべての{{label}}を公開しようとしています。よろしいですか?",
"aboutToRestore": "この {{label}} データを {{versionDate}} 時点のバージョンに復元しようとしています。",
"aboutToRestoreGlobal": "グローバルな {{label}} データを {{versionDate}} 時点のバージョンに復元しようとしています。",
"aboutToRevertToPublished": "このデータの変更を公開時の状態に戻そうとしています。よろしいですか?",
"aboutToUnpublish": "このデータを非公開にしようとしています。よろしいですか?",
+ "aboutToUnpublishSelection": "選択したすべての{{label}}の公開を取り消そうとしています。よろしいですか?",
"autosave": "自動保存",
"autosavedSuccessfully": "自動保存に成功しました。",
"autosavedVersion": "自動保存されたバージョン",
"changed": "変更済み",
"compareVersion": "バージョンを比較:",
+ "confirmPublish": "公開を確認する",
"confirmRevertToSaved": "保存された状態に戻す確認",
"confirmUnpublish": "非公開の確認",
"confirmVersionRestoration": "バージョン復元の確認",
@@ -313,6 +320,7 @@
"noRowsFound": "{{label}} は未設定です",
"preview": "プレビュー",
"problemRestoringVersion": "このバージョンの復元に問題がありました。",
+ "publish": "公開する",
"publishChanges": "変更内容を公開",
"published": "公開済み",
"restoreThisVersion": "このバージョンを復元",
@@ -324,6 +332,7 @@
"selectLocales": "表示するロケールを選択",
"selectVersionToCompare": "比較するバージョンを選択",
"showLocales": "ロケールを表示:",
+ "showingVersionsFor": "次のバージョンを表示します:",
"status": "ステータス",
"type": "タイプ",
"unpublish": "非公開",
@@ -332,6 +341,7 @@
"versionCount_many": "{{count}} バージョンがあります",
"versionCount_none": "バージョンがありません",
"versionCount_one": "{{count}} バージョンがあります",
+ "versionCount_other": "{{count}}バージョンが見つかりました",
"versionCreatedOn": "{{version}} 作成日時:",
"versionID": "バージョンID",
"versions": "バージョン",
@@ -340,4 +350,4 @@
"viewingVersions": "表示バージョン: {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "表示バージョン: グローバルな {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/my.json b/src/translations/my.json
index 7b1d54156f0..0c6d809b10c 100644
--- a/src/translations/my.json
+++ b/src/translations/my.json
@@ -63,8 +63,8 @@
"deletingFile": "ဖိုင်ကိုဖျက်ရာတွင် အမှားအယွင်းရှိနေသည်။",
"deletingTitle": "{{title}} ကို ဖျက်ရာတွင် အမှားအယွင်းရှိခဲ့သည်။ သင့် အင်တာနက်လိုင်းအား စစ်ဆေးပြီး ထပ်မံကြို့စားကြည့်ပါ။",
"emailOrPasswordIncorrect": "ထည့်သွင်းထားသော အီးမေးလ် သို့မဟုတ် စကားဝှက်သည် မမှန်ပါ။",
- "followingFieldsInvalid_other": "ထည့်သွင်းထားသော အချက်အလက်များသည် မမှန်ကန်ပါ။",
"followingFieldsInvalid_one": "ထည့်သွင်းထားသော အချက်အလက်သည် မမှန်ကန်ပါ။",
+ "followingFieldsInvalid_other": "ထည့်သွင်းထားသော အချက်အလက်များသည် မမှန်ကန်ပါ။",
"incorrectCollection": "မှားယွင်းသော စုစည်းမှု",
"invalidFileType": "မမှန်ကန်သော ဖိုင်အမျိုးအစား",
"invalidFileTypeValue": "မမှန်ကန်သော ဖိုင်အမျိုးအစား: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "အောင်မြင်စွာ ဖျက်လိုက်ပါပြီ။",
"deleting": "ဖျက်နေဆဲ ...",
"descending": "ဆင်းသက်လာသည်။",
+ "deselectAllRows": "အားလုံးကို မရွေးနိုင်ပါ",
"duplicate": "ပုံတူပွားမည်။",
"duplicateWithoutSaving": "သေချာပါပြီ။",
"edit": "တည်းဖြတ်ပါ။",
@@ -222,10 +223,13 @@
"saving": "သိမ်းနေဆဲ ...",
"searchBy": "ရှာဖွေပါ။",
"selectAll": "{{count}} {{label}} အားလုံးကို ရွေးပါ",
+ "selectAllRows": "အားလုံးကိုရွေးချယ်ပါ",
"selectValue": "တစ်ခုခုကို ရွေးချယ်ပါ။",
"selectedCount": "{{count}} {{label}} ကို ရွေးထားသည်။",
+ "showAllLabel": "Tunjukkan semua {{label}}",
"sorryNotFound": "ဝမ်းနည်းပါသည်။ သင်ရှာနေတဲ့ဟာ ဒီမှာမရှိပါ။",
"sort": "အစဉ်လိုက်",
+ "sortByLabelDirection": "အစဉ်အလိုက် စီမံခန့်ခွဲထားသည် {{label}} {{direction}}",
"stayOnThisPage": "ဒီမှာပဲ ဆက်နေမည်။",
"submissionSuccessful": "သိမ်းဆည်းမှု အောင်မြင်ပါသည်။",
"submit": "သိမ်းဆည်းမည်။",
@@ -346,4 +350,4 @@
"viewingVersions": "{{entityLabel}} {{documentTitle}} အတွက် ဗားရှင်းများကို ကြည့်ရှုခြင်း",
"viewingVersionsGlobal": "`ဂလိုဘယ်ဆိုင်ရာ {{entityLabel}} အတွက် ဗားရှင်းများကို ကြည့်ရှုနေသည်"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/nb.json b/src/translations/nb.json
index 3493db1de14..2e7582eee1b 100644
--- a/src/translations/nb.json
+++ b/src/translations/nb.json
@@ -63,8 +63,8 @@
"deletingFile": "Det oppstod en feil under sletting av filen.",
"deletingTitle": "Det oppstod en feil under sletting av {{title}}. Sjekk tilkoblingen og prøv igjen.",
"emailOrPasswordIncorrect": "E-postadressen eller passordet er feil.",
- "followingFieldsInvalid_other": "Følgende felter er ugyldige:",
"followingFieldsInvalid_one": "Følgende felt er ugyldig:",
+ "followingFieldsInvalid_other": "Følgende felter er ugyldige:",
"incorrectCollection": "Ugyldig samling",
"invalidFileType": "Ugyldig filtype",
"invalidFileTypeValue": "Ugyldig filtype: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Slettet.",
"deleting": "Sletter...",
"descending": "Synkende",
+ "deselectAllRows": "Fjern markeringen fra alle rader",
"duplicate": "Dupliser",
"duplicateWithoutSaving": "Dupliser uten å lagre endringer",
"edit": "Redigere",
@@ -222,10 +223,13 @@
"saving": "Lagrer...",
"searchBy": "Søk etter {{label}}",
"selectAll": "Velg alle {{count}} {{label}}",
+ "selectAllRows": "Velg alle rader",
"selectValue": "Velg en verdi",
"selectedCount": "{{count}} {{label}} valgt",
+ "showAllLabel": "Vis alle {{label}}",
"sorryNotFound": "Beklager, det er ingenting som samsvarer med forespørselen din.",
"sort": "Sortér",
+ "sortByLabelDirection": "Sorter etter {{label}} {{direction}}",
"stayOnThisPage": "Bli på denne siden",
"submissionSuccessful": "Innsending vellykket.",
"submit": "Send inn",
@@ -346,4 +350,4 @@
"viewingVersions": "Viser versjoner for {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Viser versjoner for den globale variabelen {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/nl.json b/src/translations/nl.json
index f7ccc9895b2..60fb63b1bba 100644
--- a/src/translations/nl.json
+++ b/src/translations/nl.json
@@ -63,8 +63,8 @@
"deletingFile": "Er is een fout opgetreden bij het verwijderen van dit bestand.",
"deletingTitle": "Er is een fout opgetreden tijdens het verwijderen van {{title}}. Controleer uw verbinding en probeer het opnieuw.",
"emailOrPasswordIncorrect": "Het opgegeven e-mailadres of wachtwoord is onjuist.",
- "followingFieldsInvalid_other": "De volgende velden zijn ongeldig:",
"followingFieldsInvalid_one": "Het volgende veld is ongeldig:",
+ "followingFieldsInvalid_other": "De volgende velden zijn ongeldig:",
"incorrectCollection": "Ongeldige collectie",
"invalidFileType": "Ongeldig bestandstype",
"invalidFileTypeValue": "Ongeldig bestandstype: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Succesvol verwijderd.",
"deleting": "Verwijderen...",
"descending": "Aflopend",
+ "deselectAllRows": "Deselecteer alle rijen",
"duplicate": "Dupliceren",
"duplicateWithoutSaving": "Dupliceren zonder wijzigingen te bewaren",
"edit": "Bewerk",
@@ -222,10 +223,13 @@
"saving": "Bewaren...",
"searchBy": "Zoeken op {{label}}",
"selectAll": "Alles selecteren {{count}} {{label}}",
+ "selectAllRows": "Selecteer alle rijen",
"selectValue": "Selecteer een waarde",
"selectedCount": "{{count}} {{label}} geselecteerd",
+ "showAllLabel": "Toon alle {{label}}",
"sorryNotFound": "Sorry, er is niets dat overeen komt met uw verzoek.",
"sort": "Sorteer",
+ "sortByLabelDirection": "Sorteer op {{label}} {{direction}}",
"stayOnThisPage": "Blijf op deze pagina",
"submissionSuccessful": "Indiening succesvol.",
"submit": "Indienen",
@@ -346,4 +350,4 @@
"viewingVersions": "Bekijk versies voor {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "`Bekijk versies voor global {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/pl.json b/src/translations/pl.json
index 99613d87c44..4ff73ba21ad 100644
--- a/src/translations/pl.json
+++ b/src/translations/pl.json
@@ -63,8 +63,8 @@
"deletingFile": "",
"deletingTitle": "Wystąpił błąd podczas usuwania {{title}}. Proszę, sprawdź swoje połączenie i spróbuj ponownie.",
"emailOrPasswordIncorrect": "Podany adres e-mail lub hasło jest nieprawidłowe.",
- "followingFieldsInvalid_other": "Następujące pola są nieprawidłowe:",
"followingFieldsInvalid_one": "To pole jest nieprawidłowe:",
+ "followingFieldsInvalid_other": "Następujące pola są nieprawidłowe:",
"incorrectCollection": "Nieprawidłowa kolekcja",
"invalidFileType": "Nieprawidłowy typ pliku",
"invalidFileTypeValue": "Nieprawidłowy typ pliku: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Skutecznie usunięte.",
"deleting": "Usuwanie...",
"descending": "Malejąco",
+ "deselectAllRows": "Odznacz wszystkie wiersze",
"duplicate": "Zduplikuj",
"duplicateWithoutSaving": "Zduplikuj bez zapisywania zmian",
"edit": "Edytować",
@@ -222,10 +223,13 @@
"saving": "Zapisywanie...",
"searchBy": "Szukaj według",
"selectAll": "Wybierz wszystkie {{liczba}} {{etykieta}}",
+ "selectAllRows": "Wybierz wszystkie wiersze",
"selectValue": "Wybierz wartość",
"selectedCount": "Wybrano {{count}} {{label}}",
+ "showAllLabel": "Pokaż wszystkie {{label}}",
"sorryNotFound": "Przepraszamy — nie ma nic, co odpowiadałoby twojej prośbie.",
"sort": "Sortuj",
+ "sortByLabelDirection": "Sortuj według {{label}} {{direction}}",
"stayOnThisPage": "Pozostań na stronie",
"submissionSuccessful": "Zgłoszenie zakończone powodzeniem.",
"submit": "Zatwierdź",
@@ -346,4 +350,4 @@
"viewingVersions": "Przeglądanie wersji {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Przeglądanie wersji dla globalnej kolekcji {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/pt.json b/src/translations/pt.json
index 9166a657381..70693957a5d 100644
--- a/src/translations/pt.json
+++ b/src/translations/pt.json
@@ -63,8 +63,8 @@
"deletingFile": "Ocorreu um erro ao excluir o arquivo.",
"deletingTitle": "Ocorreu um erro ao excluir {{title}}. Por favor, verifique sua conexão e tente novamente.",
"emailOrPasswordIncorrect": "O email ou senha fornecido está incorreto.",
- "followingFieldsInvalid_other": "Os campos a seguir estão inválidos:",
"followingFieldsInvalid_one": "O campo a seguir está inválido:",
+ "followingFieldsInvalid_other": "Os campos a seguir estão inválidos:",
"incorrectCollection": "Coleção Incorreta",
"invalidFileType": "Tipo de arquivo inválido",
"invalidFileTypeValue": "Tipo de arquivo inválido: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Apagado com sucesso.",
"deleting": "Excluindo...",
"descending": "Decrescente",
+ "deselectAllRows": "Desmarcar todas as linhas",
"duplicate": "Duplicar",
"duplicateWithoutSaving": "Duplicar sem salvar alterações",
"edit": "Editar",
@@ -222,10 +223,13 @@
"saving": "Salvando...",
"searchBy": "Buscar por {{label}}",
"selectAll": "Selecione tudo {{count}} {{label}}",
+ "selectAllRows": "Selecione todas as linhas",
"selectValue": "Selecione um valor",
"selectedCount": "{{count}} {{label}} selecionado",
+ "showAllLabel": "Mostre todos {{label}}",
"sorryNotFound": "Desculpe—não há nada que corresponda à sua requisição.",
"sort": "Ordenar",
+ "sortByLabelDirection": "Ordenar por {{label}} {{direction}}",
"stayOnThisPage": "Permanecer nessa página",
"submissionSuccessful": "Envio bem-sucedido.",
"submit": "Enviar",
@@ -346,4 +350,4 @@
"viewingVersions": "Visualizando versões para o/a {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "`Visualizando versões para o global {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/ro.json b/src/translations/ro.json
index 56298aa24ac..8e4de0e6d9c 100644
--- a/src/translations/ro.json
+++ b/src/translations/ro.json
@@ -63,8 +63,8 @@
"deletingFile": "S-a produs o eroare la ștergerea fișierului.",
"deletingTitle": "S-a produs o eroare în timpul ștergerii {{title}}. Vă rugăm să verificați conexiunea și să încercați din nou.",
"emailOrPasswordIncorrect": "Adresa de e-mail sau parola este incorectă.",
- "followingFieldsInvalid_other": "Următoarele câmpuri nu sunt valabile:",
"followingFieldsInvalid_one": "Următorul câmp nu este valid:",
+ "followingFieldsInvalid_other": "Următoarele câmpuri nu sunt valabile:",
"incorrectCollection": "Colecție incorectă",
"invalidFileType": "Tip de fișier invalid",
"invalidFileTypeValue": "Tip de fișier invalid: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Șters cu succes.",
"deleting": "Deleting...",
"descending": "Descendentă",
+ "deselectAllRows": "Deselectează toate rândurile",
"duplicate": "Duplicați",
"duplicateWithoutSaving": "Duplicați fără salvarea modificărilor",
"edit": "Editează",
@@ -222,10 +223,13 @@
"saving": "Salvare...",
"searchBy": "Căutați după {{label}}",
"selectAll": "Selectați toate {{count}} {{label}}",
+ "selectAllRows": "Selectează toate rândurile",
"selectValue": "Selectați o valoare",
"selectedCount": "{{count}} {{label}} selectate",
+ "showAllLabel": "Afișează toate {{eticheta}}",
"sorryNotFound": "Ne pare rău - nu există nimic care să corespundă cu cererea dvs.",
"sort": "Sortează",
+ "sortByLabelDirection": "Sortează după {{etichetă}} {{direcţie}}",
"stayOnThisPage": "Rămâneți pe această pagină",
"submissionSuccessful": "Trimitere cu succes.",
"submit": "Trimite",
@@ -346,4 +350,4 @@
"viewingVersions": "Vizualizarea versiunilor pentru {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Vizualizarea versiunilor pentru globala {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/ru.json b/src/translations/ru.json
index 04e82d0bfc7..8ef06311b96 100644
--- a/src/translations/ru.json
+++ b/src/translations/ru.json
@@ -63,8 +63,8 @@
"deletingFile": "Произошла ошибка при удалении файла.",
"deletingTitle": "При удалении {{title}} произошла ошибка. Пожалуйста, проверьте соединение и повторите попытку.",
"emailOrPasswordIncorrect": "Указанный email или пароль неверен.",
- "followingFieldsInvalid_other": "Следующие поля недействительны:",
"followingFieldsInvalid_one": "Следующее поле недействительно:",
+ "followingFieldsInvalid_other": "Следующие поля недействительны:",
"incorrectCollection": "Неправильная Коллекция",
"invalidFileType": "Недопустимый тип файла",
"invalidFileTypeValue": "Недопустимый тип файла: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Удален успешно.",
"deleting": "Удаление...",
"descending": "Уменьшение",
+ "deselectAllRows": "Снять выделение со всех строк",
"duplicate": "Дублировать",
"duplicateWithoutSaving": "Дублирование без сохранения изменений",
"edit": "Редактировать",
@@ -222,10 +223,13 @@
"saving": "Сохранение...",
"searchBy": "Искать по",
"selectAll": "Выбрать все {{count}} {{label}}",
+ "selectAllRows": "Выбрать все строки",
"selectValue": "Выбрать значение",
"selectedCount": "{{count}} {{label}} выбрано",
+ "showAllLabel": "Показать все {{label}}",
"sorryNotFound": "К сожалению, ничего подходящего под ваш запрос нет.",
"sort": "Сортировать",
+ "sortByLabelDirection": "Сортировать по {{label}} {{direction}}",
"stayOnThisPage": "Остаться на этой странице",
"submissionSuccessful": "Успешно отправлено.",
"submit": "Отправить",
@@ -346,4 +350,4 @@
"viewingVersions": "Просмотр версий для {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "`Просмотр версии для глобальной Коллекции {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/sv.json b/src/translations/sv.json
index 4fd209c5b23..56d56150962 100644
--- a/src/translations/sv.json
+++ b/src/translations/sv.json
@@ -63,8 +63,8 @@
"deletingFile": "Det gick inte att ta bort filen.",
"deletingTitle": "Det uppstod ett fel vid borttagningen av {{title}}. Vänligen kontrollera din anslutning och försök igen.",
"emailOrPasswordIncorrect": "E-postadressen eller lösenordet som angivits är felaktigt.",
- "followingFieldsInvalid_other": "Följande fält är ogiltiga:",
"followingFieldsInvalid_one": "Följande fält är ogiltigt:",
+ "followingFieldsInvalid_other": "Följande fält är ogiltiga:",
"incorrectCollection": "Felaktig Samling",
"invalidFileType": "Ogiltig filtyp",
"invalidFileTypeValue": "Ogiltig filtyp: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Togs bort framgångsrikt.",
"deleting": "Tar bort...",
"descending": "Fallande",
+ "deselectAllRows": "Avmarkera alla rader",
"duplicate": "Duplicera",
"duplicateWithoutSaving": "Duplicera utan att spara ändringar",
"edit": "Redigera",
@@ -222,10 +223,13 @@
"saving": "Sparar...",
"searchBy": "Sök efter {{label}}",
"selectAll": "Välj alla {{count}} {{label}}",
+ "selectAllRows": "Välj alla rader",
"selectValue": "Välj ett värde",
"selectedCount": "{{count}} {{label}} har valts",
+ "showAllLabel": "Visa alla {{label}}",
"sorryNotFound": "Tyvärr–det finns inget som motsvarar din begäran.",
"sort": "Sortera",
+ "sortByLabelDirection": "Sortera efter {{label}} {{direction}}",
"stayOnThisPage": "Stanna på denna sida",
"submissionSuccessful": "Inlämningen Lyckades.",
"submit": "Lämna in",
@@ -346,4 +350,4 @@
"viewingVersions": "Visar versioner för {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Visa versioner för den globala {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/th.json b/src/translations/th.json
index 09968e06e21..c9c111f29cb 100644
--- a/src/translations/th.json
+++ b/src/translations/th.json
@@ -63,8 +63,8 @@
"deletingFile": "เกิดปัญหาระหว่างการลบไฟล์",
"deletingTitle": "เกิดปัญหาระหว่างการลบ {{title}} โปรดตรวจสอบการเชื่อมต่อของคุณแล้วลองอีกครั้ง",
"emailOrPasswordIncorrect": "อีเมลหรือรหัสผ่านไม่ถูกต้อง",
- "followingFieldsInvalid_other": "ช่องต่อไปนี้ไม่ถูกต้อง:",
"followingFieldsInvalid_one": "ช่องต่อไปนี้ไม่ถูกต้อง:",
+ "followingFieldsInvalid_other": "ช่องต่อไปนี้ไม่ถูกต้อง:",
"incorrectCollection": "Collection ไม่ถูกต้อง",
"invalidFileType": "ประเภทของไฟล์ไม่ถูกต้อง",
"invalidFileTypeValue": "ประเภทของไฟล์ไม่ถูกต้อง: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "ลบสำเร็จ",
"deleting": "กำลังลบ...",
"descending": "มากไปน้อย",
+ "deselectAllRows": "ยกเลิกการเลือกทุกแถว",
"duplicate": "สำเนา",
"duplicateWithoutSaving": "สำเนาโดยไม่บันทึกการแก้ไข",
"edit": "แก้ไข",
@@ -222,10 +223,13 @@
"saving": "กำลังบันทึก...",
"searchBy": "ค้นหาด้วย {{label}}",
"selectAll": "เลือกทั้งหมด {{count}} {{label}}",
+ "selectAllRows": "เลือกทุกแถว",
"selectValue": "เลือกค่า",
"selectedCount": "เลือก {{count}} {{label}} แล้ว",
+ "showAllLabel": "แสดง {{label}} ทั้งหมด",
"sorryNotFound": "ขออภัย ไม่สามารถทำตามคำขอของคุณได้",
"sort": "เรียง",
+ "sortByLabelDirection": "เรียงลำดับตาม {{label}} {{direction}}",
"stayOnThisPage": "อยู่หน้านี้ต่อ",
"submissionSuccessful": "ส่งสำเร็จ",
"submit": "ส่ง",
@@ -346,4 +350,4 @@
"viewingVersions": "กำลังดูเวอร์ชันของ {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "กำลังดูเวอร์ชันของ global {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/tr.json b/src/translations/tr.json
index 4a5c10468df..bb6a256ce9c 100644
--- a/src/translations/tr.json
+++ b/src/translations/tr.json
@@ -63,8 +63,8 @@
"deletingFile": "Dosya silinirken bir hatayla karşılaşıldı.",
"deletingTitle": "{{title}} silinirken bir sorun yaşandı. Lütfen internet bağlantınızı kontrol edip tekrar deneyin.",
"emailOrPasswordIncorrect": "Girilen e-posta veya parola hatalı",
- "followingFieldsInvalid_other": "Lütfen geçersiz alanları düzeltin:",
"followingFieldsInvalid_one": "Lütfen geçersiz alanı düzeltin:",
+ "followingFieldsInvalid_other": "Lütfen geçersiz alanları düzeltin:",
"incorrectCollection": "Hatalı koleksiyon",
"invalidFileType": "Geçersiz dosya türü",
"invalidFileTypeValue": "Geçersiz dosya türü: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Başarıyla silindi.",
"deleting": "Siliniyor...",
"descending": "Azalan",
+ "deselectAllRows": "Tüm satırların seçimini kaldır",
"duplicate": "Çoğalt",
"duplicateWithoutSaving": "Ayarları kaydetmeden çoğalt",
"edit": "Düzenle",
@@ -222,10 +223,13 @@
"saving": "Kaydediliyor...",
"searchBy": "Şuna göre sırala: {{label}}",
"selectAll": "Tüm {{count}} {{label}}'ı seçin",
+ "selectAllRows": "Tüm satırları seçin",
"selectValue": "Bir değer seçin",
"selectedCount": "{{count}} {{label}} seçildi",
+ "showAllLabel": "Tüm {{label}} göster",
"sorryNotFound": "Üzgünüz, isteğinizle eşleşen bir sonuç bulunamadı.",
"sort": "Sırala",
+ "sortByLabelDirection": "{{label}} göre sırala {{direction}}",
"stayOnThisPage": "Bu sayfada kal",
"submissionSuccessful": "Gönderme başarılı",
"submit": "Gönder",
@@ -346,4 +350,4 @@
"viewingVersions": "{{entityLabel}} {{documentTitle}} için sürümler gösteriliyor",
"viewingVersionsGlobal": "`Global {{entityLabel}} için sürümler gösteriliyor"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/translation-schema.json b/src/translations/translation-schema.json
index 86f6c1687c5..1545c572d56 100644
--- a/src/translations/translation-schema.json
+++ b/src/translations/translation-schema.json
@@ -663,6 +663,9 @@
"descending": {
"type": "string"
},
+ "deselectAllRows": {
+ "type": "string"
+ },
"duplicate": {
"type": "string"
},
@@ -810,18 +813,27 @@
"selectAll": {
"type": "string"
},
+ "selectAllRows": {
+ "type": "string"
+ },
"selectValue": {
"type": "string"
},
"selectedCount": {
"type": "string"
},
+ "showAllLabel": {
+ "type": "string"
+ },
"sorryNotFound": {
"type": "string"
},
"sort": {
"type": "string"
},
+ "sortByLabelDirection": {
+ "type": "string"
+ },
"stayOnThisPage": {
"type": "string"
},
diff --git a/src/translations/ua.json b/src/translations/ua.json
index 257f37362f8..679ad4e0eb6 100644
--- a/src/translations/ua.json
+++ b/src/translations/ua.json
@@ -63,8 +63,8 @@
"deletingFile": "Виникла помилка під час видалення файлу",
"deletingTitle": "Виникла помилка під час видалення {{title}}, Будь ласка, перевірте ваше з'єднання та спробуйте ще раз.",
"emailOrPasswordIncorrect": "Вказаний email або пароль не є вірними",
- "followingFieldsInvalid_other": "Наступні поля не є вірними",
"followingFieldsInvalid_one": "Наступне поле не є вірним:",
+ "followingFieldsInvalid_other": "Наступні поля не є вірними",
"incorrectCollection": "Неправильна колекція",
"invalidFileType": "Невіртий тип файлу",
"invalidFileTypeValue": "Невірний тип файлу: {{value}}",
@@ -131,8 +131,8 @@
"selectExistingLabel": "Вибрати існуючий {{label}}",
"selectFieldsToEdit": "Виберіть поля для редагування",
"showAll": "Показати все",
- "swapUpload": "Замінити завантаження",
"swapRelationship": "Замінити зв'язок",
+ "swapUpload": "Замінити завантаження",
"textToDisplay": "Текст для відображення",
"toggleBlock": "Перемкнути блок",
"uploadNewLabel": "Завантажити новий {{label}}"
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Успішно видалено.",
"deleting": "Видалення...",
"descending": "В порядку спадання",
+ "deselectAllRows": "Скасувати вибір всіх рядків",
"duplicate": "Дублювати",
"duplicateWithoutSaving": "Дублювання без збереження змін",
"edit": "Редагувати",
@@ -222,10 +223,13 @@
"saving": "Збереження...",
"searchBy": "Шукати по {{label}}",
"selectAll": "Вибрати всі {{count}} {{label}}",
+ "selectAllRows": "Вибрати всі рядки",
"selectValue": "Вибрати значення",
"selectedCount": "Вибрано {{count}} {{label}}",
+ "showAllLabel": "Показати всі {{label}}",
"sorryNotFound": "Вибачте - немає нічого, що відповідало б Вашому запиту.",
"sort": "Сортувати",
+ "sortByLabelDirection": "Сортувати за {{label}} {{direction}}",
"stayOnThisPage": "Залишитись на цій сторінці",
"submissionSuccessful": "Успішно відправлено.",
"submit": "Відправити",
@@ -346,4 +350,4 @@
"viewingVersions": "Огляд версій для {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Огляд версій для глобальної колекції {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/vi.json b/src/translations/vi.json
index ded98ed594d..f93522a9a66 100644
--- a/src/translations/vi.json
+++ b/src/translations/vi.json
@@ -63,8 +63,8 @@
"deletingFile": "Lỗi - Đã xảy ra vấn đề khi xóa tệp này.",
"deletingTitle": "Lỗi - Đã xảy ra vấn đề khi xóa {{title}}. Hãy kiểm tra kết nối mạng và thử lại.",
"emailOrPasswordIncorrect": "Lỗi - Email hoặc mật khẩu không chính xác.",
- "followingFieldsInvalid_other": "Lỗi - Những fields sau không hợp lệ:",
"followingFieldsInvalid_one": "Lỗi - Field sau không hợp lệ:",
+ "followingFieldsInvalid_other": "Lỗi - Những fields sau không hợp lệ:",
"incorrectCollection": "Lỗi - Collection không hợp lệ.",
"invalidFileType": "Lỗi - Định dạng tệp không hợp lệ.",
"invalidFileTypeValue": "Lỗi - Định dạng tệp không hợp lệ: {{value}}.",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "Đã xoá thành công.",
"deleting": "Đang xóa...",
"descending": "Xếp theo thứ tự giảm dần",
+ "deselectAllRows": "Bỏ chọn tất cả các hàng",
"duplicate": "Tạo bản sao",
"duplicateWithoutSaving": "Không lưu dữ liệu và tạo bản sao",
"edit": "Chỉnh sửa",
@@ -222,10 +223,13 @@
"saving": "Đang lưu...",
"searchBy": "Tìm với {{label}}",
"selectAll": "Chọn tất cả {{count}} {{label}}",
+ "selectAllRows": "Chọn tất cả các hàng",
"selectValue": "Chọn một giá trị",
"selectedCount": "Đã chọn {{count}} {{label}}",
+ "showAllLabel": "Hiển thị tất cả {{label}}",
"sorryNotFound": "Xin lỗi, không có kết quả nào tương ứng với request của bạn.",
"sort": "Sắp xếp",
+ "sortByLabelDirection": "Sắp xếp theo {{label}} {{direction}}",
"stayOnThisPage": "Ở lại trang này",
"submissionSuccessful": "Gửi thành công.",
"submit": "Gửi",
@@ -346,4 +350,4 @@
"viewingVersions": "Xem những phiên bản của {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "`Xem những phiên bản toàn thể (global) của {{entityLabel}}"
}
-}
+}
\ No newline at end of file
diff --git a/src/translations/zh.json b/src/translations/zh.json
index a37a48d4b78..a1ed3e0ee84 100644
--- a/src/translations/zh.json
+++ b/src/translations/zh.json
@@ -63,8 +63,8 @@
"deletingFile": "删除文件时出现了错误。",
"deletingTitle": "删除{{title}}时出现了错误。请检查您的连接并重试。",
"emailOrPasswordIncorrect": "提供的电子邮件或密码不正确。",
- "followingFieldsInvalid_other": "以下字段是无效的:",
"followingFieldsInvalid_one": "下面的字段是无效的:",
+ "followingFieldsInvalid_other": "以下字段是无效的:",
"incorrectCollection": "不正确的集合",
"invalidFileType": "无效的文件类型",
"invalidFileTypeValue": "无效的文件类型: {{value}}",
@@ -173,6 +173,7 @@
"deletedSuccessfully": "已成功删除。",
"deleting": "删除中...",
"descending": "降序",
+ "deselectAllRows": "取消选择所有行",
"duplicate": "重复",
"duplicateWithoutSaving": "重复而不保存更改。",
"edit": "编辑",
@@ -222,10 +223,13 @@
"saving": "保存中...",
"searchBy": "搜索{{label}}",
"selectAll": "选择所有 {{count}} {{label}}",
+ "selectAllRows": "选择所有行",
"selectValue": "选择一个值",
"selectedCount": "已选择 {{count}} {{label}}",
+ "showAllLabel": "显示所有{{label}}",
"sorryNotFound": "对不起,没有与您的请求相对应的东西。",
"sort": "排序",
+ "sortByLabelDirection": "按{{label}} {{direction}}排序",
"stayOnThisPage": "停留在此页面",
"submissionSuccessful": "提交成功。",
"submit": "提交",
@@ -346,4 +350,4 @@
"viewingVersions": "正在查看{{entityLabel}} {{documentTitle}}的版本",
"viewingVersionsGlobal": "正在查看全局{{entityLabel}}的版本"
}
-}
+}
\ No newline at end of file
diff --git a/src/types/constants.ts b/src/types/constants.ts
new file mode 100644
index 00000000000..ef89774f9bb
--- /dev/null
+++ b/src/types/constants.ts
@@ -0,0 +1,15 @@
+export const validOperators = [
+ 'equals',
+ 'contains',
+ 'not_equals',
+ 'in',
+ 'all',
+ 'not_in',
+ 'exists',
+ 'greater_than',
+ 'greater_than_equal',
+ 'less_than',
+ 'less_than_equal',
+ 'like',
+ 'near',
+] as const;
diff --git a/src/types/index.ts b/src/types/index.ts
index be11631972b..d05551577b8 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -1,23 +1,11 @@
import { Document as MongooseDocument } from 'mongoose';
import { TypeWithTimestamps } from '../collections/config/types';
import { FileData } from '../uploads/types';
+import { validOperators } from './constants';
export { PayloadRequest } from '../express/types';
-export type Operator =
- | 'equals'
- | 'contains'
- | 'not_equals'
- | 'in'
- | 'all'
- | 'not_in'
- | 'exists'
- | 'greater_than'
- | 'greater_than_equal'
- | 'less_than'
- | 'less_than_equal'
- | 'like'
- | 'near';
+export type Operator = typeof validOperators[number];
export type WhereField = {
[key in Operator]?: unknown;
diff --git a/src/uploads/generateFileData.ts b/src/uploads/generateFileData.ts
index c2fe72ecd8f..247c9259701 100644
--- a/src/uploads/generateFileData.ts
+++ b/src/uploads/generateFileData.ts
@@ -115,6 +115,7 @@ export const generateFileData = async ({
fileBuffer = await sharpFile.toBuffer({ resolveWithObject: true });
({ mime, ext } = await fromBuffer(fileBuffer.data)); // This is getting an incorrect gif height back.
fileData.width = fileBuffer.info.width;
+ fileData.height = fileBuffer.info.height;
fileData.filesize = fileBuffer.info.size;
// Animated GIFs + WebP aggregate the height from every frame, so we need to use divide by number of pages
diff --git a/src/uploads/imageResizer.ts b/src/uploads/imageResizer.ts
index 7da8f0a3134..d28d85a7d71 100644
--- a/src/uploads/imageResizer.ts
+++ b/src/uploads/imageResizer.ts
@@ -106,7 +106,7 @@ const createResult = (
* @returns true if the image needs to be resized, false otherwise
*/
const needsResize = (
- { width: desiredWidth, height: desiredHeigth, withoutEnlargement, withoutReduction }: ImageSize,
+ { width: desiredWidth, height: desiredHeight, withoutEnlargement, withoutReduction }: ImageSize,
original: ProbedImageSize,
): boolean => {
// allow enlargement or prevent reduction (our default is to prevent
@@ -115,7 +115,8 @@ const needsResize = (
return true; // needs resize
}
- const isWidthOrHeightNotDefined = !desiredHeigth || !desiredWidth;
+ const isWidthOrHeightNotDefined = !desiredHeight || !desiredWidth;
+
if (isWidthOrHeightNotDefined) {
// If with and height are not defined, it means there is a format conversion
// and the image needs to be "resized" (transformed).
@@ -123,7 +124,7 @@ const needsResize = (
}
const hasInsufficientWidth = original.width < desiredWidth;
- const hasInsufficientHeight = original.height < desiredHeigth;
+ const hasInsufficientHeight = original.height < desiredHeight;
if (hasInsufficientWidth && hasInsufficientHeight) {
// doesn't need resize - prevent enlargement. This should only happen if both width and height are insufficient.
// if only one dimension is insufficient and the other is sufficient, resizing needs to happen, as the image
diff --git a/src/utilities/checkDuplicateCollections.ts b/src/utilities/checkDuplicateCollections.ts
index 2a34f67c68e..03c1146c8ee 100644
--- a/src/utilities/checkDuplicateCollections.ts
+++ b/src/utilities/checkDuplicateCollections.ts
@@ -1,9 +1,9 @@
import { DuplicateCollection } from '../errors';
-import { CollectionConfig } from '../collections/config/types';
+import { SanitizedCollectionConfig } from '../collections/config/types';
const getDuplicates = (arr: string[]) => arr.filter((item, index) => arr.indexOf(item) !== index);
-const checkDuplicateCollections = (collections: CollectionConfig[]): void => {
+const checkDuplicateCollections = (collections: SanitizedCollectionConfig[]): void => {
const duplicateSlugs = getDuplicates(collections.map((c) => c.slug));
if (duplicateSlugs.length > 0) {
throw new DuplicateCollection('slug', duplicateSlugs);
diff --git a/templates/blank/yarn.lock b/templates/blank/yarn.lock
index 53ff49f8325..3b3d832a438 100644
--- a/templates/blank/yarn.lock
+++ b/templates/blank/yarn.lock
@@ -3942,9 +3942,9 @@ graphql-type-json@^0.3.2:
integrity sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg==
graphql@^16.6.0:
- version "16.7.1"
- resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.7.1.tgz#11475b74a7bff2aefd4691df52a0eca0abd9b642"
- integrity sha512-DRYR9tf+UGU0KOsMcKAlXeFfX89UiiIZ0dRU3mR0yJfu6OjZqUcp68NnFLnqQU5RexygFoDy1EW+ccOYcPfmHg==
+ version "16.8.1"
+ resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07"
+ integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==
gzip-size@^6.0.0:
version "6.0.0"
@@ -6072,9 +6072,9 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
postcss@^8.2.15, postcss@^8.4.21, postcss@^8.4.24:
- version "8.4.27"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057"
- integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==
+ version "8.4.31"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
+ integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
dependencies:
nanoid "^3.3.6"
picocolors "^1.0.0"
diff --git a/templates/ecommerce/package.json b/templates/ecommerce/package.json
index a13469ab99a..37fe594e512 100644
--- a/templates/ecommerce/package.json
+++ b/templates/ecommerce/package.json
@@ -30,7 +30,7 @@
"cross-env": "^7.0.3",
"dotenv": "^8.2.0",
"express": "^4.17.1",
- "next": "^13.4.8",
+ "next": "^13.5.0",
"payload": "latest",
"payload-admin-bar": "^1.0.6",
"react": "^18.2.0",
diff --git a/templates/ecommerce/yarn.lock b/templates/ecommerce/yarn.lock
index 3d0969a10ad..a217a32a0b8 100644
--- a/templates/ecommerce/yarn.lock
+++ b/templates/ecommerce/yarn.lock
@@ -1318,10 +1318,10 @@
dependencies:
"@monaco-editor/loader" "^1.3.3"
-"@next/env@13.4.12":
- version "13.4.12"
- resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.12.tgz#0b88115ab817f178bf9dc0c5e7b367277595b58d"
- integrity sha512-RmHanbV21saP/6OEPBJ7yJMuys68cIf8OBBWd7+uj40LdpmswVAwe1uzeuFyUsd6SfeITWT3XnQfn6wULeKwDQ==
+"@next/env@13.5.0":
+ version "13.5.0"
+ resolved "https://registry.yarnpkg.com/@next/env/-/env-13.5.0.tgz#a61dee2f29b09985847eabcc4c8a815031267a36"
+ integrity sha512-mxhf/BskjPURT+qEjNP7wBvqre2q6OXEIbydF8BrH+duSSJQnB4/vzzuJDoahYwTXiUaXpouAnMWHZdG0HU62g==
"@next/eslint-plugin-next@^13.1.6":
version "13.4.12"
@@ -1330,50 +1330,50 @@
dependencies:
glob "7.1.7"
-"@next/swc-darwin-arm64@13.4.12":
- version "13.4.12"
- resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.12.tgz#326c830b111de8a1a51ac0cbc3bcb157c4c4f92c"
- integrity sha512-deUrbCXTMZ6ZhbOoloqecnUeNpUOupi8SE2tx4jPfNS9uyUR9zK4iXBvH65opVcA/9F5I/p8vDXSYbUlbmBjZg==
-
-"@next/swc-darwin-x64@13.4.12":
- version "13.4.12"
- resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.12.tgz#dd5c49fc092a8ffe4f30b7aa9bf6c5d2e40bbfa1"
- integrity sha512-WRvH7RxgRHlC1yb5oG0ZLx8F7uci9AivM5/HGGv9ZyG2Als8Ij64GC3d+mQ5sJhWjusyU6T6V1WKTUoTmOB0zQ==
-
-"@next/swc-linux-arm64-gnu@13.4.12":
- version "13.4.12"
- resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.12.tgz#816cbe9d26ce4670ea99d95b66041e483ed122d6"
- integrity sha512-YEKracAWuxp54tKiAvvq73PUs9lok57cc8meYRibTWe/VdPB2vLgkTVWFcw31YDuRXdEhdX0fWS6Q+ESBhnEig==
-
-"@next/swc-linux-arm64-musl@13.4.12":
- version "13.4.12"
- resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.12.tgz#670c8aee221628f65e5b299ee84db746e6c778b0"
- integrity sha512-LhJR7/RAjdHJ2Isl2pgc/JaoxNk0KtBgkVpiDJPVExVWA1c6gzY57+3zWuxuyWzTG+fhLZo2Y80pLXgIJv7g3g==
-
-"@next/swc-linux-x64-gnu@13.4.12":
- version "13.4.12"
- resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.12.tgz#54c64e689f007ae463698dddc1c6637491c99cb4"
- integrity sha512-1DWLL/B9nBNiQRng+1aqs3OaZcxC16Nf+mOnpcrZZSdyKHek3WQh6j/fkbukObgNGwmCoVevLUa/p3UFTTqgqg==
-
-"@next/swc-linux-x64-musl@13.4.12":
- version "13.4.12"
- resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.12.tgz#9cbddf4e542ef3d32284e0c36ce102facc015f8b"
- integrity sha512-kEAJmgYFhp0VL+eRWmUkVxLVunn7oL9Mdue/FS8yzRBVj7Z0AnIrHpTIeIUl1bbdQq1VaoOztnKicAjfkLTRCQ==
-
-"@next/swc-win32-arm64-msvc@13.4.12":
- version "13.4.12"
- resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.12.tgz#3467a4b25429ccf49fd416388c9d19c80a4f6465"
- integrity sha512-GMLuL/loR6yIIRTnPRY6UGbLL9MBdw2anxkOnANxvLvsml4F0HNIgvnU3Ej4BjbqMTNjD4hcPFdlEow4XHPdZA==
-
-"@next/swc-win32-ia32-msvc@13.4.12":
- version "13.4.12"
- resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.12.tgz#73494cd167191946833c680b28d6a42435d383a8"
- integrity sha512-PhgNqN2Vnkm7XaMdRmmX0ZSwZXQAtamBVSa9A/V1dfKQCV1rjIZeiy/dbBnVYGdj63ANfsOR/30XpxP71W0eww==
-
-"@next/swc-win32-x64-msvc@13.4.12":
- version "13.4.12"
- resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.12.tgz#4a497edc4e8c5ee3c3eb27cf0eb39dfadff70874"
- integrity sha512-Z+56e/Ljt0bUs+T+jPjhFyxYBcdY2RIq9ELFU+qAMQMteHo7ymbV7CKmlcX59RI9C4YzN8PgMgLyAoi916b5HA==
+"@next/swc-darwin-arm64@13.5.0":
+ version "13.5.0"
+ resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.0.tgz#45ea191e13593088572d0048d4ddfc1fcdb3c8ed"
+ integrity sha512-DavPD8oRjSoCRJana5DCAWdRZ4nbS7/pPw13DlnukFfMPJUk5hCAC3+NbqEyekS/X1IBFdZWSV2lJIdzTn4s6w==
+
+"@next/swc-darwin-x64@13.5.0":
+ version "13.5.0"
+ resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.0.tgz#582e8df7d563c057581bc118fff1cea79391d6e7"
+ integrity sha512-s5QSKKB0CTKFWp3CNMC5GH1YOipH1Jjr5P3w+RQTC4Aybo6xPqeWp/UyDW0fxmLRq0e1zgnOMgDQRdxAkoThrw==
+
+"@next/swc-linux-arm64-gnu@13.5.0":
+ version "13.5.0"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.0.tgz#7ee0a43b6635eca1e80a887304b7bfe31254a4a6"
+ integrity sha512-E0fCKA8F2vfgZWwcv4iq642No75EiACSNUBNGvc5lx/ylqAUdNwE/9+x2SHv+LPUXFhZ6hZLR0Qox/oKgZqFlg==
+
+"@next/swc-linux-arm64-musl@13.5.0":
+ version "13.5.0"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.0.tgz#99a1efd6b68a4d0dfdc24b81f14cd8b8251425a9"
+ integrity sha512-jG/blDDLndFRUcafCQO4TOI3VuoIZh3jQriZ7JaVCgAEZe0D1EUrxKdbBarZ74isutHZ6DpNGRDi/0OHFZpJAA==
+
+"@next/swc-linux-x64-gnu@13.5.0":
+ version "13.5.0"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.0.tgz#7c85acd45879a20d8fb102b3212e792924d02e93"
+ integrity sha512-6JWR7U41uNL6HGwNbGg3Oedt+FN4YuA126sHWKTq3ic5kkhEusIIdVo7+WcswVJl8nTMB1yT3gEPwygQbVYVUA==
+
+"@next/swc-linux-x64-musl@13.5.0":
+ version "13.5.0"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.0.tgz#23aad9ab7621f53bb947b727e659d85e74b0e31a"
+ integrity sha512-uY+wrYfD5QUossqznwidOpJYmmcBwojToZx55shihtbTl6afVYzOxsUbRXLdWmZAa36ckxXpqkvuFNS8icQuug==
+
+"@next/swc-win32-arm64-msvc@13.5.0":
+ version "13.5.0"
+ resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.0.tgz#5a45686335e5f54342faf9d9ed25f55a4107ce7f"
+ integrity sha512-lWZ5vJTULxTOdLcRmrllNgAdDRSDwk8oqJMyDxpqS691NG5uhle9ZwRj3g1F1/vHNkDa+B7PmWhQgG0nmlbKZg==
+
+"@next/swc-win32-ia32-msvc@13.5.0":
+ version "13.5.0"
+ resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.0.tgz#b9990965762aaa109bdeb7b49cbdc7e4af7f9014"
+ integrity sha512-jirQXnVCU9hi3cHzgd33d4qSBXn1/0gUT/KtXqy9Ux9OTcIcjJT3TcAzoLJLTdhRg7op3MZoSnuFeWl8kmGGNw==
+
+"@next/swc-win32-x64-msvc@13.5.0":
+ version "13.5.0"
+ resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.0.tgz#4385c5d9c0db39c2623aed566b3ec7fedaf6f190"
+ integrity sha512-Q8QYLyWcMMUp3DohI04VyJbLNCfFMNTxYNhujvJD2lowuqnqApUBP2DxI/jCZRMFWgKi76n5u8UboLVeYXn6jA==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
@@ -1993,10 +1993,10 @@
"@swc/core-win32-ia32-msvc" "1.3.71"
"@swc/core-win32-x64-msvc" "1.3.71"
-"@swc/helpers@0.5.1":
- version "0.5.1"
- resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.1.tgz#e9031491aa3f26bfcc974a67f48bd456c8a5357a"
- integrity sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==
+"@swc/helpers@0.5.2":
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.2.tgz#85ea0c76450b61ad7d10a37050289eded783c27d"
+ integrity sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==
dependencies:
tslib "^2.4.0"
@@ -4690,9 +4690,9 @@ graphql-type-json@^0.3.2:
integrity sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg==
graphql@^16.6.0:
- version "16.7.1"
- resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.7.1.tgz#11475b74a7bff2aefd4691df52a0eca0abd9b642"
- integrity sha512-DRYR9tf+UGU0KOsMcKAlXeFfX89UiiIZ0dRU3mR0yJfu6OjZqUcp68NnFLnqQU5RexygFoDy1EW+ccOYcPfmHg==
+ version "16.8.1"
+ resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07"
+ integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==
gzip-size@^6.0.0:
version "6.0.0"
@@ -5886,13 +5886,13 @@ next-tick@1, next-tick@^1.1.0:
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb"
integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==
-next@^13.4.8:
- version "13.4.12"
- resolved "https://registry.yarnpkg.com/next/-/next-13.4.12.tgz#809b21ea0aabbe88ced53252c88c4a5bd5af95df"
- integrity sha512-eHfnru9x6NRmTMcjQp6Nz0J4XH9OubmzOa7CkWL+AUrUxpibub3vWwttjduu9No16dug1kq04hiUUpo7J3m3Xw==
+next@^13.5.0:
+ version "13.5.0"
+ resolved "https://registry.yarnpkg.com/next/-/next-13.5.0.tgz#3a3ce5b8c89c4fff9c6f0b2452bcb03f63d8c84c"
+ integrity sha512-mhguN5JPZXhhrD/nNcezXgKoxN8GT8xZvvGhUQV2ETiaNm+KHRWT1rCbrF5FlbG2XCcLRKOmOe3D5YQgXmJrDQ==
dependencies:
- "@next/env" "13.4.12"
- "@swc/helpers" "0.5.1"
+ "@next/env" "13.5.0"
+ "@swc/helpers" "0.5.2"
busboy "1.6.0"
caniuse-lite "^1.0.30001406"
postcss "8.4.14"
@@ -5900,15 +5900,15 @@ next@^13.4.8:
watchpack "2.4.0"
zod "3.21.4"
optionalDependencies:
- "@next/swc-darwin-arm64" "13.4.12"
- "@next/swc-darwin-x64" "13.4.12"
- "@next/swc-linux-arm64-gnu" "13.4.12"
- "@next/swc-linux-arm64-musl" "13.4.12"
- "@next/swc-linux-x64-gnu" "13.4.12"
- "@next/swc-linux-x64-musl" "13.4.12"
- "@next/swc-win32-arm64-msvc" "13.4.12"
- "@next/swc-win32-ia32-msvc" "13.4.12"
- "@next/swc-win32-x64-msvc" "13.4.12"
+ "@next/swc-darwin-arm64" "13.5.0"
+ "@next/swc-darwin-x64" "13.5.0"
+ "@next/swc-linux-arm64-gnu" "13.5.0"
+ "@next/swc-linux-arm64-musl" "13.5.0"
+ "@next/swc-linux-x64-gnu" "13.5.0"
+ "@next/swc-linux-x64-musl" "13.5.0"
+ "@next/swc-win32-arm64-msvc" "13.5.0"
+ "@next/swc-win32-ia32-msvc" "13.5.0"
+ "@next/swc-win32-x64-msvc" "13.5.0"
no-case@^3.0.4:
version "3.0.4"
diff --git a/templates/website/src/server.ts b/templates/website/src/server.ts
index 0afd8b93d19..a67b0b6ac90 100644
--- a/templates/website/src/server.ts
+++ b/templates/website/src/server.ts
@@ -29,7 +29,7 @@ const start = async (): Promise => {
payload.logger.info('Done.')
}
- app.listen(process.env.PORT)
+ app.listen(process.env.PORT || 3000)
}
start()
diff --git a/templates/website/yarn.lock b/templates/website/yarn.lock
index 9d2ad88a6c1..d0291bc0ba1 100644
--- a/templates/website/yarn.lock
+++ b/templates/website/yarn.lock
@@ -4550,9 +4550,9 @@ graphql-type-json@^0.3.2:
integrity sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg==
graphql@^16.6.0:
- version "16.7.1"
- resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.7.1.tgz#11475b74a7bff2aefd4691df52a0eca0abd9b642"
- integrity sha512-DRYR9tf+UGU0KOsMcKAlXeFfX89UiiIZ0dRU3mR0yJfu6OjZqUcp68NnFLnqQU5RexygFoDy1EW+ccOYcPfmHg==
+ version "16.8.1"
+ resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07"
+ integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==
gzip-size@^6.0.0:
version "6.0.0"
@@ -6817,9 +6817,9 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
postcss@^8.2.15, postcss@^8.4.21, postcss@^8.4.24:
- version "8.4.27"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057"
- integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==
+ version "8.4.31"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
+ integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
dependencies:
nanoid "^3.3.6"
picocolors "^1.0.0"
diff --git a/test/access-control/e2e.spec.ts b/test/access-control/e2e.spec.ts
index 7017cc17043..38dd6bf2a0a 100644
--- a/test/access-control/e2e.spec.ts
+++ b/test/access-control/e2e.spec.ts
@@ -206,7 +206,7 @@ describe('access control', () => {
const duplicateAction = page.locator('.collection-edit__collection-actions >> li').last();
await expect(duplicateAction).toContainText('Duplicate');
- await page.locator('#field-approvedForRemoval + button').click();
+ await page.locator('#field-approvedForRemoval').check();
await page.locator('#action-save').click();
const deleteAction = page.locator('.collection-edit__collection-actions >> li').last();
diff --git a/test/admin/e2e.spec.ts b/test/admin/e2e.spec.ts
index fb6ac90b28a..f5c9569cc48 100644
--- a/test/admin/e2e.spec.ts
+++ b/test/admin/e2e.spec.ts
@@ -198,7 +198,7 @@ describe('admin', () => {
await page.goto(url.list);
- await page.locator('.select-all__input').click();
+ await page.locator('input#select-all').check();
await page.locator('.delete-documents__toggle').click();
@@ -216,7 +216,7 @@ describe('admin', () => {
const bulkTitle = 'Bulk update title';
await page.goto(url.list);
- await page.locator('.select-all__input').click();
+ await page.locator('input#select-all').check();
await page.locator('.edit-many__toggle').click();
await page.locator('.field-select .rs__control').click();
const options = page.locator('.rs__option');
@@ -394,6 +394,25 @@ describe('admin', () => {
await page.locator('.condition__actions-remove').click();
await expect(page.locator(tableRowLocator)).toHaveCount(2);
});
+
+ test('should accept where query from valid URL where parameter', async () => {
+ await createPost({ title: 'post1' });
+ await createPost({ title: 'post2' });
+ await page.goto(`${url.list}?limit=10&page=1&where[or][0][and][0][title][equals]=post1`);
+
+ await expect(page.locator('.react-select--single-value').first()).toContainText('Title en');
+ await expect(page.locator(tableRowLocator)).toHaveCount(1);
+ });
+
+ test('should accept transformed where query from invalid URL where parameter', async () => {
+ await createPost({ title: 'post1' });
+ await createPost({ title: 'post2' });
+ // [title][equals]=post1 should be getting transformed into a valid where[or][0][and][0][title][equals]=post1
+ await page.goto(`${url.list}?limit=10&page=1&where[title][equals]=post1`);
+
+ await expect(page.locator('.react-select--single-value').first()).toContainText('Title en');
+ await expect(page.locator(tableRowLocator)).toHaveCount(1);
+ });
});
describe('table columns', () => {
@@ -523,18 +542,18 @@ describe('admin', () => {
});
test('should select multiple rows', async () => {
- const selectAll = page.locator('.select-all');
- await page.locator('.row-1 .select-row button').click();
+ const selectAll = page.locator('.custom-checkbox:has(#select-all)');
+ await page.locator('.row-1 .cell-_select input').check();
- const indeterminateSelectAll = selectAll.locator('.icon--line');
+ const indeterminateSelectAll = selectAll.locator('.custom-checkbox__icon.partial');
expect(indeterminateSelectAll).toBeDefined();
- await selectAll.locator('button').click();
- const emptySelectAll = selectAll.locator('.icon');
+ await selectAll.locator('input').click();
+ const emptySelectAll = selectAll.locator('.custom-checkbox__icon:not(.check):not(.partial)');
await expect(emptySelectAll).toHaveCount(0);
- await selectAll.locator('button').click();
- const checkSelectAll = selectAll.locator('.icon .icon--check');
+ await selectAll.locator('input').click();
+ const checkSelectAll = selectAll.locator('.custom-checkbox__icon.check');
expect(checkSelectAll).toBeDefined();
});
@@ -542,16 +561,16 @@ describe('admin', () => {
// delete should not appear without selection
await expect(page.locator('#confirm-delete')).toHaveCount(0);
// select one row
- await page.locator('.row-1 .select-row button').click();
+ await page.locator('.row-1 .cell-_select input').check();
// delete button should be present
await expect(page.locator('#confirm-delete')).toHaveCount(1);
- await page.locator('.row-2 .select-row button').click();
+ await page.locator('.row-2 .cell-_select input').check();
await page.locator('.delete-documents__toggle').click();
await page.locator('#confirm-delete').click();
- await expect(page.locator('.select-row')).toHaveCount(1);
+ await expect(await page.locator('.cell-_select')).toHaveCount(1);
});
});
diff --git a/test/fields/collections/Text/index.ts b/test/fields/collections/Text/index.ts
index 56a7220ebd3..fd92475e387 100644
--- a/test/fields/collections/Text/index.ts
+++ b/test/fields/collections/Text/index.ts
@@ -57,6 +57,26 @@ const TextFields: CollectionConfig = {
type: 'text',
maxLength: 50000,
},
+ {
+ name: 'fieldWithDefaultValue',
+ type: 'text',
+ defaultValue: async () => {
+ const defaultValue = new Promise((resolve) => setTimeout(() => resolve('some-value'), 1000));
+
+ return defaultValue;
+ },
+ },
+ {
+ name: 'dependentOnFieldWithDefaultValue',
+ type: 'text',
+ hooks: {
+ beforeChange: [
+ ({ data }) => {
+ return data?.fieldWithDefaultValue || '';
+ },
+ ],
+ },
+ },
],
};
diff --git a/test/fields/int.spec.ts b/test/fields/int.spec.ts
index 5cc287230d1..2266f560f81 100644
--- a/test/fields/int.spec.ts
+++ b/test/fields/int.spec.ts
@@ -47,6 +47,15 @@ describe('Fields', () => {
expect(doc.defaultFunction).toEqual(defaultText);
expect(doc.defaultAsync).toEqual(defaultText);
});
+
+ it('should populate default values in beforeValidate hook', async () => {
+ const { fieldWithDefaultValue, dependentOnFieldWithDefaultValue } = await payload.create({
+ collection: 'text-fields',
+ data: { text },
+ });
+
+ await expect(fieldWithDefaultValue).toEqual(dependentOnFieldWithDefaultValue);
+ });
});
describe('timestamps', () => {
diff --git a/test/hooks/collections/AfterOperation/index.ts b/test/hooks/collections/AfterOperation/index.ts
new file mode 100644
index 00000000000..cad742b32ca
--- /dev/null
+++ b/test/hooks/collections/AfterOperation/index.ts
@@ -0,0 +1,71 @@
+import { AfterOperationHook, CollectionConfig } from '../../../../src/collections/config/types';
+import { AfterOperation } from '../../payload-types';
+
+export const afterOperationSlug = 'afterOperation';
+
+const AfterOperation: CollectionConfig = {
+ slug: afterOperationSlug,
+ hooks: {
+ // beforeRead: [(operation) => operation.doc],
+ afterOperation: [
+ async ({ result, operation }) => {
+ if (operation === 'create') {
+ if ('docs' in result) {
+ return {
+ ...result,
+ docs: result.docs?.map((doc) => ({
+ ...doc,
+ title: 'Title created',
+ })),
+ };
+ }
+
+ return { ...result, title: 'Title created' };
+ }
+
+ if (operation === 'find') {
+ // only modify the first doc for `find` operations
+ // this is so we can test against the other operations
+ return {
+ ...result,
+ docs: result.docs?.map((doc, index) => (index === 0 ? {
+ ...doc,
+ title: 'Title read',
+ } : doc)),
+ };
+ }
+
+ if (operation === 'findByID') {
+ return { ...result, title: 'Title read' };
+ }
+
+ if (operation === 'update') {
+ if ('docs' in result) {
+ return {
+ ...result,
+ docs: result.docs?.map((doc) => ({
+ ...doc,
+ title: 'Title updated',
+ })),
+ };
+ }
+ }
+
+ if (operation === 'updateByID') {
+ return { ...result, title: 'Title updated' };
+ }
+
+ return result;
+ },
+ ] as AfterOperationHook[],
+ },
+ fields: [
+ {
+ name: 'title',
+ type: 'text',
+ required: true,
+ },
+ ],
+};
+
+export default AfterOperation;
diff --git a/test/hooks/config.ts b/test/hooks/config.ts
index d36e9ce3640..cca0e4b3b45 100644
--- a/test/hooks/config.ts
+++ b/test/hooks/config.ts
@@ -4,11 +4,13 @@ import Hooks, { hooksSlug } from './collections/Hook';
import NestedAfterReadHooks from './collections/NestedAfterReadHooks';
import ChainingHooks from './collections/ChainingHooks';
import Relations from './collections/Relations';
+import AfterOperation from './collections/AfterOperation';
import Users, { seedHooksUsers } from './collections/Users';
import ContextHooks from './collections/ContextHooks';
export default buildConfigWithDefaults({
collections: [
+ AfterOperation,
ContextHooks,
TransformHooks,
Hooks,
diff --git a/test/hooks/int.spec.ts b/test/hooks/int.spec.ts
index d65909b9f2e..d0fbf984486 100644
--- a/test/hooks/int.spec.ts
+++ b/test/hooks/int.spec.ts
@@ -1,6 +1,6 @@
import mongoose from 'mongoose';
import { initPayloadTest } from '../helpers/configHelpers';
-import config from './config';
+import configPromise from './config';
import payload from '../../src';
import { RESTClient } from '../helpers/rest';
import { transformSlug } from './collections/Transform';
@@ -8,10 +8,10 @@ import { hooksSlug } from './collections/Hook';
import { chainingHooksSlug } from './collections/ChainingHooks';
import { generatedAfterReadText, nestedAfterReadHooksSlug } from './collections/NestedAfterReadHooks';
import { relationsSlug } from './collections/Relations';
-import type { NestedAfterReadHook } from './payload-types';
import { hooksUsersSlug } from './collections/Users';
import { devUser, regularUser } from '../credentials';
import { AuthenticationError } from '../../src/errors';
+import { afterOperationSlug } from './collections/AfterOperation';
import { contextHooksSlug } from './collections/ContextHooks';
let client: RESTClient;
@@ -20,6 +20,7 @@ let apiUrl;
describe('Hooks', () => {
beforeAll(async () => {
const { serverURL } = await initPayloadTest({ __dirname, init: { local: false } });
+ const config = await configPromise;
client = new RESTClient(config, { serverURL, defaultSlug: transformSlug });
apiUrl = `${serverURL}/api`;
});
@@ -74,7 +75,7 @@ describe('Hooks', () => {
});
it('should save data generated with afterRead hooks in nested field structures', async () => {
- const document = await payload.create({
+ const document = await payload.create({
collection: nestedAfterReadHooksSlug,
data: {
text: 'ok',
@@ -155,6 +156,62 @@ describe('Hooks', () => {
expect(retrievedDocs[0].text).toEqual('ok!!');
});
+ it('should execute collection afterOperation hook', async () => {
+ const [doc1, doc2] = await Promise.all([
+ await payload.create({
+ collection: afterOperationSlug,
+ data: {
+ title: 'Title',
+ },
+ }),
+ await payload.create({
+ collection: afterOperationSlug,
+ data: {
+ title: 'Title',
+ },
+ }),
+ ]);
+
+ expect(doc1.title === 'Title created').toBeTruthy();
+ expect(doc2.title === 'Title created').toBeTruthy();
+
+ const findResult = await payload.find({
+ collection: afterOperationSlug,
+ });
+
+ expect(findResult.docs).toHaveLength(2);
+ expect(findResult.docs[0].title === 'Title read').toBeTruthy();
+ expect(findResult.docs[1].title === 'Title').toBeTruthy();
+
+ const [updatedDoc1, updatedDoc2] = await Promise.all([
+ await payload.update({
+ collection: afterOperationSlug,
+ id: doc1.id,
+ data: {
+ title: 'Title',
+ },
+ }),
+ await payload.update({
+ collection: afterOperationSlug,
+ id: doc2.id,
+ data: {
+ title: 'Title',
+ },
+ }),
+ ]);
+
+ expect(updatedDoc1.title === 'Title updated').toBeTruthy();
+ expect(updatedDoc2.title === 'Title updated').toBeTruthy();
+
+ const findResult2 = await payload.find({
+ collection: afterOperationSlug,
+ });
+
+ expect(findResult2.docs).toHaveLength(2);
+ expect(findResult2.docs[0].title === 'Title read').toBeTruthy();
+ expect(findResult2.docs[1].title === 'Title').toBeTruthy();
+ });
+
it('should pass context from beforeChange to afterChange', async () => {
const document = await payload.create({
collection: contextHooksSlug,
diff --git a/test/hooks/payload-types.ts b/test/hooks/payload-types.ts
index f5582c89f39..4d9a73c4877 100644
--- a/test/hooks/payload-types.ts
+++ b/test/hooks/payload-types.ts
@@ -5,11 +5,24 @@
* and re-run `payload generate:types` to regenerate this file.
*/
-export interface Config {}
-/**
- * This interface was referenced by `Config`'s JSON-Schema
- * via the `definition` "transforms".
- */
+export interface Config {
+ collections: {
+ afterOperation: AfterOperation;
+ transforms: Transform;
+ hooks: Hook;
+ 'nested-after-read-hooks': NestedAfterReadHook;
+ 'chaining-hooks': ChainingHook;
+ relations: Relation;
+ 'hooks-users': HooksUser;
+ };
+ globals: {};
+}
+export interface AfterOperation {
+ id: string;
+ title: string;
+ updatedAt: string;
+ createdAt: string;
+}
export interface Transform {
id: string;
/**
@@ -22,13 +35,9 @@ export interface Transform {
* @maxItems 2
*/
localizedTransform?: [number, number];
- createdAt: string;
updatedAt: string;
+ createdAt: string;
}
-/**
- * This interface was referenced by `Config`'s JSON-Schema
- * via the `definition` "hooks".
- */
export interface Hook {
id: string;
fieldBeforeValidate?: boolean;
@@ -40,53 +49,48 @@ export interface Hook {
collectionAfterChange?: boolean;
collectionBeforeRead?: boolean;
collectionAfterRead?: boolean;
- createdAt: string;
updatedAt: string;
+ createdAt: string;
}
-/**
- * This interface was referenced by `Config`'s JSON-Schema
- * via the `definition` "nested-after-read-hooks".
- */
export interface NestedAfterReadHook {
id: string;
text?: string;
- group: {
- array: {
+ group?: {
+ array?: {
input?: string;
afterRead?: string;
shouldPopulate?: string | Relation;
id?: string;
}[];
- subGroup: {
+ subGroup?: {
afterRead?: string;
shouldPopulate?: string | Relation;
};
};
- createdAt: string;
updatedAt: string;
+ createdAt: string;
}
-/**
- * This interface was referenced by `Config`'s JSON-Schema
- * via the `definition` "relations".
- */
export interface Relation {
id: string;
title: string;
+ updatedAt: string;
createdAt: string;
+}
+export interface ChainingHook {
+ id: string;
+ text?: string;
updatedAt: string;
+ createdAt: string;
}
-/**
- * This interface was referenced by `Config`'s JSON-Schema
- * via the `definition` "hooks-users".
- */
export interface HooksUser {
id: string;
roles: ('admin' | 'user')[];
+ updatedAt: string;
+ createdAt: string;
email?: string;
resetPasswordToken?: string;
resetPasswordExpiration?: string;
loginAttempts?: number;
lockUntil?: string;
- createdAt: string;
- updatedAt: string;
+ password?: string;
}
diff --git a/test/refresh-permissions/e2e.spec.ts b/test/refresh-permissions/e2e.spec.ts
index aa52f99c65a..92dd2da8f56 100644
--- a/test/refresh-permissions/e2e.spec.ts
+++ b/test/refresh-permissions/e2e.spec.ts
@@ -24,7 +24,7 @@ describe('refresh-permissions', () => {
await expect(page.locator('#nav-global-test')).toBeHidden();
// Allow access to test global.
- await page.locator('.custom-checkbox:has(#field-test) button').click();
+ await page.locator('.custom-checkbox:has(#field-test) input').check();
await page.locator('#action-save').click();
// Now test collection should appear in the menu.
diff --git a/test/relationships/config.ts b/test/relationships/config.ts
index 231d3421183..556516ffd72 100644
--- a/test/relationships/config.ts
+++ b/test/relationships/config.ts
@@ -190,6 +190,12 @@ export default buildConfigWithDefaults({
name: 'name',
type: 'text',
},
+ {
+ name: 'movies',
+ type: 'relationship',
+ relationTo: 'movies',
+ hasMany: true,
+ },
],
},
],
diff --git a/test/relationships/int.spec.ts b/test/relationships/int.spec.ts
index 20302a29565..852daeb366f 100644
--- a/test/relationships/int.spec.ts
+++ b/test/relationships/int.spec.ts
@@ -1,5 +1,5 @@
-import mongoose from 'mongoose';
import { randomBytes } from 'crypto';
+import mongoose from 'mongoose';
import { initPayloadTest } from '../helpers/configHelpers';
import config, { customIdSlug, chainedRelSlug, defaultAccessRelSlug, slug, relationSlug, customIdNumberSlug } from './config';
import payload from '../../src';
@@ -345,6 +345,64 @@ describe('Relationships', () => {
expect(query.docs).toHaveLength(1);
});
});
+ describe('Multiple Docs', () => {
+ const movieList = [
+ 'Pulp Fiction',
+ 'Reservoir Dogs',
+ 'Once Upon a Time in Hollywood',
+ 'Shrek',
+ 'Shrek 2',
+ 'Shrek 3',
+ 'Scream',
+ 'The Matrix',
+ 'The Matrix Reloaded',
+ 'The Matrix Revolutions',
+ 'The Matrix Resurrections',
+ 'The Haunting',
+ 'The Haunting of Hill House',
+ 'The Haunting of Bly Manor',
+ 'Insidious',
+ ];
+
+ beforeAll(async () => {
+ await Promise.all(movieList.map((movie) => {
+ return payload.create({
+ collection: 'movies',
+ data: {
+ name: movie,
+ },
+ });
+ }));
+ });
+
+ it('should return more than 10 docs in relationship', async () => {
+ const allMovies = await payload.find({
+ collection: 'movies',
+ limit: 20,
+ });
+
+ const movieIDs = allMovies.docs.map((doc) => doc.id);
+
+ await payload.create({
+ collection: 'directors',
+ data: {
+ name: 'Quentin Tarantino',
+ movies: movieIDs,
+ },
+ });
+
+ const director = await payload.find({
+ collection: 'directors',
+ where: {
+ name: {
+ equals: 'Quentin Tarantino',
+ },
+ },
+ });
+
+ expect(director.docs[0].movies.length).toBeGreaterThan(10);
+ });
+ });
});
});
diff --git a/test/relationships/payload-types.ts b/test/relationships/payload-types.ts
index de4c1310a60..3ba0925a93b 100644
--- a/test/relationships/payload-types.ts
+++ b/test/relationships/payload-types.ts
@@ -85,6 +85,7 @@ export interface Movie {
export interface Director {
id: string;
name?: string;
+ movies?: Array;
updatedAt: string;
createdAt: string;
}
diff --git a/test/versions/e2e.spec.ts b/test/versions/e2e.spec.ts
index 787fa065f9d..58b8a4e4d3a 100644
--- a/test/versions/e2e.spec.ts
+++ b/test/versions/e2e.spec.ts
@@ -54,7 +54,7 @@ describe('versions', () => {
test('should bulk publish', async () => {
await page.goto(url.list);
- await page.locator('.select-all__input').click();
+ await page.locator('.custom-checkbox:has(#select-all) input').check();
await page.locator('.publish-many__toggle').click();
@@ -67,7 +67,7 @@ describe('versions', () => {
test('should bulk unpublish', async () => {
await page.goto(url.list);
- await page.locator('.select-all__input').click();
+ await page.locator('.custom-checkbox:has(#select-all) input').check();
await page.locator('.unpublish-many__toggle').click();
@@ -80,7 +80,7 @@ describe('versions', () => {
test('should publish while editing many', async () => {
const description = 'published document';
await page.goto(url.list);
- await page.locator('.select-all__input').click();
+ await page.locator('.custom-checkbox:has(#select-all) input').check();
await page.locator('.edit-many__toggle').click();
await page.locator('.field-select .rs__control').click();
const options = page.locator('.rs__option');
@@ -97,7 +97,7 @@ describe('versions', () => {
test('should save as draft while editing many', async () => {
const description = 'draft document';
await page.goto(url.list);
- await page.locator('.select-all__input').click();
+ await page.locator('.custom-checkbox:has(#select-all) input').check();
await page.locator('.edit-many__toggle').click();
await page.locator('.field-select .rs__control').click();
const options = page.locator('.rs__option');
diff --git a/types.d.ts b/types.d.ts
index 70adee2f2f9..12c2da5cbf1 100644
--- a/types.d.ts
+++ b/types.d.ts
@@ -8,6 +8,7 @@ export {
export {
CollectionConfig,
SanitizedCollectionConfig,
+ AfterOperationHook as CollectionAfterOperationHook,
BeforeOperationHook as CollectionBeforeOperationHook,
BeforeValidateHook as CollectionBeforeValidateHook,
BeforeChangeHook as CollectionBeforeChangeHook,
diff --git a/yarn.lock b/yarn.lock
index 8217e868f82..283bdc40270 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8,9 +8,9 @@
integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==
"@adobe/css-tools@^4.0.1":
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.0.tgz#1991d273fb29edbd2f63060f5bdaf0af26aa64e3"
- integrity sha512-+RNNcQvw2V1bmnBTPAtOLfW/9mhH2vC67+rUSi5T8EtEWt6lEnGNY2GuhZ1/YwbgikT1TkhvidCDmN5Q5YCo/w==
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.1.tgz#abfccb8ca78075a2b6187345c26243c1a0842f28"
+ integrity sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==
"@ampproject/remapping@^2.2.0":
version "2.2.1"
@@ -470,6 +470,14 @@
"@babel/highlight" "^7.22.10"
chalk "^2.4.2"
+"@babel/code-frame@^7.22.13":
+ version "7.22.13"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e"
+ integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==
+ dependencies:
+ "@babel/highlight" "^7.22.13"
+ chalk "^2.4.2"
+
"@babel/compat-data@^7.22.9":
version "7.22.9"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730"
@@ -506,6 +514,16 @@
"@jridgewell/trace-mapping" "^0.3.17"
jsesc "^2.5.1"
+"@babel/generator@^7.23.0":
+ version "7.23.0"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420"
+ integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==
+ dependencies:
+ "@babel/types" "^7.23.0"
+ "@jridgewell/gen-mapping" "^0.3.2"
+ "@jridgewell/trace-mapping" "^0.3.17"
+ jsesc "^2.5.1"
+
"@babel/helper-compilation-targets@^7.22.10":
version "7.22.10"
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz#01d648bbc25dd88f513d862ee0df27b7d4e67024"
@@ -517,18 +535,23 @@
lru-cache "^5.1.1"
semver "^6.3.1"
+"@babel/helper-environment-visitor@^7.22.20":
+ version "7.22.20"
+ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
+ integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
+
"@babel/helper-environment-visitor@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98"
integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==
-"@babel/helper-function-name@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be"
- integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==
+"@babel/helper-function-name@^7.23.0":
+ version "7.23.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
+ integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
dependencies:
- "@babel/template" "^7.22.5"
- "@babel/types" "^7.22.5"
+ "@babel/template" "^7.22.15"
+ "@babel/types" "^7.23.0"
"@babel/helper-hoist-variables@^7.22.5":
version "7.22.5"
@@ -579,6 +602,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
+"@babel/helper-validator-identifier@^7.22.20":
+ version "7.22.20"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
+ integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
+
"@babel/helper-validator-identifier@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193"
@@ -607,11 +635,25 @@
chalk "^2.4.2"
js-tokens "^4.0.0"
+"@babel/highlight@^7.22.13":
+ version "7.22.20"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54"
+ integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.22.20"
+ chalk "^2.4.2"
+ js-tokens "^4.0.0"
+
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.10", "@babel/parser@^7.22.5":
version "7.22.10"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.10.tgz#e37634f9a12a1716136c44624ef54283cabd3f55"
integrity sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==
+"@babel/parser@^7.22.15", "@babel/parser@^7.23.0":
+ version "7.23.0"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
+ integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
+
"@babel/plugin-syntax-async-generators@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
@@ -717,6 +759,15 @@
dependencies:
regenerator-runtime "^0.14.0"
+"@babel/template@^7.22.15":
+ version "7.22.15"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
+ integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
+ dependencies:
+ "@babel/code-frame" "^7.22.13"
+ "@babel/parser" "^7.22.15"
+ "@babel/types" "^7.22.15"
+
"@babel/template@^7.22.5", "@babel/template@^7.3.3":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec"
@@ -727,18 +778,18 @@
"@babel/types" "^7.22.5"
"@babel/traverse@^7.22.10":
- version "7.22.10"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.10.tgz#20252acb240e746d27c2e82b4484f199cf8141aa"
- integrity sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==
- dependencies:
- "@babel/code-frame" "^7.22.10"
- "@babel/generator" "^7.22.10"
- "@babel/helper-environment-visitor" "^7.22.5"
- "@babel/helper-function-name" "^7.22.5"
+ version "7.23.2"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
+ integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==
+ dependencies:
+ "@babel/code-frame" "^7.22.13"
+ "@babel/generator" "^7.23.0"
+ "@babel/helper-environment-visitor" "^7.22.20"
+ "@babel/helper-function-name" "^7.23.0"
"@babel/helper-hoist-variables" "^7.22.5"
"@babel/helper-split-export-declaration" "^7.22.6"
- "@babel/parser" "^7.22.10"
- "@babel/types" "^7.22.10"
+ "@babel/parser" "^7.23.0"
+ "@babel/types" "^7.23.0"
debug "^4.1.0"
globals "^11.1.0"
@@ -751,6 +802,15 @@
"@babel/helper-validator-identifier" "^7.22.5"
to-fast-properties "^2.0.0"
+"@babel/types@^7.22.15", "@babel/types@^7.23.0":
+ version "7.23.0"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb"
+ integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==
+ dependencies:
+ "@babel/helper-string-parser" "^7.22.5"
+ "@babel/helper-validator-identifier" "^7.22.20"
+ to-fast-properties "^2.0.0"
+
"@bcherny/json-schema-ref-parser@9.0.9":
version "9.0.9"
resolved "https://registry.yarnpkg.com/@bcherny/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#09899d405bc708c0acac0066ae8db5b94d465ca4"
@@ -5461,13 +5521,14 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
-es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@^0.10.61, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46:
- version "0.10.62"
- resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5"
- integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==
+es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@^0.10.61, es5-ext@^0.10.62, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46:
+ version "0.10.64"
+ resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.64.tgz#12e4ffb48f1ba2ea777f1fcdd1918ef73ea21714"
+ integrity sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==
dependencies:
es6-iterator "^2.0.3"
es6-symbol "^3.1.3"
+ esniff "^2.0.1"
next-tick "^1.1.0"
es6-iterator@^2.0.3:
@@ -5748,6 +5809,16 @@ eslint@^8.39.0:
strip-ansi "^6.0.1"
text-table "^0.2.0"
+esniff@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308"
+ integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==
+ dependencies:
+ d "^1.0.1"
+ es5-ext "^0.10.62"
+ event-emitter "^0.3.5"
+ type "^2.7.2"
+
espree@^9.6.0, espree@^9.6.1:
version "9.6.1"
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f"
@@ -6590,9 +6661,9 @@ graphql-type-json@^0.3.2:
integrity sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg==
graphql@^16.6.0:
- version "16.7.1"
- resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.7.1.tgz#11475b74a7bff2aefd4691df52a0eca0abd9b642"
- integrity sha512-DRYR9tf+UGU0KOsMcKAlXeFfX89UiiIZ0dRU3mR0yJfu6OjZqUcp68NnFLnqQU5RexygFoDy1EW+ccOYcPfmHg==
+ version "16.8.1"
+ resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07"
+ integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==
gzip-size@^6.0.0:
version "6.0.0"
@@ -9983,9 +10054,9 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
postcss@^8.2.15, postcss@^8.4.21, postcss@^8.4.24:
- version "8.4.27"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057"
- integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==
+ version "8.4.31"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
+ integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
dependencies:
nanoid "^3.3.6"
picocolors "^1.0.0"