feat: bulk-operations (#2346)
Co-authored-by: PatrikKozak <patrik@trbl.design>
This commit is contained in:
@@ -189,12 +189,10 @@ const Routes = () => {
|
||||
render={(routeProps) => {
|
||||
if (permissions?.collections?.[collection.slug]?.read?.permission) {
|
||||
return (
|
||||
<TableColumnsProvider collection={collection}>
|
||||
<List
|
||||
{...routeProps}
|
||||
collection={collection}
|
||||
/>
|
||||
</TableColumnsProvider>
|
||||
<List
|
||||
{...routeProps}
|
||||
collection={collection}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useId } from 'react';
|
||||
import React, { useId, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Pill from '../Pill';
|
||||
import Plus from '../../icons/Plus';
|
||||
@@ -49,6 +49,8 @@ const ColumnSelector: React.FC<Props> = (props) => {
|
||||
name,
|
||||
} = col;
|
||||
|
||||
if (col.accessor === '_select') return null;
|
||||
|
||||
return (
|
||||
<Pill
|
||||
draggable
|
||||
|
||||
17
src/admin/components/elements/DeleteMany/index.scss
Normal file
17
src/admin/components/elements/DeleteMany/index.scss
Normal file
@@ -0,0 +1,17 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.delete-documents {
|
||||
@include blur-bg;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
|
||||
&__template {
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-right: $baseline;
|
||||
}
|
||||
}
|
||||
120
src/admin/components/elements/DeleteMany/index.tsx
Normal file
120
src/admin/components/elements/DeleteMany/index.tsx
Normal file
@@ -0,0 +1,120 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { Modal, useModal } from '@faceless-ui/modal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useConfig } from '../../utilities/Config';
|
||||
import Button from '../Button';
|
||||
import MinimalTemplate from '../../templates/Minimal';
|
||||
import { requests } from '../../../api';
|
||||
import { Props } from './types';
|
||||
import { SelectAllStatus, useSelection } from '../../views/collections/List/SelectionProvider';
|
||||
import { getTranslation } from '../../../../utilities/getTranslation';
|
||||
import Pill from '../Pill';
|
||||
import { useAuth } from '../../utilities/Auth';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'delete-documents';
|
||||
|
||||
const DeleteMany: React.FC<Props> = (props) => {
|
||||
const {
|
||||
resetParams,
|
||||
collection: {
|
||||
slug,
|
||||
labels: {
|
||||
plural,
|
||||
},
|
||||
} = {},
|
||||
} = props;
|
||||
|
||||
const { permissions } = useAuth();
|
||||
const { serverURL, routes: { api } } = useConfig();
|
||||
const { toggleModal } = useModal();
|
||||
const { selectAll, count, getQueryParams, toggleAll } = useSelection();
|
||||
const { t, i18n } = useTranslation('general');
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
|
||||
const collectionPermissions = permissions?.collections?.[slug];
|
||||
const hasDeletePermission = collectionPermissions?.delete?.permission;
|
||||
|
||||
const modalSlug = `delete-${slug}`;
|
||||
|
||||
const addDefaultError = useCallback(() => {
|
||||
toast.error(t('error:unknown'));
|
||||
}, [t]);
|
||||
|
||||
const handleDelete = useCallback(() => {
|
||||
setDeleting(true);
|
||||
requests.delete(`${serverURL}${api}/${slug}${getQueryParams()}`, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept-Language': i18n.language,
|
||||
},
|
||||
}).then(async (res) => {
|
||||
try {
|
||||
const json = await res.json();
|
||||
toggleModal(modalSlug);
|
||||
if (res.status < 400) {
|
||||
toast.success(json.message || t('deletedSuccessfully'), { autoClose: 3000 });
|
||||
toggleAll();
|
||||
resetParams({ page: selectAll ? 1 : undefined });
|
||||
return null;
|
||||
}
|
||||
|
||||
if (json.errors) {
|
||||
toast.error(json.message);
|
||||
} else {
|
||||
addDefaultError();
|
||||
}
|
||||
return false;
|
||||
} catch (e) {
|
||||
return addDefaultError();
|
||||
}
|
||||
});
|
||||
}, [addDefaultError, api, getQueryParams, i18n.language, modalSlug, resetParams, selectAll, serverURL, slug, t, toggleAll, toggleModal]);
|
||||
|
||||
if (selectAll === SelectAllStatus.None || !hasDeletePermission) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Pill
|
||||
className={`${baseClass}__toggle`}
|
||||
onClick={() => {
|
||||
setDeleting(false);
|
||||
toggleModal(modalSlug);
|
||||
}}
|
||||
>
|
||||
{t('delete')}
|
||||
</Pill>
|
||||
<Modal
|
||||
slug={modalSlug}
|
||||
className={baseClass}
|
||||
>
|
||||
<MinimalTemplate className={`${baseClass}__template`}>
|
||||
<h1>{t('confirmDeletion')}</h1>
|
||||
<p>
|
||||
{t('aboutToDeleteCount', { label: getTranslation(plural, i18n), count })}
|
||||
</p>
|
||||
<Button
|
||||
id="confirm-cancel"
|
||||
buttonStyle="secondary"
|
||||
type="button"
|
||||
onClick={deleting ? undefined : () => toggleModal(modalSlug)}
|
||||
>
|
||||
{t('cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={deleting ? undefined : handleDelete}
|
||||
id="confirm-delete"
|
||||
>
|
||||
{deleting ? t('deleting') : t('confirm')}
|
||||
</Button>
|
||||
</MinimalTemplate>
|
||||
</Modal>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteMany;
|
||||
8
src/admin/components/elements/DeleteMany/types.ts
Normal file
8
src/admin/components/elements/DeleteMany/types.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
|
||||
import type { Props as ListProps } from '../../views/collections/List/types';
|
||||
|
||||
export type Props = {
|
||||
collection: SanitizedCollectionConfig,
|
||||
title?: string,
|
||||
resetParams: ListProps['resetParams'],
|
||||
}
|
||||
190
src/admin/components/elements/EditMany/index.scss
Normal file
190
src/admin/components/elements/EditMany/index.scss
Normal file
@@ -0,0 +1,190 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.edit-many {
|
||||
|
||||
&__toggle {
|
||||
font-size: 1rem;
|
||||
line-height: base(1);
|
||||
display: inline-flex;
|
||||
background: var(--theme-elevation-150);
|
||||
color: var(--theme-elevation-800);
|
||||
border-radius: $style-radius-s;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
border: 0;
|
||||
padding: 0 base(.25);
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
|
||||
&:active,
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--theme-elevation-100);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: var(--theme-elevation-100);
|
||||
}
|
||||
}
|
||||
|
||||
&__form {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&__main {
|
||||
width: calc(100% - #{base(15)});
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
margin-top: base(2.5);
|
||||
margin-bottom: base(1);
|
||||
width: 100%;
|
||||
|
||||
&__title {
|
||||
margin: 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&__close {
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
width: base(1);
|
||||
height: base(1);
|
||||
|
||||
svg {
|
||||
width: base(2.75);
|
||||
height: base(2.75);
|
||||
position: relative;
|
||||
left: base(-.825);
|
||||
top: base(-.825);
|
||||
|
||||
.stroke {
|
||||
stroke-width: 2px;
|
||||
vector-effect: non-scaling-stroke;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__edit {
|
||||
padding-top: base(1);
|
||||
padding-bottom: base(2);
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&__sidebar-wrap {
|
||||
position: fixed;
|
||||
width: base(15);
|
||||
height: 100%;
|
||||
top: 0;
|
||||
right: 0;
|
||||
overflow: visible;
|
||||
border-left: 1px solid var(--theme-elevation-100);
|
||||
}
|
||||
|
||||
&__sidebar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
&__sidebar-sticky-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
&__collection-actions,
|
||||
&__meta,
|
||||
&__sidebar-fields {
|
||||
padding-left: base(1.5);
|
||||
}
|
||||
|
||||
&__document-actions {
|
||||
padding-right: $baseline;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: var(--z-nav);
|
||||
|
||||
> * {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@include mid-break {
|
||||
@include blur-bg;
|
||||
}
|
||||
}
|
||||
|
||||
&__document-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: base(1);
|
||||
gap: base(.5);
|
||||
|
||||
.form-submit {
|
||||
width: calc(50% - #{base(1)});
|
||||
|
||||
@include mid-break {
|
||||
width: auto;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
padding-left: base(.5);
|
||||
padding-right: base(.5);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include mid-break {
|
||||
&__main {
|
||||
width: 100%;
|
||||
min-height: initial;
|
||||
}
|
||||
|
||||
&__sidebar-wrap {
|
||||
position: static;
|
||||
width: 100%;
|
||||
height: initial;
|
||||
}
|
||||
|
||||
&__form {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&__edit {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
&__document-actions {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: auto;
|
||||
z-index: var(--z-nav);
|
||||
}
|
||||
|
||||
&__document-actions,
|
||||
&__sidebar-fields {
|
||||
padding-left: var(--gutter-h);
|
||||
padding-right: var(--gutter-h);
|
||||
}
|
||||
}
|
||||
}
|
||||
204
src/admin/components/elements/EditMany/index.tsx
Normal file
204
src/admin/components/elements/EditMany/index.tsx
Normal file
@@ -0,0 +1,204 @@
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useModal } from '@faceless-ui/modal';
|
||||
import { useConfig } from '../../utilities/Config';
|
||||
import { Drawer, DrawerToggler } from '../Drawer';
|
||||
import { Props } from './types';
|
||||
import { SelectAllStatus, useSelection } from '../../views/collections/List/SelectionProvider';
|
||||
import { getTranslation } from '../../../../utilities/getTranslation';
|
||||
import { useAuth } from '../../utilities/Auth';
|
||||
import { FieldSelect } from '../FieldSelect';
|
||||
import FormSubmit from '../../forms/Submit';
|
||||
import Form from '../../forms/Form';
|
||||
import { useForm } from '../../forms/Form/context';
|
||||
import RenderFields from '../../forms/RenderFields';
|
||||
import { OperationContext } from '../../utilities/OperationProvider';
|
||||
import fieldTypes from '../../forms/field-types';
|
||||
import X from '../../icons/X';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'edit-many';
|
||||
|
||||
const Submit: React.FC<{disabled: boolean, action: string}> = ({ action, disabled }) => {
|
||||
const { submit } = useForm();
|
||||
const { t } = useTranslation('general');
|
||||
|
||||
const save = useCallback(() => {
|
||||
submit({
|
||||
skipValidation: true,
|
||||
method: 'PATCH',
|
||||
action,
|
||||
});
|
||||
}, [action, submit]);
|
||||
|
||||
return (
|
||||
<FormSubmit
|
||||
className={`${baseClass}__save`}
|
||||
onClick={save}
|
||||
disabled={disabled}
|
||||
>
|
||||
{t('save')}
|
||||
</FormSubmit>
|
||||
);
|
||||
};
|
||||
const Publish: React.FC<{disabled: boolean, action: string}> = ({ action, disabled }) => {
|
||||
const { submit } = useForm();
|
||||
const { t } = useTranslation('version');
|
||||
|
||||
const save = useCallback(() => {
|
||||
submit({
|
||||
skipValidation: true,
|
||||
method: 'PATCH',
|
||||
overrides: {
|
||||
_status: 'published',
|
||||
},
|
||||
action,
|
||||
});
|
||||
}, [action, submit]);
|
||||
|
||||
return (
|
||||
<FormSubmit
|
||||
className={`${baseClass}__publish`}
|
||||
onClick={save}
|
||||
disabled={disabled}
|
||||
>
|
||||
{t('publishChanges')}
|
||||
</FormSubmit>
|
||||
);
|
||||
};
|
||||
const SaveDraft: React.FC<{disabled: boolean, action: string}> = ({ action, disabled }) => {
|
||||
const { submit } = useForm();
|
||||
const { t } = useTranslation('version');
|
||||
|
||||
const save = useCallback(() => {
|
||||
submit({
|
||||
skipValidation: true,
|
||||
method: 'PATCH',
|
||||
overrides: {
|
||||
_status: 'draft',
|
||||
},
|
||||
action,
|
||||
});
|
||||
}, [action, submit]);
|
||||
|
||||
return (
|
||||
<FormSubmit
|
||||
className={`${baseClass}__draft`}
|
||||
onClick={save}
|
||||
disabled={disabled}
|
||||
>
|
||||
{t('saveDraft')}
|
||||
</FormSubmit>
|
||||
);
|
||||
};
|
||||
const EditMany: React.FC<Props> = (props) => {
|
||||
const {
|
||||
resetParams,
|
||||
collection,
|
||||
collection: {
|
||||
slug,
|
||||
labels: {
|
||||
plural,
|
||||
},
|
||||
fields,
|
||||
} = {},
|
||||
} = props;
|
||||
|
||||
const { permissions } = useAuth();
|
||||
const { closeModal } = useModal();
|
||||
const { serverURL, routes: { api } } = useConfig();
|
||||
const { selectAll, count, getQueryParams } = useSelection();
|
||||
const { t, i18n } = useTranslation('general');
|
||||
const [selected, setSelected] = useState([]);
|
||||
|
||||
const collectionPermissions = permissions?.collections?.[slug];
|
||||
const hasUpdatePermission = collectionPermissions?.update?.permission;
|
||||
|
||||
const drawerSlug = `edit-${slug}`;
|
||||
|
||||
if (selectAll === SelectAllStatus.None || !hasUpdatePermission) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const onSuccess = () => {
|
||||
resetParams({ page: selectAll === SelectAllStatus.AllAvailable ? 1 : undefined });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<DrawerToggler
|
||||
slug={drawerSlug}
|
||||
className={`${baseClass}__toggle`}
|
||||
aria-label={t('edit')}
|
||||
onClick={() => {
|
||||
setSelected([]);
|
||||
}}
|
||||
>
|
||||
{t('edit')}
|
||||
</DrawerToggler>
|
||||
<Drawer
|
||||
slug={drawerSlug}
|
||||
header={null}
|
||||
>
|
||||
<OperationContext.Provider value="update">
|
||||
<Form
|
||||
className={`${baseClass}__form`}
|
||||
onSuccess={onSuccess}
|
||||
>
|
||||
<div className={`${baseClass}__main`}>
|
||||
<div className={`${baseClass}__header`}>
|
||||
<h2 className={`${baseClass}__header__title`}>
|
||||
{t('editingLabel', { label: getTranslation(plural, i18n), count })}
|
||||
</h2>
|
||||
<button
|
||||
className={`${baseClass}__header__close`}
|
||||
id={`close-drawer__${drawerSlug}`}
|
||||
type="button"
|
||||
onClick={() => closeModal(drawerSlug)}
|
||||
aria-label={t('close')}
|
||||
>
|
||||
<X />
|
||||
</button>
|
||||
</div>
|
||||
<FieldSelect
|
||||
fields={fields}
|
||||
setSelected={setSelected}
|
||||
/>
|
||||
<RenderFields
|
||||
fieldTypes={fieldTypes}
|
||||
fieldSchema={selected}
|
||||
/>
|
||||
<div className={`${baseClass}__sidebar-wrap`}>
|
||||
<div className={`${baseClass}__sidebar`}>
|
||||
<div className={`${baseClass}__sidebar-sticky-wrap`}>
|
||||
<div className={`${baseClass}__document-actions`}>
|
||||
<Submit
|
||||
action={`${serverURL}${api}/${slug}${getQueryParams()}`}
|
||||
disabled={selected.length === 0}
|
||||
/>
|
||||
{ collection.versions && (
|
||||
<React.Fragment>
|
||||
<Publish
|
||||
action={`${serverURL}${api}/${slug}${getQueryParams()}`}
|
||||
disabled={selected.length === 0}
|
||||
/>
|
||||
<SaveDraft
|
||||
action={`${serverURL}${api}/${slug}${getQueryParams()}`}
|
||||
disabled={selected.length === 0}
|
||||
/>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</OperationContext.Provider>
|
||||
</Drawer>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditMany;
|
||||
7
src/admin/components/elements/EditMany/types.ts
Normal file
7
src/admin/components/elements/EditMany/types.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
|
||||
import type { Props as ListProps } from '../../views/collections/List/types';
|
||||
|
||||
export type Props = {
|
||||
collection: SanitizedCollectionConfig,
|
||||
resetParams: ListProps['resetParams'],
|
||||
}
|
||||
5
src/admin/components/elements/FieldSelect/index.scss
Normal file
5
src/admin/components/elements/FieldSelect/index.scss
Normal file
@@ -0,0 +1,5 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.field-select {
|
||||
margin-bottom: base(1);
|
||||
}
|
||||
101
src/admin/components/elements/FieldSelect/index.tsx
Normal file
101
src/admin/components/elements/FieldSelect/index.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Field, fieldAffectsData,
|
||||
fieldHasSubFields, FieldWithPath,
|
||||
tabHasName,
|
||||
} from '../../../../fields/config/types';
|
||||
import ReactSelect from '../ReactSelect';
|
||||
import { getTranslation } from '../../../../utilities/getTranslation';
|
||||
import Label from '../../forms/Label';
|
||||
import { useForm } from '../../forms/Form/context';
|
||||
import { createNestedFieldPath } from '../../forms/Form/createNestedFieldPath';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'field-select';
|
||||
|
||||
type Props = {
|
||||
fields: Field[];
|
||||
setSelected: (fields: FieldWithPath[]) => void
|
||||
}
|
||||
|
||||
const combineLabel = (prefix, field, i18n): string => (
|
||||
`${prefix === '' ? '' : `${prefix} > `}${getTranslation(field.label || field.name, i18n) || ''}`
|
||||
);
|
||||
const reduceFields = (fields: Field[], i18n, path = '', labelPrefix = ''): {label: string, value: FieldWithPath}[] => (
|
||||
fields.reduce((fieldsToUse, field) => {
|
||||
// escape for a variety of reasons
|
||||
if (fieldAffectsData(field) && (field.admin?.disableBulkEdit || field.unique || field.hidden || field.admin?.hidden || field.admin?.readOnly)) {
|
||||
return fieldsToUse;
|
||||
}
|
||||
if (!(field.type === 'array' || field.type === 'blocks') && fieldHasSubFields(field)) {
|
||||
return [
|
||||
...fieldsToUse,
|
||||
...reduceFields(field.fields, i18n, createNestedFieldPath(path, field), combineLabel(labelPrefix, field, i18n)),
|
||||
];
|
||||
}
|
||||
if (field.type === 'tabs') {
|
||||
return [
|
||||
...fieldsToUse,
|
||||
...field.tabs.reduce((tabFields, tab) => {
|
||||
return [
|
||||
...tabFields,
|
||||
...(reduceFields(tab.fields, i18n, tabHasName(tab) ? createNestedFieldPath(path, field) : path, combineLabel(labelPrefix, field, i18n))),
|
||||
];
|
||||
}, []),
|
||||
];
|
||||
}
|
||||
const formattedField = {
|
||||
label: combineLabel(labelPrefix, field, i18n),
|
||||
value: {
|
||||
...field,
|
||||
path: createNestedFieldPath(path, field),
|
||||
},
|
||||
};
|
||||
|
||||
return [
|
||||
...fieldsToUse,
|
||||
formattedField,
|
||||
];
|
||||
}, []));
|
||||
export const FieldSelect: React.FC<Props> = ({
|
||||
fields,
|
||||
setSelected,
|
||||
}) => {
|
||||
const { t, i18n } = useTranslation('general');
|
||||
const [options] = useState(() => reduceFields(fields, i18n));
|
||||
const { getFields, dispatchFields } = useForm();
|
||||
const handleChange = (selected) => {
|
||||
const activeFields = getFields();
|
||||
if (selected === null) {
|
||||
setSelected([]);
|
||||
} else {
|
||||
setSelected(selected.map(({ value }) => value));
|
||||
}
|
||||
// remove deselected values from form state
|
||||
if (selected === null || Object.keys(activeFields).length > selected.length) {
|
||||
Object.keys(activeFields).forEach((path) => {
|
||||
if (selected === null || !selected.find((field) => {
|
||||
return field.value.path === path;
|
||||
})) {
|
||||
dispatchFields({
|
||||
type: 'REMOVE',
|
||||
path,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<Label label={t('fields:selectFieldsToEdit')} />
|
||||
<ReactSelect
|
||||
options={options}
|
||||
isMulti
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
&__wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: var(--theme-elevation-50);
|
||||
}
|
||||
|
||||
.search-filter {
|
||||
@@ -21,24 +23,28 @@
|
||||
|
||||
&__buttons-wrap {
|
||||
display: flex;
|
||||
margin-left: - base(.5);
|
||||
margin-right: - base(.5);
|
||||
width: calc(100% + #{base(1)});
|
||||
align-items: center;
|
||||
margin-right: base(.5);
|
||||
|
||||
.btn, .pill {
|
||||
margin: 0 0 0 base(.5);
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin: 0 base(.5);
|
||||
background-color: var(--theme-elevation-100);
|
||||
cursor: pointer;
|
||||
padding: 0 base(.25);
|
||||
border-radius: $style-radius-s;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--theme-elevation-200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__toggle-columns,
|
||||
&__toggle-where,
|
||||
&__toggle-sort {
|
||||
min-width: 140px;
|
||||
|
||||
&.btn--style-primary {
|
||||
svg {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
&__buttons-active {
|
||||
svg {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,25 +54,10 @@
|
||||
margin-top: base(1);
|
||||
}
|
||||
|
||||
@include mid-break {
|
||||
&__buttons {
|
||||
margin-left: base(.5);
|
||||
}
|
||||
|
||||
&__buttons-wrap {
|
||||
margin-left: - base(.25);
|
||||
margin-right: - base(.25);
|
||||
width: calc(100% + #{base(0.5)});
|
||||
|
||||
.btn {
|
||||
margin: 0 base(.25);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include small-break {
|
||||
&__wrap {
|
||||
flex-wrap: wrap;
|
||||
background-color: unset;
|
||||
}
|
||||
|
||||
.search-filter {
|
||||
@@ -74,11 +65,23 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__buttons {
|
||||
margin: 0;
|
||||
&__buttons-wrap {
|
||||
margin-left: - base(.25);
|
||||
margin-right: - base(.25);
|
||||
width: calc(100% + #{base(0.5)});
|
||||
|
||||
.pill {
|
||||
margin: 0 base(.25);
|
||||
padding: base(.5) base(1);
|
||||
|
||||
svg {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__buttons {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import AnimateHeight from 'react-animate-height';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useWindowInfo } from '@faceless-ui/window-info';
|
||||
import { fieldAffectsData } from '../../../../fields/config/types';
|
||||
import SearchFilter from '../SearchFilter';
|
||||
import ColumnSelector from '../ColumnSelector';
|
||||
@@ -13,6 +14,12 @@ import validateWhereQuery from '../WhereBuilder/validateWhereQuery';
|
||||
import flattenFields from '../../../../utilities/flattenTopLevelFields';
|
||||
import { getTextFieldsToBeSearched } from './getTextFieldsToBeSearched';
|
||||
import { getTranslation } from '../../../../utilities/getTranslation';
|
||||
import Pill from '../Pill';
|
||||
import Chevron from '../../icons/Chevron';
|
||||
import EditMany from '../EditMany';
|
||||
import DeleteMany from '../DeleteMany';
|
||||
import PublishMany from '../PublishMany';
|
||||
import UnpublishMany from '../UnpublishMany';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
@@ -26,6 +33,7 @@ const ListControls: React.FC<Props> = (props) => {
|
||||
handleSortChange,
|
||||
handleWhereChange,
|
||||
modifySearchQuery = true,
|
||||
resetParams,
|
||||
collection: {
|
||||
fields,
|
||||
admin: {
|
||||
@@ -45,6 +53,7 @@ const ListControls: React.FC<Props> = (props) => {
|
||||
const [textFieldsToBeSearched] = useState(getTextFieldsToBeSearched(listSearchableFields, fields));
|
||||
const [visibleDrawer, setVisibleDrawer] = useState<'where' | 'sort' | 'columns'>(shouldInitializeWhereOpened ? 'where' : undefined);
|
||||
const { t, i18n } = useTranslation('general');
|
||||
const { breakpoints: { s: smallBreak } } = useWindowInfo();
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
@@ -58,26 +67,44 @@ const ListControls: React.FC<Props> = (props) => {
|
||||
/>
|
||||
<div className={`${baseClass}__buttons`}>
|
||||
<div className={`${baseClass}__buttons-wrap`}>
|
||||
{ !smallBreak && (
|
||||
<React.Fragment>
|
||||
<EditMany
|
||||
collection={collection}
|
||||
resetParams={resetParams}
|
||||
/>
|
||||
<PublishMany
|
||||
collection={collection}
|
||||
resetParams={resetParams}
|
||||
/>
|
||||
<UnpublishMany
|
||||
collection={collection}
|
||||
resetParams={resetParams}
|
||||
/>
|
||||
<DeleteMany
|
||||
collection={collection}
|
||||
resetParams={resetParams}
|
||||
/>
|
||||
</React.Fragment>
|
||||
)}
|
||||
{enableColumns && (
|
||||
<Button
|
||||
className={`${baseClass}__toggle-columns`}
|
||||
buttonStyle={visibleDrawer === 'columns' ? undefined : 'secondary'}
|
||||
<Pill
|
||||
pillStyle="dark"
|
||||
className={`${baseClass}__toggle-columns ${visibleDrawer === 'columns' ? `${baseClass}__buttons-active` : ''}`}
|
||||
onClick={() => setVisibleDrawer(visibleDrawer !== 'columns' ? 'columns' : undefined)}
|
||||
icon="chevron"
|
||||
iconStyle="none"
|
||||
icon={<Chevron />}
|
||||
>
|
||||
{t('columns')}
|
||||
</Button>
|
||||
</Pill>
|
||||
)}
|
||||
<Button
|
||||
className={`${baseClass}__toggle-where`}
|
||||
buttonStyle={visibleDrawer === 'where' ? undefined : 'secondary'}
|
||||
<Pill
|
||||
pillStyle="dark"
|
||||
className={`${baseClass}__toggle-where ${visibleDrawer === 'where' ? `${baseClass}__buttons-active` : ''}`}
|
||||
onClick={() => setVisibleDrawer(visibleDrawer !== 'where' ? 'where' : undefined)}
|
||||
icon="chevron"
|
||||
iconStyle="none"
|
||||
icon={<Chevron />}
|
||||
>
|
||||
{t('filters')}
|
||||
</Button>
|
||||
</Pill>
|
||||
{enableSort && (
|
||||
<Button
|
||||
className={`${baseClass}__toggle-sort`}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Where } from '../../../../types';
|
||||
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
|
||||
import { Column } from '../Table/types';
|
||||
import type { Props as ListProps } from '../../views/collections/List/types';
|
||||
|
||||
export type Props = {
|
||||
enableColumns?: boolean
|
||||
@@ -9,6 +10,7 @@ export type Props = {
|
||||
handleSortChange?: (sort: string) => void
|
||||
handleWhereChange?: (where: Where) => void
|
||||
collection: SanitizedCollectionConfig
|
||||
resetParams?: ListProps['resetParams']
|
||||
}
|
||||
|
||||
export type ListControls = {
|
||||
|
||||
@@ -222,16 +222,6 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
|
||||
hasCreatePermission,
|
||||
disableEyebrow: true,
|
||||
modifySearchParams: false,
|
||||
onCardClick: (doc) => {
|
||||
if (typeof onSelect === 'function') {
|
||||
onSelect({
|
||||
docID: doc.id,
|
||||
collectionConfig: selectedCollectionConfig,
|
||||
});
|
||||
}
|
||||
closeModal(drawerSlug);
|
||||
},
|
||||
disableCardLink: true,
|
||||
handleSortChange: setSort,
|
||||
handleWhereChange: setWhere,
|
||||
handlePageChange: setPage,
|
||||
|
||||
19
src/admin/components/elements/ListSelection/index.scss
Normal file
19
src/admin/components/elements/ListSelection/index.scss
Normal file
@@ -0,0 +1,19 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.list-selection {
|
||||
margin-left: auto;
|
||||
color: var(--theme-elevation-500);
|
||||
|
||||
&__button {
|
||||
color: var(--theme-elevation-500);
|
||||
background: unset;
|
||||
border: none;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
@include small-break {
|
||||
margin-bottom: base(.5);
|
||||
}
|
||||
}
|
||||
41
src/admin/components/elements/ListSelection/index.tsx
Normal file
41
src/admin/components/elements/ListSelection/index.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SelectAllStatus, useSelection } from '../../views/collections/List/SelectionProvider';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'list-selection';
|
||||
|
||||
type Props = {
|
||||
label: string
|
||||
}
|
||||
const ListSelection: React.FC<Props> = ({ label }) => {
|
||||
const { toggleAll, count, totalDocs, selectAll } = useSelection();
|
||||
const { t } = useTranslation('general');
|
||||
|
||||
if (count === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<span>{t('selectedCount', { label, count })}</span>
|
||||
{ selectAll !== SelectAllStatus.AllAvailable && (
|
||||
<Fragment>
|
||||
{' '}
|
||||
—
|
||||
<button
|
||||
className={`${baseClass}__button`}
|
||||
type="button"
|
||||
onClick={() => toggleAll(true)}
|
||||
aria-label={t('selectAll', { label, count })}
|
||||
>
|
||||
{t('selectAll', { label, count: totalDocs })}
|
||||
</button>
|
||||
</Fragment>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ListSelection;
|
||||
17
src/admin/components/elements/PublishMany/index.scss
Normal file
17
src/admin/components/elements/PublishMany/index.scss
Normal file
@@ -0,0 +1,17 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.publish-many {
|
||||
@include blur-bg;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
|
||||
&__template {
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-right: $baseline;
|
||||
}
|
||||
}
|
||||
123
src/admin/components/elements/PublishMany/index.tsx
Normal file
123
src/admin/components/elements/PublishMany/index.tsx
Normal file
@@ -0,0 +1,123 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { Modal, useModal } from '@faceless-ui/modal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useConfig } from '../../utilities/Config';
|
||||
import Button from '../Button';
|
||||
import MinimalTemplate from '../../templates/Minimal';
|
||||
import { requests } from '../../../api';
|
||||
import { Props } from './types';
|
||||
import { SelectAllStatus, useSelection } from '../../views/collections/List/SelectionProvider';
|
||||
import { getTranslation } from '../../../../utilities/getTranslation';
|
||||
import Pill from '../Pill';
|
||||
import { useAuth } from '../../utilities/Auth';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'publish-many';
|
||||
|
||||
const PublishMany: React.FC<Props> = (props) => {
|
||||
const {
|
||||
resetParams,
|
||||
collection: {
|
||||
slug,
|
||||
labels: {
|
||||
plural,
|
||||
},
|
||||
versions,
|
||||
} = {},
|
||||
} = props;
|
||||
|
||||
const { serverURL, routes: { api } } = useConfig();
|
||||
const { permissions } = useAuth();
|
||||
const { toggleModal } = useModal();
|
||||
const { t, i18n } = useTranslation('version');
|
||||
const { selectAll, count, getQueryParams } = useSelection();
|
||||
const [submitted, setSubmitted] = useState(false);
|
||||
|
||||
const collectionPermissions = permissions?.collections?.[slug];
|
||||
const hasPermission = collectionPermissions?.update?.permission;
|
||||
|
||||
const modalSlug = `publish-${slug}`;
|
||||
|
||||
const addDefaultError = useCallback(() => {
|
||||
toast.error(t('error:unknown'));
|
||||
}, [t]);
|
||||
|
||||
const handlePublish = useCallback(() => {
|
||||
setSubmitted(true);
|
||||
requests.patch(`${serverURL}${api}/${slug}${getQueryParams({ _status: { not_equals: 'published' } })}`, {
|
||||
body: JSON.stringify({
|
||||
_status: 'published',
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept-Language': i18n.language,
|
||||
},
|
||||
}).then(async (res) => {
|
||||
try {
|
||||
const json = await res.json();
|
||||
toggleModal(modalSlug);
|
||||
if (res.status < 400) {
|
||||
toast.success(t('general:updatedSuccessfully'));
|
||||
resetParams({ page: selectAll ? 1 : undefined });
|
||||
return null;
|
||||
}
|
||||
|
||||
if (json.errors) {
|
||||
json.errors.forEach((error) => toast.error(error.message));
|
||||
} else {
|
||||
addDefaultError();
|
||||
}
|
||||
return false;
|
||||
} catch (e) {
|
||||
return addDefaultError();
|
||||
}
|
||||
});
|
||||
}, [addDefaultError, api, getQueryParams, i18n.language, modalSlug, resetParams, selectAll, serverURL, slug, t, toggleModal]);
|
||||
|
||||
if (!(versions?.drafts) || (selectAll === SelectAllStatus.None || !hasPermission)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Pill
|
||||
className={`${baseClass}__toggle`}
|
||||
onClick={() => {
|
||||
setSubmitted(false);
|
||||
toggleModal(modalSlug);
|
||||
}}
|
||||
>
|
||||
{t('publish')}
|
||||
</Pill>
|
||||
<Modal
|
||||
slug={modalSlug}
|
||||
className={baseClass}
|
||||
>
|
||||
<MinimalTemplate className={`${baseClass}__template`}>
|
||||
<h1>{t('confirmPublish')}</h1>
|
||||
<p>
|
||||
{t('aboutToPublishSelection', { label: getTranslation(plural, i18n) })}
|
||||
</p>
|
||||
<Button
|
||||
id="confirm-cancel"
|
||||
buttonStyle="secondary"
|
||||
type="button"
|
||||
onClick={submitted ? undefined : () => toggleModal(modalSlug)}
|
||||
>
|
||||
{t('general:cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={submitted ? undefined : handlePublish}
|
||||
id="confirm-publish"
|
||||
>
|
||||
{submitted ? t('publishing') : t('general:confirm')}
|
||||
</Button>
|
||||
</MinimalTemplate>
|
||||
</Modal>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default PublishMany;
|
||||
7
src/admin/components/elements/PublishMany/types.ts
Normal file
7
src/admin/components/elements/PublishMany/types.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
|
||||
import type { Props as ListProps } from '../../views/collections/List/types';
|
||||
|
||||
export type Props = {
|
||||
collection: SanitizedCollectionConfig,
|
||||
resetParams: ListProps['resetParams'],
|
||||
}
|
||||
@@ -7,10 +7,20 @@
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
right: base(.5);
|
||||
left: base(.5);
|
||||
}
|
||||
|
||||
&__input {
|
||||
@include formInput;
|
||||
box-shadow: none;
|
||||
padding-left: base(2);
|
||||
background-color: var(--theme-elevation-50);
|
||||
border: none;
|
||||
|
||||
&:not(:disabled) {
|
||||
&:hover, &:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,53 +1,25 @@
|
||||
import React from 'react';
|
||||
import type { TFunction } from 'react-i18next';
|
||||
import Cell from '../../views/collections/List/Cell';
|
||||
import SortColumn from '../SortColumn';
|
||||
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
|
||||
import { Column } from '../Table/types';
|
||||
import { Field, fieldIsPresentationalOnly } from '../../../../fields/config/types';
|
||||
import { fieldIsPresentationalOnly } from '../../../../fields/config/types';
|
||||
import flattenFields from '../../../../utilities/flattenTopLevelFields';
|
||||
import { Props as CellProps } from '../../views/collections/List/Cell/types';
|
||||
import SelectAll from '../../views/collections/List/SelectAll';
|
||||
import SelectRow from '../../views/collections/List/SelectRow';
|
||||
|
||||
const buildColumns = ({
|
||||
collection,
|
||||
columns,
|
||||
t,
|
||||
cellProps,
|
||||
}: {
|
||||
collection: SanitizedCollectionConfig,
|
||||
columns: Pick<Column, 'accessor' | 'active'>[],
|
||||
t: TFunction,
|
||||
cellProps: Partial<CellProps>[]
|
||||
}): Column[] => {
|
||||
// only insert each base field if it doesn't already exist in the collection
|
||||
const baseFields: Field[] = [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'text',
|
||||
label: 'ID',
|
||||
},
|
||||
{
|
||||
name: 'updatedAt',
|
||||
type: 'date',
|
||||
label: t('updatedAt'),
|
||||
},
|
||||
{
|
||||
name: 'createdAt',
|
||||
type: 'date',
|
||||
label: t('createdAt'),
|
||||
},
|
||||
];
|
||||
|
||||
const combinedFields = baseFields.reduce((acc, field) => {
|
||||
// if the field already exists in the collection, don't add it
|
||||
if (acc.find((f) => 'name' in f && 'name' in field && f.name === field.name)) return acc;
|
||||
return [...acc, field];
|
||||
}, collection.fields);
|
||||
|
||||
const flattenedFields = flattenFields(combinedFields, true);
|
||||
|
||||
// sort the fields to the order of activeColumns
|
||||
const sortedFields = flattenedFields.sort((a, b) => {
|
||||
const sortedFields = flattenFields(collection.fields, true).sort((a, b) => {
|
||||
const aIndex = columns.findIndex((column) => column.accessor === a.name);
|
||||
const bIndex = columns.findIndex((column) => column.accessor === b.name);
|
||||
if (aIndex === -1 && bIndex === -1) return 0;
|
||||
@@ -97,6 +69,23 @@ const buildColumns = ({
|
||||
};
|
||||
});
|
||||
|
||||
cols.unshift({
|
||||
active: true,
|
||||
label: null,
|
||||
name: '',
|
||||
accessor: '_select',
|
||||
components: {
|
||||
Heading: (
|
||||
<SelectAll />
|
||||
),
|
||||
renderCell: (rowData) => (
|
||||
<SelectRow
|
||||
id={rowData.id}
|
||||
/>
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
return cols;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { TFunction } from 'react-i18next';
|
||||
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
|
||||
import { Column } from '../Table/types';
|
||||
import buildColumns from './buildColumns';
|
||||
@@ -9,7 +8,6 @@ type TOGGLE = {
|
||||
type: 'toggle',
|
||||
payload: {
|
||||
column: string
|
||||
t: TFunction
|
||||
collection: SanitizedCollectionConfig
|
||||
cellProps: Partial<CellProps>[]
|
||||
}
|
||||
@@ -19,7 +17,6 @@ type SET = {
|
||||
type: 'set',
|
||||
payload: {
|
||||
columns: Pick<Column, 'accessor' | 'active'>[]
|
||||
t: TFunction
|
||||
collection: SanitizedCollectionConfig
|
||||
cellProps: Partial<CellProps>[]
|
||||
}
|
||||
@@ -30,7 +27,6 @@ type MOVE = {
|
||||
payload: {
|
||||
fromIndex: number
|
||||
toIndex: number
|
||||
t: TFunction
|
||||
collection: SanitizedCollectionConfig
|
||||
cellProps: Partial<CellProps>[]
|
||||
}
|
||||
@@ -43,7 +39,6 @@ export const columnReducer = (state: Column[], action: Action): Column[] => {
|
||||
case 'toggle': {
|
||||
const {
|
||||
column,
|
||||
t,
|
||||
collection,
|
||||
cellProps,
|
||||
} = action.payload;
|
||||
@@ -62,7 +57,6 @@ export const columnReducer = (state: Column[], action: Action): Column[] => {
|
||||
return buildColumns({
|
||||
columns: withToggledColumn,
|
||||
collection,
|
||||
t,
|
||||
cellProps,
|
||||
});
|
||||
}
|
||||
@@ -70,7 +64,6 @@ export const columnReducer = (state: Column[], action: Action): Column[] => {
|
||||
const {
|
||||
fromIndex,
|
||||
toIndex,
|
||||
t,
|
||||
collection,
|
||||
cellProps,
|
||||
} = action.payload;
|
||||
@@ -82,14 +75,12 @@ export const columnReducer = (state: Column[], action: Action): Column[] => {
|
||||
return buildColumns({
|
||||
columns: withMovedColumn,
|
||||
collection,
|
||||
t,
|
||||
cellProps,
|
||||
});
|
||||
}
|
||||
case 'set': {
|
||||
const {
|
||||
columns,
|
||||
t,
|
||||
collection,
|
||||
cellProps,
|
||||
} = action.payload;
|
||||
@@ -97,7 +88,6 @@ export const columnReducer = (state: Column[], action: Action): Column[] => {
|
||||
return buildColumns({
|
||||
columns,
|
||||
collection,
|
||||
t,
|
||||
cellProps,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useEffect, useReducer, createContext, useContext, useRef } from 'react';
|
||||
import React, { useCallback, useEffect, useReducer, createContext, useContext, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
|
||||
import { usePreferences } from '../../utilities/Preferences';
|
||||
@@ -8,6 +8,8 @@ import buildColumns from './buildColumns';
|
||||
import { Action, columnReducer } from './columnReducer';
|
||||
import getInitialColumnState from './getInitialColumns';
|
||||
import { Props as CellProps } from '../../views/collections/List/Cell/types';
|
||||
import formatFields from '../../views/collections/List/formatFields';
|
||||
import { Field } from '../../../../fields/config/types';
|
||||
|
||||
export interface ITableColumns {
|
||||
columns: Column[]
|
||||
@@ -33,21 +35,22 @@ export const TableColumnsProvider: React.FC<{
|
||||
cellProps,
|
||||
collection,
|
||||
collection: {
|
||||
fields,
|
||||
admin: {
|
||||
useAsTitle,
|
||||
defaultColumns,
|
||||
},
|
||||
},
|
||||
}) => {
|
||||
const { t } = useTranslation('general');
|
||||
const preferenceKey = `${collection.slug}-list`;
|
||||
const prevCollection = useRef<SanitizedCollectionConfig['slug']>();
|
||||
const hasInitialized = useRef(false);
|
||||
const { getPreference, setPreference } = usePreferences();
|
||||
const { t } = useTranslation();
|
||||
const [formattedFields] = useState<Field[]>(() => formatFields(collection, t));
|
||||
|
||||
const [tableColumns, dispatchTableColumns] = useReducer(columnReducer, {}, () => {
|
||||
const initialColumns = getInitialColumnState(fields, useAsTitle, defaultColumns);
|
||||
const initialColumns = getInitialColumnState(formattedFields, useAsTitle, defaultColumns);
|
||||
|
||||
return buildColumns({
|
||||
collection,
|
||||
columns: initialColumns.map((column) => ({
|
||||
@@ -55,7 +58,6 @@ export const TableColumnsProvider: React.FC<{
|
||||
active: true,
|
||||
})),
|
||||
cellProps,
|
||||
t,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -72,7 +74,7 @@ export const TableColumnsProvider: React.FC<{
|
||||
|
||||
const currentPreferences = await getPreference<ListPreferences>(preferenceKey);
|
||||
prevCollection.current = collection.slug;
|
||||
const initialColumns = getInitialColumnState(fields, useAsTitle, defaultColumns);
|
||||
const initialColumns = getInitialColumnState(formattedFields, useAsTitle, defaultColumns);
|
||||
const newCols = currentPreferences?.columns || initialColumns;
|
||||
|
||||
dispatchTableColumns({
|
||||
@@ -89,8 +91,7 @@ export const TableColumnsProvider: React.FC<{
|
||||
}
|
||||
return column;
|
||||
}),
|
||||
t,
|
||||
collection,
|
||||
collection: { ...collection, fields: formatFields(collection, t) },
|
||||
cellProps,
|
||||
},
|
||||
});
|
||||
@@ -100,7 +101,7 @@ export const TableColumnsProvider: React.FC<{
|
||||
};
|
||||
|
||||
sync();
|
||||
}, [preferenceKey, setPreference, fields, tableColumns, getPreference, useAsTitle, defaultColumns, t, collection, cellProps]);
|
||||
}, [preferenceKey, setPreference, tableColumns, getPreference, useAsTitle, defaultColumns, collection, cellProps, formattedFields, t]);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Set preferences on column change
|
||||
@@ -130,12 +131,11 @@ export const TableColumnsProvider: React.FC<{
|
||||
dispatchTableColumns({
|
||||
type: 'set',
|
||||
payload: {
|
||||
collection,
|
||||
collection: { ...collection, fields: formatFields(collection, t) },
|
||||
columns: columns.map((column) => ({
|
||||
accessor: column,
|
||||
active: true,
|
||||
})),
|
||||
t,
|
||||
// onSelect,
|
||||
cellProps,
|
||||
},
|
||||
@@ -153,8 +153,7 @@ export const TableColumnsProvider: React.FC<{
|
||||
payload: {
|
||||
fromIndex,
|
||||
toIndex,
|
||||
collection,
|
||||
t,
|
||||
collection: { ...collection, fields: formatFields(collection, t) },
|
||||
cellProps,
|
||||
},
|
||||
});
|
||||
@@ -165,8 +164,7 @@ export const TableColumnsProvider: React.FC<{
|
||||
type: 'toggle',
|
||||
payload: {
|
||||
column,
|
||||
collection,
|
||||
t,
|
||||
collection: { ...collection, fields: formatFields(collection, t) },
|
||||
cellProps,
|
||||
},
|
||||
});
|
||||
|
||||
17
src/admin/components/elements/UnpublishMany/index.scss
Normal file
17
src/admin/components/elements/UnpublishMany/index.scss
Normal file
@@ -0,0 +1,17 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.unpublish-many {
|
||||
@include blur-bg;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
|
||||
&__template {
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-right: $baseline;
|
||||
}
|
||||
}
|
||||
123
src/admin/components/elements/UnpublishMany/index.tsx
Normal file
123
src/admin/components/elements/UnpublishMany/index.tsx
Normal file
@@ -0,0 +1,123 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { Modal, useModal } from '@faceless-ui/modal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useConfig } from '../../utilities/Config';
|
||||
import Button from '../Button';
|
||||
import MinimalTemplate from '../../templates/Minimal';
|
||||
import { requests } from '../../../api';
|
||||
import { Props } from './types';
|
||||
import { SelectAllStatus, useSelection } from '../../views/collections/List/SelectionProvider';
|
||||
import { getTranslation } from '../../../../utilities/getTranslation';
|
||||
import Pill from '../Pill';
|
||||
import { useAuth } from '../../utilities/Auth';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'unpublish-many';
|
||||
|
||||
const UnpublishMany: React.FC<Props> = (props) => {
|
||||
const {
|
||||
resetParams,
|
||||
collection: {
|
||||
slug,
|
||||
labels: {
|
||||
plural,
|
||||
},
|
||||
versions,
|
||||
} = {},
|
||||
} = props;
|
||||
|
||||
const { serverURL, routes: { api } } = useConfig();
|
||||
const { permissions } = useAuth();
|
||||
const { toggleModal } = useModal();
|
||||
const { t, i18n } = useTranslation('version');
|
||||
const { selectAll, count, getQueryParams } = useSelection();
|
||||
const [submitted, setSubmitted] = useState(false);
|
||||
|
||||
const collectionPermissions = permissions?.collections?.[slug];
|
||||
const hasPermission = collectionPermissions?.update?.permission;
|
||||
|
||||
const modalSlug = `unpublish-${slug}`;
|
||||
|
||||
const addDefaultError = useCallback(() => {
|
||||
toast.error(t('error:unknown'));
|
||||
}, [t]);
|
||||
|
||||
const handleUnpublish = useCallback(() => {
|
||||
setSubmitted(true);
|
||||
requests.patch(`${serverURL}${api}/${slug}${getQueryParams({ _status: { not_equals: 'draft' } })}`, {
|
||||
body: JSON.stringify({
|
||||
_status: 'draft',
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept-Language': i18n.language,
|
||||
},
|
||||
}).then(async (res) => {
|
||||
try {
|
||||
const json = await res.json();
|
||||
toggleModal(modalSlug);
|
||||
if (res.status < 400) {
|
||||
toast.success(t('general:updatedSuccessfully'));
|
||||
resetParams({ page: selectAll ? 1 : undefined });
|
||||
return null;
|
||||
}
|
||||
|
||||
if (json.errors) {
|
||||
json.errors.forEach((error) => toast.error(error.message));
|
||||
} else {
|
||||
addDefaultError();
|
||||
}
|
||||
return false;
|
||||
} catch (e) {
|
||||
return addDefaultError();
|
||||
}
|
||||
});
|
||||
}, [addDefaultError, api, getQueryParams, i18n.language, modalSlug, resetParams, selectAll, serverURL, slug, t, toggleModal]);
|
||||
|
||||
if (!(versions?.drafts) || (selectAll === SelectAllStatus.None || !hasPermission)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Pill
|
||||
className={`${baseClass}__toggle`}
|
||||
onClick={() => {
|
||||
setSubmitted(false);
|
||||
toggleModal(modalSlug);
|
||||
}}
|
||||
>
|
||||
{t('unpublish')}
|
||||
</Pill>
|
||||
<Modal
|
||||
slug={modalSlug}
|
||||
className={baseClass}
|
||||
>
|
||||
<MinimalTemplate className={`${baseClass}__template`}>
|
||||
<h1>{t('confirmUnpublish')}</h1>
|
||||
<p>
|
||||
{t('aboutToUnpublishSelection', { label: getTranslation(plural, i18n) })}
|
||||
</p>
|
||||
<Button
|
||||
id="confirm-cancel"
|
||||
buttonStyle="secondary"
|
||||
type="button"
|
||||
onClick={submitted ? undefined : () => toggleModal(modalSlug)}
|
||||
>
|
||||
{t('general:cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={submitted ? undefined : handleUnpublish}
|
||||
id="confirm-unpublish"
|
||||
>
|
||||
{submitted ? t('unpublishing') : t('general:confirm')}
|
||||
</Button>
|
||||
</MinimalTemplate>
|
||||
</Modal>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default UnpublishMany;
|
||||
7
src/admin/components/elements/UnpublishMany/types.ts
Normal file
7
src/admin/components/elements/UnpublishMany/types.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
|
||||
import type { Props as ListProps } from '../../views/collections/List/types';
|
||||
|
||||
export type Props = {
|
||||
collection: SanitizedCollectionConfig,
|
||||
resetParams: ListProps['resetParams'],
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.upload-gallery {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: base(2) -#{base(.5)};
|
||||
width: calc(100% + #{$baseline});
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
li {
|
||||
min-width: 0;
|
||||
width: 16.66%;
|
||||
}
|
||||
|
||||
.thumbnail-card {
|
||||
margin: base(.5);
|
||||
max-width: initial;
|
||||
}
|
||||
|
||||
@include mid-break {
|
||||
li {
|
||||
width: 33.33%;
|
||||
}
|
||||
}
|
||||
|
||||
@include small-break {
|
||||
li {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Props } from './types';
|
||||
import { ThumbnailCard } from '../ThumbnailCard';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'upload-gallery';
|
||||
|
||||
const UploadGallery: React.FC<Props> = (props) => {
|
||||
const { docs, onCardClick, collection } = props;
|
||||
|
||||
if (docs && docs.length > 0) {
|
||||
return (
|
||||
<ul className={baseClass}>
|
||||
{docs.map((doc) => (
|
||||
<li key={String(doc.id)}>
|
||||
<ThumbnailCard
|
||||
doc={doc}
|
||||
collection={collection}
|
||||
onClick={() => onCardClick(doc)}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default UploadGallery;
|
||||
@@ -1,7 +0,0 @@
|
||||
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
|
||||
|
||||
export type Props = {
|
||||
docs?: Record<string, unknown>[],
|
||||
collection: SanitizedCollectionConfig,
|
||||
onCardClick: (doc) => void,
|
||||
}
|
||||
11
src/admin/components/icons/Line/index.scss
Normal file
11
src/admin/components/icons/Line/index.scss
Normal file
@@ -0,0 +1,11 @@
|
||||
@import '../../../scss/styles';
|
||||
|
||||
.icon--line {
|
||||
width: $baseline;
|
||||
height: $baseline;
|
||||
|
||||
.stroke {
|
||||
stroke: var(--theme-elevation-800);
|
||||
stroke-width: $style-stroke-width;
|
||||
}
|
||||
}
|
||||
21
src/admin/components/icons/Line/index.tsx
Normal file
21
src/admin/components/icons/Line/index.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import React from 'react';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const Line: React.FC = () => (
|
||||
<svg
|
||||
className="icon icon--line"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 25 25"
|
||||
>
|
||||
<line
|
||||
x1="8.05164"
|
||||
y1="12.594"
|
||||
x2="16.468"
|
||||
y2="12.594"
|
||||
className="stroke"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default Line;
|
||||
@@ -0,0 +1,17 @@
|
||||
@import '../../../../../../../scss/styles.scss';
|
||||
|
||||
.upload-cell {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
margin: base(-.25) 0;
|
||||
|
||||
.thumbnail {
|
||||
max-width: base(3);
|
||||
height: base(3);
|
||||
}
|
||||
|
||||
&__filename {
|
||||
align-self: center;
|
||||
margin-left: base(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import Thumbnail from '../../../../../../elements/Thumbnail';
|
||||
import type { Props } from './types';
|
||||
import { useConfig } from '../../../../../../utilities/Config';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'upload-cell';
|
||||
|
||||
const UploadCell:React.FC<Props> = ({ rowData, cellData, collection }: Props) => {
|
||||
const { routes: { admin } } = useConfig();
|
||||
|
||||
return (
|
||||
<Link
|
||||
className={baseClass}
|
||||
to={`${admin}/collections/${collection.slug}/${rowData.id}`}
|
||||
>
|
||||
<Thumbnail
|
||||
size="small"
|
||||
doc={{
|
||||
...rowData,
|
||||
filename: cellData,
|
||||
}}
|
||||
collection={collection}
|
||||
/>
|
||||
<span className={`${baseClass}__filename`}>{ String(cellData) }</span>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default UploadCell;
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { SanitizedCollectionConfig } from '../../../../../../../../collections/config/types';
|
||||
import { Props as CellProps } from '../../types';
|
||||
|
||||
export type Props = CellProps & {
|
||||
collection: SanitizedCollectionConfig
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useConfig } from '../../../utilities/Config';
|
||||
import UploadGallery from '../../../elements/UploadGallery';
|
||||
import { useWindowInfo } from '@faceless-ui/window-info';
|
||||
import Eyebrow from '../../../elements/Eyebrow';
|
||||
import Paginator from '../../../elements/Paginator';
|
||||
import ListControls from '../../../elements/ListControls';
|
||||
import ListSelection from '../../../elements/ListSelection';
|
||||
import Pill from '../../../elements/Pill';
|
||||
import Button from '../../../elements/Button';
|
||||
import { Table } from '../../../elements/Table';
|
||||
@@ -17,6 +16,11 @@ import { Gutter } from '../../../elements/Gutter';
|
||||
import { RelationshipProvider } from './RelationshipProvider';
|
||||
import { getTranslation } from '../../../../../utilities/getTranslation';
|
||||
import { StaggeredShimmers } from '../../../elements/ShimmerEffect';
|
||||
import { SelectionProvider } from './SelectionProvider';
|
||||
import EditMany from '../../../elements/EditMany';
|
||||
import DeleteMany from '../../../elements/DeleteMany';
|
||||
import PublishMany from '../../../elements/PublishMany';
|
||||
import UnpublishMany from '../../../elements/UnpublishMany';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
@@ -26,8 +30,6 @@ const DefaultList: React.FC<Props> = (props) => {
|
||||
const {
|
||||
collection,
|
||||
collection: {
|
||||
upload,
|
||||
slug,
|
||||
labels: {
|
||||
singular: singularLabel,
|
||||
plural: pluralLabel,
|
||||
@@ -42,17 +44,15 @@ const DefaultList: React.FC<Props> = (props) => {
|
||||
hasCreatePermission,
|
||||
disableEyebrow,
|
||||
modifySearchParams,
|
||||
disableCardLink,
|
||||
onCardClick,
|
||||
handleSortChange,
|
||||
handleWhereChange,
|
||||
handlePageChange,
|
||||
handlePerPageChange,
|
||||
customHeader,
|
||||
resetParams,
|
||||
} = props;
|
||||
|
||||
const { routes: { admin } } = useConfig();
|
||||
const history = useHistory();
|
||||
const { breakpoints: { s: smallBreak } } = useWindowInfo();
|
||||
const { t, i18n } = useTranslation('general');
|
||||
|
||||
return (
|
||||
@@ -60,117 +60,135 @@ const DefaultList: React.FC<Props> = (props) => {
|
||||
<Meta
|
||||
title={getTranslation(collection.labels.plural, i18n)}
|
||||
/>
|
||||
{!disableEyebrow && (
|
||||
<Eyebrow />
|
||||
)}
|
||||
<Gutter className={`${baseClass}__wrap`}>
|
||||
<header className={`${baseClass}__header`}>
|
||||
{customHeader && customHeader}
|
||||
{!customHeader && (
|
||||
<Fragment>
|
||||
<h1>
|
||||
{getTranslation(pluralLabel, i18n)}
|
||||
</h1>
|
||||
{hasCreatePermission && (
|
||||
<Pill to={newDocumentURL}>
|
||||
{t('createNew')}
|
||||
</Pill>
|
||||
)}
|
||||
{description && (
|
||||
<div className={`${baseClass}__sub-header`}>
|
||||
<ViewDescription description={description} />
|
||||
</div>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
</header>
|
||||
<ListControls
|
||||
collection={collection}
|
||||
enableColumns={Boolean(!upload)}
|
||||
enableSort={Boolean(upload)}
|
||||
modifySearchQuery={modifySearchParams}
|
||||
handleSortChange={handleSortChange}
|
||||
handleWhereChange={handleWhereChange}
|
||||
/>
|
||||
{!data.docs && (
|
||||
<StaggeredShimmers
|
||||
className={[
|
||||
`${baseClass}__shimmer`,
|
||||
upload ? `${baseClass}__shimmer--uploads` : `${baseClass}__shimmer--rows`,
|
||||
].filter(Boolean).join(' ')}
|
||||
count={6}
|
||||
width={upload ? 'unset' : '100%'}
|
||||
<SelectionProvider
|
||||
docs={data.docs}
|
||||
totalDocs={data.totalDocs}
|
||||
>
|
||||
{!disableEyebrow && (
|
||||
<Eyebrow />
|
||||
)}
|
||||
<Gutter className={`${baseClass}__wrap`}>
|
||||
<header className={`${baseClass}__header`}>
|
||||
{customHeader && customHeader}
|
||||
{!customHeader && (
|
||||
<Fragment>
|
||||
<h1>
|
||||
{getTranslation(pluralLabel, i18n)}
|
||||
</h1>
|
||||
{hasCreatePermission && (
|
||||
<Pill to={newDocumentURL}>
|
||||
{t('createNew')}
|
||||
</Pill>
|
||||
)}
|
||||
{!smallBreak && (
|
||||
<ListSelection
|
||||
label={getTranslation(collection.labels.plural, i18n)}
|
||||
/>
|
||||
)}
|
||||
{description && (
|
||||
<div className={`${baseClass}__sub-header`}>
|
||||
<ViewDescription description={description} />
|
||||
</div>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
</header>
|
||||
<ListControls
|
||||
collection={collection}
|
||||
modifySearchQuery={modifySearchParams}
|
||||
handleSortChange={handleSortChange}
|
||||
handleWhereChange={handleWhereChange}
|
||||
resetParams={resetParams}
|
||||
/>
|
||||
)}
|
||||
{(data.docs && data.docs.length > 0) && (
|
||||
<React.Fragment>
|
||||
{!upload && (
|
||||
<RelationshipProvider>
|
||||
<Table data={data.docs} />
|
||||
</RelationshipProvider>
|
||||
)}
|
||||
{upload && (
|
||||
<UploadGallery
|
||||
docs={data.docs}
|
||||
collection={collection}
|
||||
onCardClick={(doc) => {
|
||||
if (typeof onCardClick === 'function') onCardClick(doc);
|
||||
if (!disableCardLink) history.push(`${admin}/collections/${slug}/${doc.id}`);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
)}
|
||||
{data.docs && data.docs.length === 0 && (
|
||||
<div className={`${baseClass}__no-results`}>
|
||||
<p>
|
||||
{t('noResults', { label: getTranslation(pluralLabel, i18n) })}
|
||||
</p>
|
||||
{hasCreatePermission && newDocumentURL && (
|
||||
<Button
|
||||
el="link"
|
||||
to={newDocumentURL}
|
||||
>
|
||||
{t('createNewLabel', { label: getTranslation(singularLabel, i18n) })}
|
||||
</Button>
|
||||
{!data.docs && (
|
||||
<StaggeredShimmers
|
||||
className={[`${baseClass}__shimmer`, `${baseClass}__shimmer--rows`].join(' ')}
|
||||
count={6}
|
||||
/>
|
||||
)}
|
||||
{(data.docs && data.docs.length > 0) && (
|
||||
<RelationshipProvider>
|
||||
<Table data={data.docs} />
|
||||
</RelationshipProvider>
|
||||
)}
|
||||
{data.docs && data.docs.length === 0 && (
|
||||
<div className={`${baseClass}__no-results`}>
|
||||
<p>
|
||||
{t('noResults', { label: getTranslation(pluralLabel, i18n) })}
|
||||
</p>
|
||||
{hasCreatePermission && newDocumentURL && (
|
||||
<Button
|
||||
el="link"
|
||||
to={newDocumentURL}
|
||||
>
|
||||
{t('createNewLabel', { label: getTranslation(singularLabel, i18n) })}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className={`${baseClass}__page-controls`}>
|
||||
<Paginator
|
||||
limit={data.limit}
|
||||
totalPages={data.totalPages}
|
||||
page={data.page}
|
||||
hasPrevPage={data.hasPrevPage}
|
||||
hasNextPage={data.hasNextPage}
|
||||
prevPage={data.prevPage}
|
||||
nextPage={data.nextPage}
|
||||
numberOfNeighbors={1}
|
||||
disableHistoryChange={modifySearchParams === false}
|
||||
onChange={handlePageChange}
|
||||
/>
|
||||
{data?.totalDocs > 0 && (
|
||||
<Fragment>
|
||||
<div className={`${baseClass}__page-info`}>
|
||||
{(data.page * data.limit) - (data.limit - 1)}
|
||||
-
|
||||
{data.totalPages > 1 && data.totalPages !== data.page ? (data.limit * data.page) : data.totalDocs}
|
||||
{' '}
|
||||
{t('of')}
|
||||
{' '}
|
||||
{data.totalDocs}
|
||||
</div>
|
||||
<PerPage
|
||||
limits={collection?.admin?.pagination?.limits}
|
||||
limit={limit}
|
||||
modifySearchParams={modifySearchParams}
|
||||
handleChange={handlePerPageChange}
|
||||
resetPage={data.totalDocs <= data.pagingCounter}
|
||||
/>
|
||||
<div className={`${baseClass}__list-selection`}>
|
||||
{smallBreak && (
|
||||
<Fragment>
|
||||
<ListSelection
|
||||
label={getTranslation(collection.labels.plural, i18n)}
|
||||
/>
|
||||
<div className={`${baseClass}__list-selection-actions`}>
|
||||
<EditMany
|
||||
collection={collection}
|
||||
resetParams={resetParams}
|
||||
/>
|
||||
<PublishMany
|
||||
collection={collection}
|
||||
resetParams={resetParams}
|
||||
/>
|
||||
<UnpublishMany
|
||||
collection={collection}
|
||||
resetParams={resetParams}
|
||||
/>
|
||||
<DeleteMany
|
||||
collection={collection}
|
||||
resetParams={resetParams}
|
||||
/>
|
||||
</div>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className={`${baseClass}__page-controls`}>
|
||||
<Paginator
|
||||
limit={data.limit}
|
||||
totalPages={data.totalPages}
|
||||
page={data.page}
|
||||
hasPrevPage={data.hasPrevPage}
|
||||
hasNextPage={data.hasNextPage}
|
||||
prevPage={data.prevPage}
|
||||
nextPage={data.nextPage}
|
||||
numberOfNeighbors={1}
|
||||
disableHistoryChange={modifySearchParams === false}
|
||||
onChange={handlePageChange}
|
||||
/>
|
||||
{data?.totalDocs > 0 && (
|
||||
<Fragment>
|
||||
<div className={`${baseClass}__page-info`}>
|
||||
{(data.page * data.limit) - (data.limit - 1)}
|
||||
-
|
||||
{data.totalPages > 1 && data.totalPages !== data.page ? (data.limit * data.page) : data.totalDocs}
|
||||
{' '}
|
||||
{t('of')}
|
||||
{' '}
|
||||
{data.totalDocs}
|
||||
</div>
|
||||
<PerPage
|
||||
limits={collection?.admin?.pagination?.limits}
|
||||
limit={limit}
|
||||
modifySearchParams={modifySearchParams}
|
||||
handleChange={handlePerPageChange}
|
||||
resetPage={data.totalDocs <= data.pagingCounter}
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
</Gutter>
|
||||
</Gutter>
|
||||
</SelectionProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
@import '../../../../../scss/styles.scss';
|
||||
|
||||
.select-all {
|
||||
button {
|
||||
@extend %btn-reset;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
svg {
|
||||
opacity: .2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__input {
|
||||
@include formInput;
|
||||
padding: 0;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
width: $baseline;
|
||||
height: $baseline;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
import { SelectAllStatus, useSelection } from '../SelectionProvider';
|
||||
import Check from '../../../../icons/Check';
|
||||
import Line from '../../../../icons/Line';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'select-all';
|
||||
|
||||
const SelectAll: React.FC = () => {
|
||||
const { selectAll, toggleAll } = useSelection();
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => toggleAll()}
|
||||
>
|
||||
<span className={`${baseClass}__input`}>
|
||||
{ (selectAll === SelectAllStatus.AllInPage || selectAll === SelectAllStatus.AllAvailable) && (
|
||||
<Check />
|
||||
)}
|
||||
{ selectAll === SelectAllStatus.Some && (
|
||||
<Line />
|
||||
)}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectAll;
|
||||
@@ -0,0 +1,44 @@
|
||||
@import '../../../../../scss/styles.scss';
|
||||
|
||||
.select-row {
|
||||
button {
|
||||
@extend %btn-reset;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
svg {
|
||||
opacity: .2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__input {
|
||||
@include formInput;
|
||||
padding: 0;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
width: $baseline;
|
||||
height: $baseline;
|
||||
|
||||
svg {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&--checked {
|
||||
button {
|
||||
.select-row__input {
|
||||
svg {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
import { useSelection } from '../SelectionProvider';
|
||||
import Check from '../../../../icons/Check';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'select-row';
|
||||
|
||||
const SelectRow: React.FC<{ id: string | number }> = ({ id }) => {
|
||||
const { selected, setSelection } = useSelection();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={[
|
||||
baseClass,
|
||||
(selected[id]) && `${baseClass}--checked`,
|
||||
].filter(Boolean).join(' ')}
|
||||
key={id}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setSelection(id)}
|
||||
>
|
||||
<span className={`${baseClass}__input`}>
|
||||
<Check />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectRow;
|
||||
@@ -0,0 +1,157 @@
|
||||
import React, {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import queryString from 'qs';
|
||||
import { Where } from '../../../../../../types';
|
||||
|
||||
export enum SelectAllStatus {
|
||||
AllAvailable = 'allAvailable',
|
||||
AllInPage = 'allInPage',
|
||||
Some = 'some',
|
||||
None = 'none',
|
||||
}
|
||||
|
||||
type SelectionContext = {
|
||||
selected: Record<string | number, boolean>
|
||||
setSelection: (id: string | number) => void
|
||||
selectAll: SelectAllStatus
|
||||
toggleAll: (allAvailable?: boolean) => void
|
||||
totalDocs: number
|
||||
count: number
|
||||
getQueryParams: (additionalParams?: Where) => string
|
||||
}
|
||||
|
||||
const Context = createContext({} as SelectionContext);
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode
|
||||
docs: any[]
|
||||
totalDocs: number
|
||||
}
|
||||
export const SelectionProvider: React.FC<Props> = ({ children, docs = [], totalDocs }) => {
|
||||
const contextRef = useRef({} as SelectionContext);
|
||||
|
||||
const history = useHistory();
|
||||
const [selected, setSelected] = useState<SelectionContext['selected']>({});
|
||||
const [selectAll, setSelectAll] = useState<SelectAllStatus>(SelectAllStatus.None);
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
const toggleAll = useCallback((allAvailable = false) => {
|
||||
const rows = {};
|
||||
if (allAvailable) {
|
||||
setSelectAll(SelectAllStatus.AllAvailable);
|
||||
docs.forEach(({ id }) => {
|
||||
rows[id] = true;
|
||||
});
|
||||
} else if (selectAll === SelectAllStatus.AllAvailable || selectAll === SelectAllStatus.AllInPage) {
|
||||
setSelectAll(SelectAllStatus.None);
|
||||
docs.forEach(({ id }) => {
|
||||
rows[id] = false;
|
||||
});
|
||||
} else {
|
||||
docs.forEach(({ id }) => {
|
||||
rows[id] = selectAll !== SelectAllStatus.Some;
|
||||
});
|
||||
}
|
||||
setSelected(rows);
|
||||
}, [docs, selectAll]);
|
||||
|
||||
const setSelection = useCallback((id) => {
|
||||
const isSelected = !selected[id];
|
||||
const newSelected = {
|
||||
...selected,
|
||||
[id]: isSelected,
|
||||
};
|
||||
if (!isSelected) {
|
||||
setSelectAll(SelectAllStatus.Some);
|
||||
}
|
||||
setSelected(newSelected);
|
||||
}, [selected]);
|
||||
|
||||
const getQueryParams = useCallback((additionalParams?: Where): string => {
|
||||
let where: Where;
|
||||
if (selectAll === SelectAllStatus.AllAvailable) {
|
||||
const params = queryString.parse(history.location.search, { ignoreQueryPrefix: true }).where as Where;
|
||||
where = params || {
|
||||
id: { not_equals: '' },
|
||||
};
|
||||
} else {
|
||||
where = {
|
||||
id: {
|
||||
in: Object.keys(selected).filter((id) => selected[id]).map((id) => id),
|
||||
},
|
||||
};
|
||||
}
|
||||
if (additionalParams) {
|
||||
where = {
|
||||
and: [
|
||||
{ ...additionalParams },
|
||||
where,
|
||||
],
|
||||
};
|
||||
}
|
||||
return queryString.stringify({
|
||||
where,
|
||||
}, { addQueryPrefix: true });
|
||||
}, [history.location.search, selectAll, selected]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectAll === SelectAllStatus.AllAvailable) {
|
||||
return;
|
||||
}
|
||||
let some = false;
|
||||
let all = true;
|
||||
Object.values(selected).forEach((val) => {
|
||||
all = all && val;
|
||||
some = some || val;
|
||||
});
|
||||
|
||||
if (all) {
|
||||
setSelectAll(SelectAllStatus.AllInPage);
|
||||
} else if (some) {
|
||||
setSelectAll(SelectAllStatus.Some);
|
||||
} else {
|
||||
setSelectAll(SelectAllStatus.None);
|
||||
}
|
||||
}, [docs, selectAll, selected]);
|
||||
|
||||
useEffect(() => {
|
||||
const rows = {};
|
||||
if (docs.length) {
|
||||
docs.forEach(({ id }) => {
|
||||
rows[id] = false;
|
||||
});
|
||||
setSelected(rows);
|
||||
}
|
||||
setSelectAll(SelectAllStatus.None);
|
||||
}, [docs, history]);
|
||||
|
||||
useEffect(() => {
|
||||
const newCount = selectAll === SelectAllStatus.AllAvailable ? totalDocs : Object.keys(selected).filter((id) => selected[id]).length;
|
||||
setCount(newCount);
|
||||
}, [selectAll, selected, totalDocs]);
|
||||
|
||||
contextRef.current = {
|
||||
selectAll,
|
||||
toggleAll,
|
||||
selected,
|
||||
setSelection,
|
||||
totalDocs,
|
||||
count,
|
||||
getQueryParams,
|
||||
};
|
||||
|
||||
return (
|
||||
<Context.Provider value={contextRef.current}>
|
||||
{children}
|
||||
</Context.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useSelection = (): SelectionContext => useContext(Context);
|
||||
@@ -1,42 +1,70 @@
|
||||
import { TFunction } from 'react-i18next';
|
||||
import React from 'react';
|
||||
import { SanitizedCollectionConfig } from '../../../../../collections/config/types';
|
||||
import { Field, fieldAffectsData, fieldIsPresentationalOnly } from '../../../../../fields/config/types';
|
||||
import UploadCell from './Cell/field-types/Upload';
|
||||
import { Props } from './Cell/types';
|
||||
|
||||
const formatFields = (config: SanitizedCollectionConfig, t: TFunction): Field[] => {
|
||||
const hasID = config.fields.findIndex((field) => fieldAffectsData(field) && field.name === 'id') > -1;
|
||||
let fields: Field[] = config.fields.reduce((formatted, field) => {
|
||||
const fields: Field[] = config.fields.reduce((formatted, field) => {
|
||||
if (!fieldIsPresentationalOnly(field) && (field.hidden === true || field?.admin?.disabled === true)) {
|
||||
return formatted;
|
||||
}
|
||||
|
||||
if (config.upload && fieldAffectsData(field) && field.name === 'filename') {
|
||||
const Cell: React.FC<Props> = (props) => (
|
||||
<UploadCell
|
||||
collection={config}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
return [
|
||||
...formatted,
|
||||
{
|
||||
...field,
|
||||
admin: {
|
||||
...field.admin,
|
||||
components: {
|
||||
...field.admin?.components || {},
|
||||
Cell: field.admin?.components?.Cell || Cell,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
...formatted,
|
||||
field,
|
||||
];
|
||||
}, hasID ? [] : [{ name: 'id', label: 'ID', type: 'text' }]);
|
||||
}, hasID ? [] : [{
|
||||
name: 'id',
|
||||
label: 'ID',
|
||||
type: 'text',
|
||||
admin: {
|
||||
disableBulkEdit: true,
|
||||
},
|
||||
}]);
|
||||
|
||||
if (config.timestamps) {
|
||||
fields = fields.concat([
|
||||
fields.push(
|
||||
{
|
||||
name: 'createdAt',
|
||||
label: t('general:createdAt'),
|
||||
type: 'date',
|
||||
admin: {
|
||||
disableBulkEdit: true,
|
||||
},
|
||||
}, {
|
||||
name: 'updatedAt',
|
||||
label: t('general:updatedAt'),
|
||||
type: 'date',
|
||||
admin: {
|
||||
disableBulkEdit: true,
|
||||
},
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
if (config.upload) {
|
||||
fields = fields.concat([
|
||||
{
|
||||
name: 'filename',
|
||||
label: t('upload:fileName'),
|
||||
type: 'text',
|
||||
},
|
||||
]);
|
||||
);
|
||||
}
|
||||
|
||||
return fields;
|
||||
|
||||
@@ -37,6 +37,12 @@
|
||||
table {
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
|
||||
#heading-_select,
|
||||
.cell-_select {
|
||||
min-width: unset;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,31 +61,40 @@
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
&__shimmer {
|
||||
margin-top: base(1.75);
|
||||
}
|
||||
&__list-selection {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
padding: base(.75) 0;
|
||||
width: 100%;
|
||||
background-color: var(--theme-bg);
|
||||
|
||||
&__shimmer--rows {
|
||||
>div {
|
||||
margin-top: 8px;
|
||||
.btn {
|
||||
margin: 0 0 0 base(.5);
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: var(--theme-elevation-100);
|
||||
cursor: pointer;
|
||||
padding: 0 base(.25);
|
||||
border-radius: $style-radius-s;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--theme-elevation-200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__shimmer--uploads {
|
||||
// match upload cards
|
||||
margin: base(2) -#{base(.5)};
|
||||
width: calc(100% + #{$baseline});
|
||||
&__list-selection-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: base(.25);
|
||||
}
|
||||
|
||||
&__shimmer {
|
||||
margin-top: base(1.75);
|
||||
width: 100%;
|
||||
>div {
|
||||
min-width: 0;
|
||||
width: calc(16.66%);
|
||||
|
||||
>div {
|
||||
margin: base(.5);
|
||||
padding-bottom: 110%;
|
||||
}
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,19 +126,9 @@
|
||||
width: 100%;
|
||||
margin-bottom: $baseline;
|
||||
}
|
||||
|
||||
&__shimmer--uploads {
|
||||
>div {
|
||||
width: 33.33%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include small-break {
|
||||
&__shimmer--uploads {
|
||||
>div {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
margin-bottom: base(3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import queryString from 'qs';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -9,10 +10,11 @@ import DefaultList from './Default';
|
||||
import RenderCustomComponent from '../../../utilities/RenderCustomComponent';
|
||||
import { useStepNav } from '../../../elements/StepNav';
|
||||
import formatFields from './formatFields';
|
||||
import { ListIndexProps, ListPreferences } from './types';
|
||||
import { Props, ListIndexProps, ListPreferences } from './types';
|
||||
import { usePreferences } from '../../../utilities/Preferences';
|
||||
import { useSearchParams } from '../../../utilities/SearchParams';
|
||||
import { Field } from '../../../../../fields/config/types';
|
||||
import { TableColumnsProvider } from '../../../elements/TableColumns';
|
||||
import type { Field } from '../../../../../fields/config/types';
|
||||
|
||||
const ListView: React.FC<ListIndexProps> = (props) => {
|
||||
const {
|
||||
@@ -48,7 +50,7 @@ const ListView: React.FC<ListIndexProps> = (props) => {
|
||||
const collectionPermissions = permissions?.collections?.[slug];
|
||||
const hasCreatePermission = collectionPermissions?.create?.permission;
|
||||
const newDocumentURL = `${admin}/collections/${slug}/create`;
|
||||
const [{ data }, { setParams: setFetchParams }] = usePayloadAPI(fetchURL, { initialParams: { page: 1 } });
|
||||
const [{ data }, { setParams }] = usePayloadAPI(fetchURL, { initialParams: { page: 1 } });
|
||||
|
||||
useEffect(() => {
|
||||
setStepNav([
|
||||
@@ -62,27 +64,31 @@ const ListView: React.FC<ListIndexProps> = (props) => {
|
||||
// Set up Payload REST API query params
|
||||
// /////////////////////////////////////
|
||||
|
||||
useEffect(() => {
|
||||
const params = {
|
||||
const resetParams = useCallback<Props['resetParams']>((overrides = {}) => {
|
||||
const params: Record<string, unknown> = {
|
||||
depth: 0,
|
||||
draft: 'true',
|
||||
page: undefined,
|
||||
sort: undefined,
|
||||
where: undefined,
|
||||
page: overrides?.page,
|
||||
sort: overrides?.sort,
|
||||
where: overrides?.where,
|
||||
limit,
|
||||
};
|
||||
|
||||
if (page) params.page = page;
|
||||
if (sort) params.sort = sort;
|
||||
if (where) params.where = where;
|
||||
params.invoke = uuid();
|
||||
|
||||
setParams(params);
|
||||
}, [limit, page, setParams, sort, where]);
|
||||
|
||||
useEffect(() => {
|
||||
// Performance enhancement
|
||||
// Setting the Fetch URL this way
|
||||
// prevents a double-fetch
|
||||
setFetchURL(`${serverURL}${api}/${slug}`);
|
||||
|
||||
setFetchParams(params);
|
||||
}, [setFetchParams, page, sort, where, collection, limit, serverURL, api, slug]);
|
||||
resetParams();
|
||||
}, [api, resetParams, serverURL, slug]);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Fetch preferences on first load
|
||||
@@ -128,18 +134,41 @@ const ListView: React.FC<ListIndexProps> = (props) => {
|
||||
})();
|
||||
}, [sort, limit, preferenceKey, setPreference, getPreference]);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Prevent going beyond page limit
|
||||
// /////////////////////////////////////
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.totalDocs && data.pagingCounter > data.totalDocs) {
|
||||
const params = queryString.parse(history.location.search, {
|
||||
ignoreQueryPrefix: true,
|
||||
depth: 0,
|
||||
});
|
||||
const newSearchQuery = queryString.stringify({
|
||||
...params,
|
||||
page: data.totalPages,
|
||||
}, { addQueryPrefix: true });
|
||||
history.replace({
|
||||
search: newSearchQuery,
|
||||
});
|
||||
}
|
||||
}, [data, history, resetParams]);
|
||||
|
||||
return (
|
||||
<RenderCustomComponent
|
||||
DefaultComponent={DefaultList}
|
||||
CustomComponent={CustomList}
|
||||
componentProps={{
|
||||
collection: { ...collection, fields },
|
||||
newDocumentURL,
|
||||
hasCreatePermission,
|
||||
data,
|
||||
limit: limit || defaultLimit,
|
||||
}}
|
||||
/>
|
||||
<TableColumnsProvider collection={collection}>
|
||||
<RenderCustomComponent
|
||||
DefaultComponent={DefaultList}
|
||||
CustomComponent={CustomList}
|
||||
componentProps={{
|
||||
collection: { ...collection, fields },
|
||||
newDocumentURL,
|
||||
hasCreatePermission,
|
||||
data,
|
||||
limit: limit || defaultLimit,
|
||||
resetParams,
|
||||
}}
|
||||
/>
|
||||
</TableColumnsProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Where } from '../../../../../types';
|
||||
import { SanitizedCollectionConfig } from '../../../../../collections/config/types';
|
||||
import { PaginatedDocs } from '../../../../../mongoose/types';
|
||||
import { Props as ListControlsProps } from '../../../elements/ListControls/types';
|
||||
@@ -11,15 +12,16 @@ export type Props = {
|
||||
setListControls: (controls: unknown) => void
|
||||
setSort: (sort: string) => void
|
||||
toggleColumn: (column: string) => void
|
||||
resetParams: (overrides?: { page?: number, sort?: string, where?: Where }) => void
|
||||
hasCreatePermission: boolean
|
||||
setLimit: (limit: number) => void
|
||||
limit: number
|
||||
disableEyebrow?: boolean
|
||||
modifySearchParams?: boolean
|
||||
onCardClick?: (doc: any) => void
|
||||
disableCardLink?: boolean
|
||||
handleSortChange?: ListControlsProps['handleSortChange']
|
||||
handleWhereChange?: ListControlsProps['handleWhereChange']
|
||||
handleDelete?: () => void
|
||||
handlePageChange?: PaginatorProps['onChange']
|
||||
handlePerPageChange?: PerPageProps['handleChange']
|
||||
onCreateNewClick?: () => void
|
||||
|
||||
@@ -16,9 +16,11 @@ import findVersionByID from './requestHandlers/findVersionByID';
|
||||
import restoreVersion from './requestHandlers/restoreVersion';
|
||||
import deleteHandler from './requestHandlers/delete';
|
||||
import findByID from './requestHandlers/findByID';
|
||||
import update, { deprecatedUpdate } from './requestHandlers/update';
|
||||
import update from './requestHandlers/update';
|
||||
import updateByID, { deprecatedUpdate } from './requestHandlers/updateByID';
|
||||
import logoutHandler from '../auth/requestHandlers/logout';
|
||||
import docAccessRequestHandler from './requestHandlers/docAccess';
|
||||
import deleteByID from './requestHandlers/deleteByID';
|
||||
|
||||
const buildEndpoints = (collection: SanitizedCollectionConfig): Endpoint[] => {
|
||||
let { endpoints } = collection;
|
||||
@@ -131,10 +133,15 @@ const buildEndpoints = (collection: SanitizedCollectionConfig): Endpoint[] => {
|
||||
handler: deprecatedUpdate,
|
||||
},
|
||||
{
|
||||
path: '/:id',
|
||||
path: '/',
|
||||
method: 'patch',
|
||||
handler: update,
|
||||
},
|
||||
{
|
||||
path: '/:id',
|
||||
method: 'patch',
|
||||
handler: updateByID,
|
||||
},
|
||||
{
|
||||
path: '/:id',
|
||||
method: 'get',
|
||||
@@ -143,6 +150,11 @@ const buildEndpoints = (collection: SanitizedCollectionConfig): Endpoint[] => {
|
||||
{
|
||||
path: '/:id',
|
||||
method: 'delete',
|
||||
handler: deleteByID,
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
method: 'delete',
|
||||
handler: deleteHandler,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -9,6 +9,7 @@ import { PayloadRequest } from '../../express/types';
|
||||
import { IncomingAuthType, Auth } from '../../auth/types';
|
||||
import { IncomingUploadType, Upload } from '../../uploads/types';
|
||||
import { IncomingCollectionVersions, SanitizedCollectionVersions } from '../../versions/types';
|
||||
import { Config as GeneratedTypes } from '../../generated-types';
|
||||
|
||||
type Register<T = any> = (doc: T, password: string) => T;
|
||||
|
||||
@@ -101,13 +102,13 @@ export type AfterReadHook<T extends TypeWithID = any> = (args: {
|
||||
|
||||
export type BeforeDeleteHook = (args: {
|
||||
req: PayloadRequest;
|
||||
id: string;
|
||||
id: string | number;
|
||||
}) => any;
|
||||
|
||||
export type AfterDeleteHook<T extends TypeWithID = any> = (args: {
|
||||
doc: T;
|
||||
req: PayloadRequest;
|
||||
id: string;
|
||||
id: string | number;
|
||||
}) => any;
|
||||
|
||||
export type AfterErrorHook = (err: Error, res: unknown) => { response: any, status: number } | void;
|
||||
@@ -320,6 +321,14 @@ export type Collection = {
|
||||
}
|
||||
};
|
||||
|
||||
export type BulkOperationResult<TSlug extends keyof GeneratedTypes['collections']> = {
|
||||
docs: GeneratedTypes['collections'][TSlug][],
|
||||
errors: {
|
||||
message: string
|
||||
id: GeneratedTypes['collections'][TSlug]['id']
|
||||
}[]
|
||||
}
|
||||
|
||||
export type AuthCollection = {
|
||||
Model: AuthCollectionModel;
|
||||
config: SanitizedCollectionConfig;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Config as GeneratedTypes } from 'payload/generated-types';
|
||||
import { Response } from 'express';
|
||||
import { PayloadRequest } from '../../../express/types';
|
||||
import { Collection } from '../../config/types';
|
||||
import deleteOperation from '../../operations/delete';
|
||||
import deleteByID from '../../operations/deleteByID';
|
||||
|
||||
export type Resolver<TSlug extends keyof GeneratedTypes['collections']> = (
|
||||
_: unknown,
|
||||
@@ -31,7 +31,7 @@ export default function getDeleteResolver<TSlug extends keyof GeneratedTypes['co
|
||||
depth: 0,
|
||||
};
|
||||
|
||||
const result = await deleteOperation(options);
|
||||
const result = await deleteByID(options);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { Response } from 'express';
|
||||
import { Config as GeneratedTypes } from 'payload/generated-types';
|
||||
import { Collection } from '../../config/types';
|
||||
import update from '../../operations/update';
|
||||
import updateByID from '../../operations/updateByID';
|
||||
import { PayloadRequest } from '../../../express/types';
|
||||
|
||||
export type Resolver<TSlug extends keyof GeneratedTypes['collections']> = (_: unknown, args: {
|
||||
@@ -35,7 +35,7 @@ export default function updateResolver<TSlug extends keyof GeneratedTypes['colle
|
||||
autosave: args.autosave,
|
||||
};
|
||||
|
||||
const result = await update<TSlug>(options);
|
||||
const result = await updateByID<TSlug>(options);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import { Config as GeneratedTypes } from 'payload/generated-types';
|
||||
import httpStatus from 'http-status';
|
||||
import { AccessResult } from '../../config/types';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
|
||||
import { NotFound, Forbidden, ErrorDeletingFile } from '../../errors';
|
||||
import { APIError } from '../../errors';
|
||||
import executeAccess from '../../auth/executeAccess';
|
||||
import { BeforeOperationHook, Collection } from '../config/types';
|
||||
import { Document, Where } from '../../types';
|
||||
import { Where } from '../../types';
|
||||
import { hasWhereAccessResult } from '../../auth/types';
|
||||
import { FileData } from '../../uploads/types';
|
||||
import fileExists from '../../uploads/fileExists';
|
||||
import { afterRead } from '../../fields/hooks/afterRead';
|
||||
import { deleteCollectionVersions } from '../../versions/deleteCollectionVersions';
|
||||
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles';
|
||||
|
||||
export type Arguments = {
|
||||
depth?: number
|
||||
collection: Collection
|
||||
id: string
|
||||
where: Where
|
||||
req: PayloadRequest
|
||||
overrideAccess?: boolean
|
||||
showHiddenFields?: boolean
|
||||
@@ -25,7 +23,13 @@ export type Arguments = {
|
||||
|
||||
async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
incomingArgs: Arguments,
|
||||
): Promise<GeneratedTypes['collections'][TSlug]> {
|
||||
): Promise<{
|
||||
docs: GeneratedTypes['collections'][TSlug][],
|
||||
errors: {
|
||||
message: string
|
||||
id: GeneratedTypes['collections'][TSlug]['id']
|
||||
}[]
|
||||
}> {
|
||||
let args = incomingArgs;
|
||||
|
||||
// /////////////////////////////////////
|
||||
@@ -47,7 +51,7 @@ async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']
|
||||
Model,
|
||||
config: collectionConfig,
|
||||
},
|
||||
id,
|
||||
where,
|
||||
req,
|
||||
req: {
|
||||
t,
|
||||
@@ -62,166 +66,173 @@ async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']
|
||||
showHiddenFields,
|
||||
} = args;
|
||||
|
||||
if (!where) {
|
||||
throw new APIError('Missing \'where\' query of documents to delete.', httpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Access
|
||||
// /////////////////////////////////////
|
||||
|
||||
const accessResults = !overrideAccess ? await executeAccess({ req, id }, collectionConfig.access.delete) : true;
|
||||
const hasWhereAccess = hasWhereAccessResult(accessResults);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeDelete - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.beforeDelete.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
return hook({
|
||||
req,
|
||||
id,
|
||||
});
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Retrieve document
|
||||
// /////////////////////////////////////
|
||||
|
||||
const queryToBuild: {
|
||||
where: Where
|
||||
} = {
|
||||
const queryToBuild: { where?: Where } = {
|
||||
where: {
|
||||
and: [
|
||||
{
|
||||
id: {
|
||||
equals: id,
|
||||
},
|
||||
},
|
||||
],
|
||||
and: [],
|
||||
},
|
||||
};
|
||||
|
||||
if (hasWhereAccessResult(accessResults)) {
|
||||
(queryToBuild.where.and as Where[]).push(accessResults);
|
||||
if (where) {
|
||||
queryToBuild.where = {
|
||||
and: [],
|
||||
...where,
|
||||
};
|
||||
|
||||
if (Array.isArray(where.AND)) {
|
||||
queryToBuild.where.and = [
|
||||
...queryToBuild.where.and,
|
||||
...where.AND,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
let accessResult: AccessResult;
|
||||
|
||||
if (!overrideAccess) {
|
||||
accessResult = await executeAccess({ req }, collectionConfig.access.delete);
|
||||
|
||||
if (hasWhereAccessResult(accessResult)) {
|
||||
queryToBuild.where.and.push(accessResult);
|
||||
}
|
||||
}
|
||||
|
||||
const query = await Model.buildQuery(queryToBuild, locale);
|
||||
|
||||
const docToDelete = await Model.findOne(query);
|
||||
|
||||
if (!docToDelete && !hasWhereAccess) throw new NotFound(t);
|
||||
if (!docToDelete && hasWhereAccess) throw new Forbidden(t);
|
||||
|
||||
const resultToDelete = docToDelete.toJSON({ virtuals: true });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete any associated files
|
||||
// Retrieve documents
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (collectionConfig.upload) {
|
||||
const { staticDir } = collectionConfig.upload;
|
||||
const docs = await Model.find(query, {}, { lean: true });
|
||||
|
||||
const staticPath = path.resolve(config.paths.configDir, staticDir);
|
||||
const errors = [];
|
||||
|
||||
const fileToDelete = `${staticPath}/${resultToDelete.filename}`;
|
||||
/* eslint-disable no-param-reassign */
|
||||
const promises = docs.map(async (doc) => {
|
||||
let result;
|
||||
|
||||
if (await fileExists(fileToDelete)) {
|
||||
fs.unlink(fileToDelete, (err) => {
|
||||
if (err) {
|
||||
throw new ErrorDeletingFile(t);
|
||||
}
|
||||
// custom id type reset
|
||||
doc.id = doc._id;
|
||||
doc = JSON.stringify(doc);
|
||||
doc = JSON.parse(doc);
|
||||
doc = sanitizeInternalFields(doc);
|
||||
|
||||
const { id } = doc;
|
||||
|
||||
try {
|
||||
// /////////////////////////////////////
|
||||
// beforeDelete - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.beforeDelete.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
return hook({
|
||||
req,
|
||||
id,
|
||||
});
|
||||
}, Promise.resolve());
|
||||
|
||||
await deleteAssociatedFiles({ config, collectionConfig, doc, t, overrideDelete: true });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete document
|
||||
// /////////////////////////////////////
|
||||
|
||||
await Model.deleteOne({ _id: id }, { lean: true });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete versions
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (collectionConfig.versions) {
|
||||
deleteCollectionVersions({
|
||||
payload,
|
||||
id,
|
||||
slug: collectionConfig.slug,
|
||||
});
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterDelete - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterDelete.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({
|
||||
req,
|
||||
id,
|
||||
doc,
|
||||
}) || doc;
|
||||
}, Promise.resolve());
|
||||
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
result = await afterRead({
|
||||
depth,
|
||||
doc: result || doc,
|
||||
entityConfig: collectionConfig,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({
|
||||
req,
|
||||
doc: result || doc,
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 8. Return results
|
||||
// /////////////////////////////////////
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
errors.push({
|
||||
message: error.message,
|
||||
id: doc.id,
|
||||
});
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
if (resultToDelete.sizes) {
|
||||
Object.values(resultToDelete.sizes).forEach(async (size: FileData) => {
|
||||
const sizeToDelete = `${staticPath}/${size.filename}`;
|
||||
if (await fileExists(sizeToDelete)) {
|
||||
fs.unlink(sizeToDelete, (err) => {
|
||||
if (err) {
|
||||
throw new ErrorDeletingFile(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete document
|
||||
// /////////////////////////////////////
|
||||
|
||||
const doc = await Model.findOneAndDelete({ _id: id });
|
||||
|
||||
let result: Document = doc.toJSON({ virtuals: true });
|
||||
|
||||
// custom id type reset
|
||||
result.id = result._id;
|
||||
result = JSON.stringify(result);
|
||||
result = JSON.parse(result);
|
||||
result = sanitizeInternalFields(result);
|
||||
const awaitedDocs = await Promise.all(promises);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete Preferences
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (collectionConfig.auth) {
|
||||
await preferences.Model.deleteMany({ user: id, userCollection: collectionConfig.slug });
|
||||
}
|
||||
await preferences.Model.deleteMany({ key: `collection-${collectionConfig.slug}-${id}` });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete versions
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (collectionConfig.versions) {
|
||||
deleteCollectionVersions({
|
||||
payload,
|
||||
id,
|
||||
slug: collectionConfig.slug,
|
||||
preferences.Model.deleteMany({
|
||||
user: { in: docs.map(({ id }) => id) },
|
||||
userCollection: collectionConfig.slug,
|
||||
});
|
||||
}
|
||||
preferences.Model.deleteMany({ key: { in: docs.map(({ id }) => `collection-${collectionConfig.slug}-${id}`) } });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterDelete - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterDelete.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({ req, id, doc: result }) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
result = await afterRead({
|
||||
depth,
|
||||
doc: result,
|
||||
entityConfig: collectionConfig,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({
|
||||
req,
|
||||
doc: result,
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 8. Return results
|
||||
// /////////////////////////////////////
|
||||
|
||||
return result;
|
||||
return {
|
||||
docs: awaitedDocs.filter(Boolean),
|
||||
errors,
|
||||
};
|
||||
}
|
||||
|
||||
export default deleteOperation;
|
||||
|
||||
191
src/collections/operations/deleteByID.ts
Normal file
191
src/collections/operations/deleteByID.ts
Normal file
@@ -0,0 +1,191 @@
|
||||
import { Config as GeneratedTypes } from 'payload/generated-types';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
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 { hasWhereAccessResult } from '../../auth/types';
|
||||
import { afterRead } from '../../fields/hooks/afterRead';
|
||||
import { deleteCollectionVersions } from '../../versions/deleteCollectionVersions';
|
||||
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles';
|
||||
|
||||
export type Arguments = {
|
||||
depth?: number
|
||||
collection: Collection
|
||||
id: string | number
|
||||
req: PayloadRequest
|
||||
overrideAccess?: boolean
|
||||
showHiddenFields?: boolean
|
||||
}
|
||||
|
||||
async function deleteByID<TSlug extends keyof GeneratedTypes['collections']>(incomingArgs: Arguments): Promise<Document> {
|
||||
let args = incomingArgs;
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeOperation - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook | Promise<void>, hook: BeforeOperationHook) => {
|
||||
await priorHook;
|
||||
|
||||
args = (await hook({
|
||||
args,
|
||||
operation: 'delete',
|
||||
})) || args;
|
||||
}, Promise.resolve());
|
||||
|
||||
const {
|
||||
depth,
|
||||
collection: {
|
||||
Model,
|
||||
config: collectionConfig,
|
||||
},
|
||||
id,
|
||||
req,
|
||||
req: {
|
||||
t,
|
||||
locale,
|
||||
payload,
|
||||
payload: {
|
||||
config,
|
||||
preferences,
|
||||
},
|
||||
},
|
||||
overrideAccess,
|
||||
showHiddenFields,
|
||||
} = args;
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Access
|
||||
// /////////////////////////////////////
|
||||
|
||||
const accessResults = !overrideAccess ? await executeAccess({ req, id }, collectionConfig.access.delete) : true;
|
||||
const hasWhereAccess = hasWhereAccessResult(accessResults);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeDelete - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.beforeDelete.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
return hook({
|
||||
req,
|
||||
id,
|
||||
});
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Retrieve document
|
||||
// /////////////////////////////////////
|
||||
|
||||
const queryToBuild: {
|
||||
where: Where
|
||||
} = {
|
||||
where: {
|
||||
and: [
|
||||
{
|
||||
id: {
|
||||
equals: id,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
if (hasWhereAccessResult(accessResults)) {
|
||||
(queryToBuild.where.and as Where[]).push(accessResults);
|
||||
}
|
||||
|
||||
const query = await Model.buildQuery(queryToBuild, locale);
|
||||
|
||||
const docToDelete = await Model.findOne(query);
|
||||
|
||||
if (!docToDelete && !hasWhereAccess) throw new NotFound(t);
|
||||
if (!docToDelete && hasWhereAccess) throw new Forbidden(t);
|
||||
|
||||
const resultToDelete = docToDelete.toJSON({ virtuals: true });
|
||||
|
||||
await deleteAssociatedFiles({ config, collectionConfig, doc: resultToDelete, t, overrideDelete: true });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete document
|
||||
// /////////////////////////////////////
|
||||
|
||||
const doc = await Model.findOneAndDelete({ _id: id });
|
||||
|
||||
let result: Document = doc.toJSON({ virtuals: true });
|
||||
|
||||
// custom id type reset
|
||||
result.id = result._id;
|
||||
result = JSON.stringify(result);
|
||||
result = JSON.parse(result);
|
||||
result = sanitizeInternalFields(result);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete Preferences
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (collectionConfig.auth) {
|
||||
await preferences.Model.deleteMany({ user: id, userCollection: collectionConfig.slug });
|
||||
}
|
||||
await preferences.Model.deleteMany({ key: `collection-${collectionConfig.slug}-${id}` });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete versions
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (collectionConfig.versions) {
|
||||
deleteCollectionVersions({
|
||||
payload,
|
||||
id,
|
||||
slug: collectionConfig.slug,
|
||||
});
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterDelete - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterDelete.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({ req, id, doc: result }) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
result = await afterRead({
|
||||
depth,
|
||||
doc: result,
|
||||
entityConfig: collectionConfig,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({
|
||||
req,
|
||||
doc: result,
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 8. Return results
|
||||
// /////////////////////////////////////
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export default deleteByID;
|
||||
@@ -1,15 +1,17 @@
|
||||
import { Config as GeneratedTypes } from 'payload/generated-types';
|
||||
import { Document } from '../../../types';
|
||||
import { Config as GeneratedTypes } from '../../../generated-types';
|
||||
import { Document, Where } from '../../../types';
|
||||
import { PayloadRequest } from '../../../express/types';
|
||||
import { Payload } from '../../../payload';
|
||||
import deleteOperation from '../delete';
|
||||
import deleteByID from '../deleteByID';
|
||||
import { getDataLoader } from '../../dataloader';
|
||||
import i18n from '../../../translations/init';
|
||||
import { APIError } from '../../../errors';
|
||||
import { BulkOperationResult } from '../../config/types';
|
||||
|
||||
export type Options<T extends keyof GeneratedTypes['collections']> = {
|
||||
export type BaseOptions<T extends keyof GeneratedTypes['collections']> = {
|
||||
collection: T
|
||||
id: string
|
||||
id: string | number
|
||||
depth?: number
|
||||
locale?: string
|
||||
fallbackLocale?: string
|
||||
@@ -18,14 +20,26 @@ export type Options<T extends keyof GeneratedTypes['collections']> = {
|
||||
showHiddenFields?: boolean
|
||||
}
|
||||
|
||||
export default async function deleteLocal<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
payload: Payload,
|
||||
options: Options<TSlug>,
|
||||
): Promise<GeneratedTypes['collections'][TSlug]> {
|
||||
export type ByIDOptions<T extends keyof GeneratedTypes['collections']> = BaseOptions<T> & {
|
||||
where?: never
|
||||
}
|
||||
|
||||
export type ManyOptions<T extends keyof GeneratedTypes['collections']> = BaseOptions<T> & {
|
||||
where: Where
|
||||
id?: never
|
||||
}
|
||||
|
||||
export type Options<TSlug extends keyof GeneratedTypes['collections']> = ByIDOptions<TSlug> | ManyOptions<TSlug>
|
||||
|
||||
async function deleteLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: ByIDOptions<TSlug>): Promise<GeneratedTypes['collections'][TSlug]>
|
||||
async function deleteLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: ManyOptions<TSlug>): Promise<BulkOperationResult<TSlug>>
|
||||
async function deleteLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: Options<TSlug>): Promise<GeneratedTypes['collections'][TSlug] | BulkOperationResult<TSlug>>
|
||||
async function deleteLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: Options<TSlug>): Promise<GeneratedTypes['collections'][TSlug] | BulkOperationResult<TSlug>> {
|
||||
const {
|
||||
collection: collectionSlug,
|
||||
depth,
|
||||
id,
|
||||
where,
|
||||
locale = null,
|
||||
fallbackLocale = null,
|
||||
user,
|
||||
@@ -53,12 +67,20 @@ export default async function deleteLocal<TSlug extends keyof GeneratedTypes['co
|
||||
if (!req.t) req.t = req.i18n.t;
|
||||
if (!req.payloadDataLoader) req.payloadDataLoader = getDataLoader(req);
|
||||
|
||||
return deleteOperation<TSlug>({
|
||||
const args = {
|
||||
depth,
|
||||
id,
|
||||
where,
|
||||
collection,
|
||||
overrideAccess,
|
||||
showHiddenFields,
|
||||
req,
|
||||
});
|
||||
};
|
||||
|
||||
if (options.id) {
|
||||
return deleteByID<TSlug>(args);
|
||||
}
|
||||
return deleteOperation<TSlug>(args);
|
||||
}
|
||||
|
||||
export default deleteLocal;
|
||||
|
||||
@@ -1,18 +1,32 @@
|
||||
import { Config as GeneratedTypes } from 'payload/generated-types';
|
||||
import find from './find';
|
||||
import findByID from './findByID';
|
||||
import create from './create';
|
||||
import update from './update';
|
||||
import localDelete from './delete';
|
||||
import update, { ByIDOptions as UpdateByIDOptions, ManyOptions as UpdateManyOptions, Options as UpdateOptions } from './update';
|
||||
import deleteLocal, { ByIDOptions as DeleteByIDOptions, ManyOptions as DeleteManyOptions, Options as DeleteOptions } from './delete';
|
||||
import auth from '../../../auth/operations/local';
|
||||
import findVersionByID from './findVersionByID';
|
||||
import findVersions from './findVersions';
|
||||
import restoreVersion from './restoreVersion';
|
||||
import { BulkOperationResult } from '../../config/types';
|
||||
|
||||
async function localUpdate <T extends keyof GeneratedTypes['collections']>(options: UpdateByIDOptions<T>): Promise<GeneratedTypes['collections'][T]>
|
||||
async function localUpdate <T extends keyof GeneratedTypes['collections']>(options: UpdateManyOptions<T>): Promise<BulkOperationResult<T>>
|
||||
async function localUpdate <T extends keyof GeneratedTypes['collections']>(options: UpdateOptions<T>): Promise<GeneratedTypes['collections'][T] | BulkOperationResult<T>> {
|
||||
return update<T>(this, options);
|
||||
}
|
||||
|
||||
async function localDelete <T extends keyof GeneratedTypes['collections']>(options: DeleteByIDOptions<T>): Promise<GeneratedTypes['collections'][T]>
|
||||
async function localDelete <T extends keyof GeneratedTypes['collections']>(options: DeleteManyOptions<T>): Promise<BulkOperationResult<T>>
|
||||
async function localDelete <T extends keyof GeneratedTypes['collections']>(options: DeleteOptions<T>): Promise<GeneratedTypes['collections'][T] | BulkOperationResult<T>> {
|
||||
return deleteLocal<T>(this, options);
|
||||
}
|
||||
|
||||
export default {
|
||||
find,
|
||||
findByID,
|
||||
create,
|
||||
update,
|
||||
update: localUpdate,
|
||||
localDelete,
|
||||
auth,
|
||||
findVersionByID,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Config as GeneratedTypes } from 'payload/generated-types';
|
||||
import { Payload } from '../../../payload';
|
||||
import { Document } from '../../../types';
|
||||
import { Document, Where } from '../../../types';
|
||||
import getFileByPath from '../../../uploads/getFileByPath';
|
||||
import update from '../update';
|
||||
import { PayloadRequest } from '../../../express/types';
|
||||
@@ -8,10 +8,11 @@ import { getDataLoader } from '../../dataloader';
|
||||
import { File } from '../../../uploads/types';
|
||||
import i18nInit from '../../../translations/init';
|
||||
import { APIError } from '../../../errors';
|
||||
import updateByID from '../updateByID';
|
||||
import { BulkOperationResult } from '../../config/types';
|
||||
|
||||
export type Options<TSlug extends keyof GeneratedTypes['collections']> = {
|
||||
export type BaseOptions<TSlug extends keyof GeneratedTypes['collections']> = {
|
||||
collection: TSlug
|
||||
id: string | number
|
||||
data: Partial<GeneratedTypes['collections'][TSlug]>
|
||||
depth?: number
|
||||
locale?: string
|
||||
@@ -26,17 +27,28 @@ export type Options<TSlug extends keyof GeneratedTypes['collections']> = {
|
||||
autosave?: boolean
|
||||
}
|
||||
|
||||
export default async function updateLocal<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
payload: Payload,
|
||||
options: Options<TSlug>,
|
||||
): Promise<GeneratedTypes['collections'][TSlug]> {
|
||||
export type ByIDOptions<TSlug extends keyof GeneratedTypes['collections']> = BaseOptions<TSlug> & {
|
||||
id: string | number
|
||||
where?: never
|
||||
}
|
||||
|
||||
export type ManyOptions<TSlug extends keyof GeneratedTypes['collections']> = BaseOptions<TSlug> & {
|
||||
where: Where
|
||||
id?: never
|
||||
}
|
||||
|
||||
export type Options<TSlug extends keyof GeneratedTypes['collections']> = ByIDOptions<TSlug> | ManyOptions<TSlug>
|
||||
|
||||
async function updateLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: ByIDOptions<TSlug>): Promise<GeneratedTypes['collections'][TSlug]>
|
||||
async function updateLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: ManyOptions<TSlug>): Promise<BulkOperationResult<TSlug>>
|
||||
async function updateLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: Options<TSlug>): Promise<GeneratedTypes['collections'][TSlug] | BulkOperationResult<TSlug>>
|
||||
async function updateLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: Options<TSlug>): Promise<GeneratedTypes['collections'][TSlug] | BulkOperationResult<TSlug>> {
|
||||
const {
|
||||
collection: collectionSlug,
|
||||
depth,
|
||||
locale = null,
|
||||
fallbackLocale = null,
|
||||
data,
|
||||
id,
|
||||
user,
|
||||
overrideAccess = true,
|
||||
showHiddenFields,
|
||||
@@ -45,6 +57,8 @@ export default async function updateLocal<TSlug extends keyof GeneratedTypes['co
|
||||
overwriteExistingFiles = false,
|
||||
draft,
|
||||
autosave,
|
||||
id,
|
||||
where,
|
||||
} = options;
|
||||
|
||||
const collection = payload.collections[collectionSlug];
|
||||
@@ -76,14 +90,20 @@ export default async function updateLocal<TSlug extends keyof GeneratedTypes['co
|
||||
data,
|
||||
collection,
|
||||
overrideAccess,
|
||||
id,
|
||||
showHiddenFields,
|
||||
overwriteExistingFiles,
|
||||
draft,
|
||||
autosave,
|
||||
payload,
|
||||
req,
|
||||
id,
|
||||
where,
|
||||
};
|
||||
|
||||
if (options.id) {
|
||||
return updateByID<TSlug>(args);
|
||||
}
|
||||
return update<TSlug>(args);
|
||||
}
|
||||
|
||||
export default updateLocal;
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import fs from 'fs';
|
||||
import { promisify } from 'util';
|
||||
import path from 'path';
|
||||
import httpStatus from 'http-status';
|
||||
import { Config as GeneratedTypes } from 'payload/generated-types';
|
||||
import { Where, Document } from '../../types';
|
||||
import { Collection } from '../config/types';
|
||||
import { Document, Where } from '../../types';
|
||||
import { BulkOperationResult, Collection } from '../config/types';
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
|
||||
import executeAccess from '../../auth/executeAccess';
|
||||
import { NotFound, Forbidden, APIError, ValidationError, ErrorDeletingFile } from '../../errors';
|
||||
import { APIError, ValidationError } from '../../errors';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
import { hasWhereAccessResult } from '../../auth/types';
|
||||
import { saveVersion } from '../../versions/saveVersion';
|
||||
@@ -17,17 +14,15 @@ import { beforeValidate } from '../../fields/hooks/beforeValidate';
|
||||
import { afterChange } from '../../fields/hooks/afterChange';
|
||||
import { afterRead } from '../../fields/hooks/afterRead';
|
||||
import { generateFileData } from '../../uploads/generateFileData';
|
||||
import { getLatestCollectionVersion } from '../../versions/getLatestCollectionVersion';
|
||||
import { mapAsync } from '../../utilities/mapAsync';
|
||||
import fileExists from '../../uploads/fileExists';
|
||||
import { FileData } from '../../uploads/types';
|
||||
|
||||
const unlinkFile = promisify(fs.unlink);
|
||||
import { AccessResult } from '../../config/types';
|
||||
import { queryDrafts } from '../../versions/drafts/queryDrafts';
|
||||
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles';
|
||||
import { unlinkTempFiles } from '../../uploads/unlinkTempFiles';
|
||||
|
||||
export type Arguments<T extends { [field: string | number | symbol]: unknown }> = {
|
||||
collection: Collection
|
||||
req: PayloadRequest
|
||||
id: string | number
|
||||
where: Where
|
||||
data: Partial<T>
|
||||
depth?: number
|
||||
disableVerificationEmail?: boolean
|
||||
@@ -35,12 +30,10 @@ export type Arguments<T extends { [field: string | number | symbol]: unknown }>
|
||||
showHiddenFields?: boolean
|
||||
overwriteExistingFiles?: boolean
|
||||
draft?: boolean
|
||||
autosave?: boolean
|
||||
}
|
||||
|
||||
async function update<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
incomingArgs: Arguments<GeneratedTypes['collections'][TSlug]>,
|
||||
): Promise<GeneratedTypes['collections'][TSlug]> {
|
||||
): Promise<BulkOperationResult<TSlug>> {
|
||||
let args = incomingArgs;
|
||||
|
||||
// /////////////////////////////////////
|
||||
@@ -63,7 +56,7 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
Model,
|
||||
config: collectionConfig,
|
||||
},
|
||||
id,
|
||||
where,
|
||||
req,
|
||||
req: {
|
||||
t,
|
||||
@@ -77,77 +70,76 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
showHiddenFields,
|
||||
overwriteExistingFiles = false,
|
||||
draft: draftArg = false,
|
||||
autosave = false,
|
||||
} = args;
|
||||
|
||||
if (!id) {
|
||||
throw new APIError('Missing ID of document to update.', httpStatus.BAD_REQUEST);
|
||||
if (!where) {
|
||||
throw new APIError('Missing \'where\' query of documents to update.', httpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
let { data } = args;
|
||||
const { password } = data;
|
||||
const shouldSaveDraft = Boolean(draftArg && collectionConfig.versions.drafts);
|
||||
const shouldSavePassword = Boolean(password && collectionConfig.auth && !shouldSaveDraft);
|
||||
const lean = !shouldSavePassword;
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Access
|
||||
// /////////////////////////////////////
|
||||
|
||||
const accessResults = !overrideAccess ? await executeAccess({ req, id, data }, collectionConfig.access.update) : true;
|
||||
const hasWherePolicy = hasWhereAccessResult(accessResults);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Retrieve document
|
||||
// /////////////////////////////////////
|
||||
|
||||
const queryToBuild: { where: Where } = {
|
||||
const queryToBuild: { where?: Where } = {
|
||||
where: {
|
||||
and: [
|
||||
{
|
||||
id: {
|
||||
equals: id,
|
||||
},
|
||||
},
|
||||
],
|
||||
and: [],
|
||||
},
|
||||
};
|
||||
|
||||
if (hasWhereAccessResult(accessResults)) {
|
||||
(queryToBuild.where.and as Where[]).push(accessResults);
|
||||
if (where) {
|
||||
queryToBuild.where = {
|
||||
and: [],
|
||||
...where,
|
||||
};
|
||||
|
||||
if (Array.isArray(where.AND)) {
|
||||
queryToBuild.where.and = [
|
||||
...queryToBuild.where.and,
|
||||
...where.AND,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
let accessResult: AccessResult;
|
||||
|
||||
if (!overrideAccess) {
|
||||
accessResult = await executeAccess({ req }, collectionConfig.access.update);
|
||||
|
||||
if (hasWhereAccessResult(accessResult)) {
|
||||
queryToBuild.where.and.push(accessResult);
|
||||
}
|
||||
}
|
||||
|
||||
const query = await Model.buildQuery(queryToBuild, locale);
|
||||
|
||||
const doc = await getLatestCollectionVersion({
|
||||
payload,
|
||||
Model,
|
||||
config: collectionConfig,
|
||||
id,
|
||||
query,
|
||||
lean,
|
||||
});
|
||||
// /////////////////////////////////////
|
||||
// Retrieve documents
|
||||
// /////////////////////////////////////
|
||||
let docs;
|
||||
|
||||
if (!doc && !hasWherePolicy) throw new NotFound(t);
|
||||
if (!doc && hasWherePolicy) throw new Forbidden(t);
|
||||
|
||||
let docWithLocales: Document = JSON.stringify(lean ? doc : doc.toJSON({ virtuals: true }));
|
||||
docWithLocales = JSON.parse(docWithLocales);
|
||||
|
||||
const originalDoc = await afterRead({
|
||||
depth: 0,
|
||||
doc: docWithLocales,
|
||||
entityConfig: collectionConfig,
|
||||
req,
|
||||
overrideAccess: true,
|
||||
showHiddenFields: true,
|
||||
});
|
||||
if (collectionConfig.versions?.drafts && shouldSaveDraft) {
|
||||
docs = await queryDrafts<GeneratedTypes['collections'][TSlug]>({
|
||||
accessResult,
|
||||
collection,
|
||||
locale,
|
||||
payload,
|
||||
where: query,
|
||||
});
|
||||
} else {
|
||||
docs = await Model.find(query, {}, { lean: true });
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Generate data for all files and sizes
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { data: newFileData, files: filesToUpload } = await generateFileData({
|
||||
const {
|
||||
data: newFileData,
|
||||
files: filesToUpload,
|
||||
} = await generateFileData({
|
||||
config,
|
||||
collection,
|
||||
req,
|
||||
@@ -158,229 +150,217 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
|
||||
data = newFileData;
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeValidate - Fields
|
||||
// /////////////////////////////////////
|
||||
const errors = [];
|
||||
|
||||
data = await beforeValidate<GeneratedTypes['collections'][TSlug]>({
|
||||
data,
|
||||
doc: originalDoc,
|
||||
entityConfig: collectionConfig,
|
||||
id,
|
||||
operation: 'update',
|
||||
overrideAccess,
|
||||
req,
|
||||
});
|
||||
const promises = docs.map(async (doc) => {
|
||||
let docWithLocales: Document = JSON.stringify(doc);
|
||||
docWithLocales = JSON.parse(docWithLocales);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeValidate - Collection
|
||||
// /////////////////////////////////////
|
||||
const id = docWithLocales._id;
|
||||
|
||||
await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
data = (await hook({
|
||||
data,
|
||||
req,
|
||||
operation: 'update',
|
||||
originalDoc,
|
||||
})) || data;
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Write files to local storage
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (!collectionConfig.upload.disableLocalStorage) {
|
||||
await uploadFiles(payload, filesToUpload, t);
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeChange - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
data = (await hook({
|
||||
data,
|
||||
req,
|
||||
originalDoc,
|
||||
operation: 'update',
|
||||
})) || data;
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeChange - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
let result = await beforeChange<GeneratedTypes['collections'][TSlug]>({
|
||||
data,
|
||||
doc: originalDoc,
|
||||
docWithLocales,
|
||||
entityConfig: collectionConfig,
|
||||
id,
|
||||
operation: 'update',
|
||||
req,
|
||||
skipValidation: shouldSaveDraft || data._status === 'draft',
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Handle potential password update
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (shouldSavePassword) {
|
||||
await doc.setPassword(password);
|
||||
await doc.save();
|
||||
delete data.password;
|
||||
delete result.password;
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Update
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (!shouldSaveDraft) {
|
||||
try {
|
||||
result = await Model.findByIdAndUpdate(
|
||||
{ _id: id },
|
||||
result,
|
||||
{ new: true },
|
||||
);
|
||||
} catch (error) {
|
||||
// Handle uniqueness error from MongoDB
|
||||
throw error.code === 11000 && error.keyValue
|
||||
? new ValidationError([{ message: 'Value must be unique', field: Object.keys(error.keyValue)[0] }], t)
|
||||
: error;
|
||||
}
|
||||
}
|
||||
|
||||
result = JSON.parse(JSON.stringify(result));
|
||||
result.id = result._id as string | number;
|
||||
result = sanitizeInternalFields(result);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete any associated files
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (collectionConfig.upload && !overwriteExistingFiles && filesToUpload && filesToUpload.length > 0) {
|
||||
const { staticDir } = collectionConfig.upload;
|
||||
|
||||
const staticPath = path.resolve(config.paths.configDir, staticDir);
|
||||
|
||||
const fileToDelete = `${staticPath}/${doc.filename}`;
|
||||
|
||||
if (await fileExists(fileToDelete)) {
|
||||
fs.unlink(fileToDelete, (err) => {
|
||||
if (err) {
|
||||
throw new ErrorDeletingFile(t);
|
||||
}
|
||||
const originalDoc = await afterRead({
|
||||
depth: 0,
|
||||
doc: docWithLocales,
|
||||
entityConfig: collectionConfig,
|
||||
req,
|
||||
overrideAccess: true,
|
||||
showHiddenFields: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (doc.sizes) {
|
||||
Object.values(doc.sizes).forEach(async (size: FileData) => {
|
||||
const sizeToDelete = `${staticPath}/${size.filename}`;
|
||||
if (await fileExists(sizeToDelete)) {
|
||||
fs.unlink(sizeToDelete, (err) => {
|
||||
if (err) {
|
||||
throw new ErrorDeletingFile(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
await deleteAssociatedFiles({ config, collectionConfig, files: filesToUpload, doc: docWithLocales, t, overrideDelete: false });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeValidate - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
data = await beforeValidate<GeneratedTypes['collections'][TSlug]>({
|
||||
data,
|
||||
doc: originalDoc,
|
||||
entityConfig: collectionConfig,
|
||||
id,
|
||||
operation: 'update',
|
||||
overrideAccess,
|
||||
req,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Create version
|
||||
// /////////////////////////////////////
|
||||
// /////////////////////////////////////
|
||||
// beforeValidate - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (collectionConfig.versions) {
|
||||
result = await saveVersion({
|
||||
payload,
|
||||
collection: collectionConfig,
|
||||
req,
|
||||
docWithLocales: {
|
||||
...result,
|
||||
createdAt: docWithLocales.createdAt,
|
||||
},
|
||||
id,
|
||||
autosave,
|
||||
draft: shouldSaveDraft,
|
||||
});
|
||||
}
|
||||
await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Fields
|
||||
// /////////////////////////////////////
|
||||
data = (await hook({
|
||||
data,
|
||||
req,
|
||||
operation: 'update',
|
||||
originalDoc,
|
||||
})) || data;
|
||||
}, Promise.resolve());
|
||||
|
||||
result = await afterRead({
|
||||
depth,
|
||||
doc: result,
|
||||
entityConfig: collectionConfig,
|
||||
req,
|
||||
overrideAccess,
|
||||
showHiddenFields,
|
||||
});
|
||||
// /////////////////////////////////////
|
||||
// Write files to local storage
|
||||
// /////////////////////////////////////
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({
|
||||
req,
|
||||
doc: result,
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterChange - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
result = await afterChange<GeneratedTypes['collections'][TSlug]>({
|
||||
data,
|
||||
doc: result,
|
||||
previousDoc: originalDoc,
|
||||
entityConfig: collectionConfig,
|
||||
operation: 'update',
|
||||
req,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterChange - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({
|
||||
doc: result,
|
||||
previousDoc: originalDoc,
|
||||
req,
|
||||
operation: 'update',
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
// Remove temp files if enabled, as express-fileupload does not do this automatically
|
||||
if (config.upload?.useTempFiles && collectionConfig.upload) {
|
||||
const { files } = req;
|
||||
const fileArray = Array.isArray(files) ? files : [files];
|
||||
await mapAsync(fileArray, async ({ file }) => {
|
||||
// Still need this check because this will not be populated if using local API
|
||||
if (file.tempFilePath) {
|
||||
await unlinkFile(file.tempFilePath);
|
||||
if (!collectionConfig.upload.disableLocalStorage) {
|
||||
await uploadFiles(payload, filesToUpload, t);
|
||||
}
|
||||
});
|
||||
}
|
||||
// /////////////////////////////////////
|
||||
// Return results
|
||||
// /////////////////////////////////////
|
||||
|
||||
return result;
|
||||
// /////////////////////////////////////
|
||||
// beforeChange - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
data = (await hook({
|
||||
data,
|
||||
req,
|
||||
originalDoc,
|
||||
operation: 'update',
|
||||
})) || data;
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeChange - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
let result = await beforeChange<GeneratedTypes['collections'][TSlug]>({
|
||||
data,
|
||||
doc: originalDoc,
|
||||
docWithLocales,
|
||||
entityConfig: collectionConfig,
|
||||
id,
|
||||
operation: 'update',
|
||||
req,
|
||||
skipValidation: shouldSaveDraft || data._status === 'draft',
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Update
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (!shouldSaveDraft) {
|
||||
try {
|
||||
result = await Model.findByIdAndUpdate(
|
||||
{ _id: id },
|
||||
result,
|
||||
{ new: true },
|
||||
);
|
||||
} catch (error) {
|
||||
// Handle uniqueness error from MongoDB
|
||||
throw error.code === 11000 && error.keyValue
|
||||
? new ValidationError([{
|
||||
message: 'Value must be unique',
|
||||
field: Object.keys(error.keyValue)[0],
|
||||
}], t)
|
||||
: error;
|
||||
}
|
||||
}
|
||||
|
||||
result = JSON.parse(JSON.stringify(result));
|
||||
result.id = result._id as string | number;
|
||||
result = sanitizeInternalFields(result);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Create version
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (collectionConfig.versions) {
|
||||
result = await saveVersion({
|
||||
payload,
|
||||
collection: collectionConfig,
|
||||
req,
|
||||
docWithLocales: {
|
||||
...result,
|
||||
createdAt: docWithLocales.createdAt,
|
||||
},
|
||||
id,
|
||||
draft: shouldSaveDraft,
|
||||
});
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
result = await afterRead({
|
||||
depth,
|
||||
doc: result,
|
||||
entityConfig: collectionConfig,
|
||||
req,
|
||||
overrideAccess,
|
||||
showHiddenFields,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({
|
||||
req,
|
||||
doc: result,
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterChange - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
result = await afterChange<GeneratedTypes['collections'][TSlug]>({
|
||||
data,
|
||||
doc: result,
|
||||
previousDoc: originalDoc,
|
||||
entityConfig: collectionConfig,
|
||||
operation: 'update',
|
||||
req,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterChange - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({
|
||||
doc: result,
|
||||
previousDoc: originalDoc,
|
||||
req,
|
||||
operation: 'update',
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
await unlinkTempFiles({
|
||||
req,
|
||||
config,
|
||||
collectionConfig,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Return results
|
||||
// /////////////////////////////////////
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
errors.push({
|
||||
message: error.message,
|
||||
id,
|
||||
});
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
const awaitedDocs = await Promise.all(promises);
|
||||
|
||||
return {
|
||||
docs: awaitedDocs.filter(Boolean),
|
||||
errors,
|
||||
};
|
||||
}
|
||||
|
||||
export default update;
|
||||
|
||||
348
src/collections/operations/updateByID.ts
Normal file
348
src/collections/operations/updateByID.ts
Normal file
@@ -0,0 +1,348 @@
|
||||
import httpStatus from 'http-status';
|
||||
import { Config as GeneratedTypes } from 'payload/generated-types';
|
||||
import { Where, Document } from '../../types';
|
||||
import { Collection } from '../config/types';
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
|
||||
import executeAccess from '../../auth/executeAccess';
|
||||
import { NotFound, Forbidden, APIError, ValidationError } from '../../errors';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
import { hasWhereAccessResult } from '../../auth/types';
|
||||
import { saveVersion } from '../../versions/saveVersion';
|
||||
import { uploadFiles } from '../../uploads/uploadFiles';
|
||||
import { beforeChange } from '../../fields/hooks/beforeChange';
|
||||
import { beforeValidate } from '../../fields/hooks/beforeValidate';
|
||||
import { afterChange } from '../../fields/hooks/afterChange';
|
||||
import { afterRead } from '../../fields/hooks/afterRead';
|
||||
import { generateFileData } from '../../uploads/generateFileData';
|
||||
import { getLatestCollectionVersion } from '../../versions/getLatestCollectionVersion';
|
||||
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles';
|
||||
import { unlinkTempFiles } from '../../uploads/unlinkTempFiles';
|
||||
|
||||
export type Arguments<T extends { [field: string | number | symbol]: unknown }> = {
|
||||
collection: Collection
|
||||
req: PayloadRequest
|
||||
id: string | number
|
||||
data: Partial<T>
|
||||
depth?: number
|
||||
disableVerificationEmail?: boolean
|
||||
overrideAccess?: boolean
|
||||
showHiddenFields?: boolean
|
||||
overwriteExistingFiles?: boolean
|
||||
draft?: boolean
|
||||
autosave?: boolean
|
||||
}
|
||||
|
||||
async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
incomingArgs: Arguments<GeneratedTypes['collections'][TSlug]>,
|
||||
): Promise<GeneratedTypes['collections'][TSlug]> {
|
||||
let args = incomingArgs;
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeOperation - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
args = (await hook({
|
||||
args,
|
||||
operation: 'update',
|
||||
})) || args;
|
||||
}, Promise.resolve());
|
||||
|
||||
const {
|
||||
depth,
|
||||
collection,
|
||||
collection: {
|
||||
Model,
|
||||
config: collectionConfig,
|
||||
},
|
||||
id,
|
||||
req,
|
||||
req: {
|
||||
t,
|
||||
locale,
|
||||
payload,
|
||||
payload: {
|
||||
config,
|
||||
},
|
||||
},
|
||||
overrideAccess,
|
||||
showHiddenFields,
|
||||
overwriteExistingFiles = false,
|
||||
draft: draftArg = false,
|
||||
autosave = false,
|
||||
} = args;
|
||||
|
||||
if (!id) {
|
||||
throw new APIError('Missing ID of document to update.', httpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
let { data } = args;
|
||||
const { password } = data;
|
||||
const shouldSaveDraft = Boolean(draftArg && collectionConfig.versions.drafts);
|
||||
const shouldSavePassword = Boolean(password && collectionConfig.auth && !shouldSaveDraft);
|
||||
const lean = !shouldSavePassword;
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Access
|
||||
// /////////////////////////////////////
|
||||
|
||||
const accessResults = !overrideAccess ? await executeAccess({ req, id, data }, collectionConfig.access.update) : true;
|
||||
const hasWherePolicy = hasWhereAccessResult(accessResults);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Retrieve document
|
||||
// /////////////////////////////////////
|
||||
|
||||
const queryToBuild: { where: Where } = {
|
||||
where: {
|
||||
and: [
|
||||
{
|
||||
id: {
|
||||
equals: id,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
if (hasWhereAccessResult(accessResults)) {
|
||||
(queryToBuild.where.and as Where[]).push(accessResults);
|
||||
}
|
||||
|
||||
const query = await Model.buildQuery(queryToBuild, locale);
|
||||
|
||||
const doc = await getLatestCollectionVersion({
|
||||
payload,
|
||||
Model,
|
||||
config: collectionConfig,
|
||||
id,
|
||||
query,
|
||||
lean,
|
||||
});
|
||||
|
||||
if (!doc && !hasWherePolicy) throw new NotFound(t);
|
||||
if (!doc && hasWherePolicy) throw new Forbidden(t);
|
||||
|
||||
let docWithLocales: Document = JSON.stringify(lean ? doc : doc.toJSON({ virtuals: true }));
|
||||
docWithLocales = JSON.parse(docWithLocales);
|
||||
|
||||
const originalDoc = await afterRead({
|
||||
depth: 0,
|
||||
doc: docWithLocales,
|
||||
entityConfig: collectionConfig,
|
||||
req,
|
||||
overrideAccess: true,
|
||||
showHiddenFields: true,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Generate data for all files and sizes
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { data: newFileData, files: filesToUpload } = await generateFileData({
|
||||
config,
|
||||
collection,
|
||||
req,
|
||||
data,
|
||||
throwOnMissingFile: false,
|
||||
overwriteExistingFiles,
|
||||
});
|
||||
|
||||
data = newFileData;
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete any associated files
|
||||
// /////////////////////////////////////
|
||||
|
||||
await deleteAssociatedFiles({ config, collectionConfig, files: filesToUpload, doc, t, overrideDelete: false });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeValidate - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
data = await beforeValidate<GeneratedTypes['collections'][TSlug]>({
|
||||
data,
|
||||
doc: originalDoc,
|
||||
entityConfig: collectionConfig,
|
||||
id,
|
||||
operation: 'update',
|
||||
overrideAccess,
|
||||
req,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeValidate - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
data = (await hook({
|
||||
data,
|
||||
req,
|
||||
operation: 'update',
|
||||
originalDoc,
|
||||
})) || data;
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Write files to local storage
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (!collectionConfig.upload.disableLocalStorage) {
|
||||
await uploadFiles(payload, filesToUpload, t);
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeChange - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
data = (await hook({
|
||||
data,
|
||||
req,
|
||||
originalDoc,
|
||||
operation: 'update',
|
||||
})) || data;
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeChange - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
let result = await beforeChange<GeneratedTypes['collections'][TSlug]>({
|
||||
data,
|
||||
doc: originalDoc,
|
||||
docWithLocales,
|
||||
entityConfig: collectionConfig,
|
||||
id,
|
||||
operation: 'update',
|
||||
req,
|
||||
skipValidation: shouldSaveDraft || data._status === 'draft',
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Handle potential password update
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (shouldSavePassword) {
|
||||
await doc.setPassword(password);
|
||||
await doc.save();
|
||||
delete data.password;
|
||||
delete result.password;
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Update
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (!shouldSaveDraft) {
|
||||
try {
|
||||
result = await Model.findByIdAndUpdate(
|
||||
{ _id: id },
|
||||
result,
|
||||
{ new: true },
|
||||
);
|
||||
} catch (error) {
|
||||
// Handle uniqueness error from MongoDB
|
||||
throw error.code === 11000 && error.keyValue
|
||||
? new ValidationError([{ message: 'Value must be unique', field: Object.keys(error.keyValue)[0] }], t)
|
||||
: error;
|
||||
}
|
||||
}
|
||||
|
||||
result = JSON.parse(JSON.stringify(result));
|
||||
result.id = result._id as string | number;
|
||||
result = sanitizeInternalFields(result);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Create version
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (collectionConfig.versions) {
|
||||
result = await saveVersion({
|
||||
payload,
|
||||
collection: collectionConfig,
|
||||
req,
|
||||
docWithLocales: {
|
||||
...result,
|
||||
createdAt: docWithLocales.createdAt,
|
||||
},
|
||||
id,
|
||||
autosave,
|
||||
draft: shouldSaveDraft,
|
||||
});
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
result = await afterRead({
|
||||
depth,
|
||||
doc: result,
|
||||
entityConfig: collectionConfig,
|
||||
req,
|
||||
overrideAccess,
|
||||
showHiddenFields,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({
|
||||
req,
|
||||
doc: result,
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterChange - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
result = await afterChange<GeneratedTypes['collections'][TSlug]>({
|
||||
data,
|
||||
doc: result,
|
||||
previousDoc: originalDoc,
|
||||
entityConfig: collectionConfig,
|
||||
operation: 'update',
|
||||
req,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterChange - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({
|
||||
doc: result,
|
||||
previousDoc: originalDoc,
|
||||
req,
|
||||
operation: 'update',
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
await unlinkTempFiles({
|
||||
req,
|
||||
config,
|
||||
collectionConfig,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Return results
|
||||
// /////////////////////////////////////
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export default updateByID;
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Response, NextFunction } from 'express';
|
||||
import httpStatus from 'http-status';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
import { NotFound } from '../../errors';
|
||||
import { Document } from '../../types';
|
||||
import { Document, Where } from '../../types';
|
||||
import deleteOperation from '../operations/delete';
|
||||
import formatSuccessResponse from '../../express/responses/formatSuccess';
|
||||
import { getTranslation } from '../../utilities/getTranslation';
|
||||
|
||||
export type DeleteResult = {
|
||||
message: string;
|
||||
@@ -12,18 +13,36 @@ export type DeleteResult = {
|
||||
|
||||
export default async function deleteHandler(req: PayloadRequest, res: Response, next: NextFunction): Promise<Response<DeleteResult> | void> {
|
||||
try {
|
||||
const doc = await deleteOperation({
|
||||
const result = await deleteOperation({
|
||||
req,
|
||||
collection: req.collection,
|
||||
id: req.params.id,
|
||||
where: req.query.where as Where,
|
||||
depth: parseInt(String(req.query.depth), 10),
|
||||
});
|
||||
|
||||
if (!doc) {
|
||||
return res.status(httpStatus.NOT_FOUND).json(new NotFound(req.t));
|
||||
if (result.errors.length === 0) {
|
||||
const message = req.t('general:deletedCountSuccessfully', {
|
||||
count: result.docs.length,
|
||||
label: getTranslation(req.collection.config.labels[result.docs.length > 1 ? 'plural' : 'singular'], req.i18n),
|
||||
});
|
||||
|
||||
return res.status(httpStatus.OK).json({
|
||||
...formatSuccessResponse(message, 'message'),
|
||||
...result,
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(httpStatus.OK).send(doc);
|
||||
const total = result.docs.length + result.errors.length;
|
||||
const message = req.t('error:unableToDeleteCount', {
|
||||
count: result.errors.length,
|
||||
total,
|
||||
label: getTranslation(req.collection.config.labels[total > 1 ? 'plural' : 'singular'], req.i18n),
|
||||
});
|
||||
|
||||
return res.status(httpStatus.BAD_REQUEST).json({
|
||||
message,
|
||||
...result,
|
||||
});
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
|
||||
30
src/collections/requestHandlers/deleteByID.ts
Normal file
30
src/collections/requestHandlers/deleteByID.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Response, NextFunction } from 'express';
|
||||
import httpStatus from 'http-status';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
import { NotFound } from '../../errors';
|
||||
import { Document } from '../../types';
|
||||
import deleteByID from '../operations/deleteByID';
|
||||
|
||||
export type DeleteResult = {
|
||||
message: string;
|
||||
doc: Document;
|
||||
}
|
||||
|
||||
export default async function deleteByIDHandler(req: PayloadRequest, res: Response, next: NextFunction): Promise<Response<DeleteResult> | void> {
|
||||
try {
|
||||
const doc = await deleteByID({
|
||||
req,
|
||||
collection: req.collection,
|
||||
id: req.params.id,
|
||||
depth: parseInt(String(req.query.depth), 10),
|
||||
});
|
||||
|
||||
if (!doc) {
|
||||
return res.status(httpStatus.NOT_FOUND).json(new NotFound(req.t));
|
||||
}
|
||||
|
||||
return res.status(httpStatus.OK).send(doc);
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
}
|
||||
@@ -1,44 +1,51 @@
|
||||
import { Response, NextFunction } from 'express';
|
||||
import httpStatus from 'http-status';
|
||||
import { Where, Document } from '../../types';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
import formatSuccessResponse from '../../express/responses/formatSuccess';
|
||||
import { Document } from '../../types';
|
||||
import update from '../operations/update';
|
||||
import { getTranslation } from '../../utilities/getTranslation';
|
||||
|
||||
export type UpdateResult = {
|
||||
message: string
|
||||
doc: Document
|
||||
};
|
||||
|
||||
export async function deprecatedUpdate(req: PayloadRequest, res: Response, next: NextFunction): Promise<Response<UpdateResult> | void> {
|
||||
req.payload.logger.warn('The PUT method is deprecated and will no longer be supported in a future release. Please use the PATCH method for update requests.');
|
||||
|
||||
return updateHandler(req, res, next);
|
||||
}
|
||||
|
||||
export default async function updateHandler(req: PayloadRequest, res: Response, next: NextFunction): Promise<Response<UpdateResult> | void> {
|
||||
try {
|
||||
const draft = req.query.draft === 'true';
|
||||
const autosave = req.query.autosave === 'true';
|
||||
|
||||
const doc = await update({
|
||||
const result = await update({
|
||||
req,
|
||||
collection: req.collection,
|
||||
id: req.params.id,
|
||||
where: req.query.where as Where,
|
||||
data: req.body,
|
||||
depth: parseInt(String(req.query.depth), 10),
|
||||
draft,
|
||||
autosave,
|
||||
});
|
||||
|
||||
let message = req.t('general:updatedSuccessfully');
|
||||
if (result.errors.length === 0) {
|
||||
const message = req.t('general:updatedCountSuccessfully', {
|
||||
count: result.docs.length,
|
||||
label: getTranslation(req.collection.config.labels[result.docs.length > 1 ? 'plural' : 'singular'], req.i18n),
|
||||
});
|
||||
|
||||
if (draft) message = req.t('version:draftSavedSuccessfully');
|
||||
if (autosave) message = req.t('version:autosavedSuccessfully');
|
||||
return res.status(httpStatus.OK).json({
|
||||
...formatSuccessResponse(message, 'message'),
|
||||
...result,
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(httpStatus.OK).json({
|
||||
const total = result.docs.length + result.errors.length;
|
||||
const message = req.t('error:unableToUpdateCount', {
|
||||
count: result.errors.length,
|
||||
total,
|
||||
label: getTranslation(req.collection.config.labels[total > 1 ? 'plural' : 'singular'], req.i18n),
|
||||
});
|
||||
|
||||
return res.status(httpStatus.BAD_REQUEST).json({
|
||||
...formatSuccessResponse(message, 'message'),
|
||||
doc,
|
||||
...result,
|
||||
});
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
|
||||
45
src/collections/requestHandlers/updateByID.ts
Normal file
45
src/collections/requestHandlers/updateByID.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { Response, NextFunction } from 'express';
|
||||
import httpStatus from 'http-status';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
import formatSuccessResponse from '../../express/responses/formatSuccess';
|
||||
import updateByID from '../operations/updateByID';
|
||||
|
||||
export type UpdateResult = {
|
||||
message: string
|
||||
doc: Document
|
||||
};
|
||||
|
||||
export async function deprecatedUpdate(req: PayloadRequest, res: Response, next: NextFunction): Promise<Response<UpdateResult> | void> {
|
||||
req.payload.logger.warn('The PUT method is deprecated and will no longer be supported in a future release. Please use the PATCH method for update requests.');
|
||||
|
||||
return updateByIDHandler(req, res, next);
|
||||
}
|
||||
|
||||
export default async function updateByIDHandler(req: PayloadRequest, res: Response, next: NextFunction): Promise<Response<UpdateResult> | void> {
|
||||
try {
|
||||
const draft = req.query.draft === 'true';
|
||||
const autosave = req.query.autosave === 'true';
|
||||
|
||||
const doc = await updateByID({
|
||||
req,
|
||||
collection: req.collection,
|
||||
id: req.params.id,
|
||||
data: req.body,
|
||||
depth: parseInt(String(req.query.depth), 10),
|
||||
draft,
|
||||
autosave,
|
||||
});
|
||||
|
||||
let message = req.t('general:updatedSuccessfully');
|
||||
|
||||
if (draft) message = req.t('version:draftSavedSuccessfully');
|
||||
if (autosave) message = req.t('version:autosavedSuccessfully');
|
||||
|
||||
return res.status(httpStatus.OK).json({
|
||||
...formatSuccessResponse(message, 'message'),
|
||||
doc,
|
||||
});
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ export const baseAdminFields = joi.object().keys({
|
||||
initCollapsed: joi.boolean().default(false),
|
||||
hidden: joi.boolean().default(false),
|
||||
disabled: joi.boolean().default(false),
|
||||
disableBulkEdit: joi.boolean().default(false),
|
||||
condition: joi.func(),
|
||||
components: baseAdminComponentFields,
|
||||
});
|
||||
|
||||
@@ -70,6 +70,7 @@ type Admin = {
|
||||
Cell?: React.ComponentType<any>;
|
||||
Field?: React.ComponentType<any>;
|
||||
}
|
||||
disableBulkEdit?: boolean
|
||||
hidden?: boolean
|
||||
}
|
||||
|
||||
@@ -232,6 +233,7 @@ export type UIField = {
|
||||
position?: string
|
||||
width?: string
|
||||
condition?: Condition
|
||||
disableBulkEdit?: boolean
|
||||
components?: {
|
||||
Filter?: React.ComponentType<any>;
|
||||
Cell?: React.ComponentType<any>;
|
||||
|
||||
@@ -65,7 +65,7 @@ export const promise = async ({
|
||||
fields: field.fields,
|
||||
operation,
|
||||
req,
|
||||
siblingData: siblingData[field.name] as Record<string, unknown> || {},
|
||||
siblingData: siblingData?.[field.name] as Record<string, unknown> || {},
|
||||
siblingDoc: siblingDoc[field.name] as Record<string, unknown>,
|
||||
});
|
||||
|
||||
@@ -82,11 +82,11 @@ export const promise = async ({
|
||||
data,
|
||||
doc,
|
||||
previousDoc,
|
||||
previousSiblingDoc: previousDoc[field.name]?.[i] || {} as Record<string, unknown>,
|
||||
previousSiblingDoc: previousDoc?.[field.name]?.[i] || {} as Record<string, unknown>,
|
||||
fields: field.fields,
|
||||
operation,
|
||||
req,
|
||||
siblingData: siblingData[field.name]?.[i] || {},
|
||||
siblingData: siblingData?.[field.name]?.[i] || {},
|
||||
siblingDoc: { ...row } || {},
|
||||
}));
|
||||
});
|
||||
@@ -108,11 +108,11 @@ export const promise = async ({
|
||||
data,
|
||||
doc,
|
||||
previousDoc,
|
||||
previousSiblingDoc: previousDoc[field.name]?.[i] || {} as Record<string, unknown>,
|
||||
previousSiblingDoc: previousDoc?.[field.name]?.[i] || {} as Record<string, unknown>,
|
||||
fields: block.fields,
|
||||
operation,
|
||||
req,
|
||||
siblingData: siblingData[field.name]?.[i] || {},
|
||||
siblingData: siblingData?.[field.name]?.[i] || {},
|
||||
siblingDoc: { ...row } || {},
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { Config as GeneratedTypes } from 'payload/generated-types';
|
||||
import {
|
||||
InitOptions,
|
||||
} from './config/types';
|
||||
import { InitOptions } from './config/types';
|
||||
import { initHTTP } from './initHTTP';
|
||||
import { Payload as LocalPayload, BasePayload } from './payload';
|
||||
|
||||
|
||||
@@ -29,8 +29,6 @@ import { Preferences } from './preferences/types';
|
||||
import { Options as CreateOptions } from './collections/operations/local/create';
|
||||
import { Options as FindOptions } from './collections/operations/local/find';
|
||||
import { Options as FindByIDOptions } from './collections/operations/local/findByID';
|
||||
import { Options as UpdateOptions } from './collections/operations/local/update';
|
||||
import { Options as DeleteOptions } from './collections/operations/local/delete';
|
||||
import { Options as FindVersionsOptions } from './collections/operations/local/findVersions';
|
||||
import { Options as FindVersionByIDOptions } from './collections/operations/local/findVersionByID';
|
||||
import { Options as RestoreVersionOptions } from './collections/operations/local/restoreVersion';
|
||||
@@ -249,23 +247,18 @@ export class BasePayload<TGeneratedTypes extends GeneratedTypes> {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Update document
|
||||
* @description Update one or more documents
|
||||
* @param options
|
||||
* @returns Updated document
|
||||
* @returns Updated document(s)
|
||||
*/
|
||||
update = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: UpdateOptions<T>,
|
||||
): Promise<TGeneratedTypes['collections'][T]> => {
|
||||
const { update } = localOperations;
|
||||
return update<T>(this, options);
|
||||
}
|
||||
update = localOperations.update
|
||||
|
||||
delete = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: DeleteOptions<T>,
|
||||
): Promise<TGeneratedTypes['collections'][T]> => {
|
||||
const { localDelete } = localOperations;
|
||||
return localDelete<T>(this, options);
|
||||
}
|
||||
/**
|
||||
* @description delete one or more documents
|
||||
* @param options
|
||||
* @returns Updated document(s)
|
||||
*/
|
||||
delete = localOperations.localDelete;
|
||||
|
||||
/**
|
||||
* @description Find versions with criteria
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "Při nahrávání souboru došlo k chybě.",
|
||||
"tokenInvalidOrExpired": "Token je neplatný nebo vypršel.",
|
||||
"unPublishingDocument": "Při zrušení publikování tohoto dokumentu došlo k chybě.",
|
||||
"unableToDeleteCount": "Nelze smazat {{count}} z {{total}} {{label}}",
|
||||
"unableToUpdateCount": "Nelze aktualizovat {{count}} z {{total}} {{label}}.",
|
||||
"unauthorized": "Neautorizováno, pro zadání tohoto požadavku musíte být přihlášeni.",
|
||||
"unknown": "Došlo k neznámé chybě.",
|
||||
"unspecific": "Došlo k chybě.",
|
||||
@@ -124,6 +126,7 @@
|
||||
"saveChanges": "Uložit změny",
|
||||
"searchForBlock": "Hledat blok",
|
||||
"selectExistingLabel": "Vybrat existující {{label}}",
|
||||
"selectFieldsToEdit": "Vyberte pole, která chcete upravit",
|
||||
"showAll": "Zobrazit vše",
|
||||
"swapUpload": "Vyměnit nahrání",
|
||||
"textToDisplay": "Text k zobrazení",
|
||||
@@ -132,6 +135,9 @@
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "Chystáte se odstranit {{label}} <1>{{title}}</1>. Jste si jisti?",
|
||||
"aboutToDeleteCount_many": "Chystáte se smazat {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "Chystáte se smazat {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "Chystáte se smazat {{count}} {{label}}",
|
||||
"addBelow": "Přidat pod",
|
||||
"addFilter": "Přidat filtr",
|
||||
"adminTheme": "Motiv administračního rozhraní",
|
||||
@@ -159,6 +165,7 @@
|
||||
"dark": "Tmavé",
|
||||
"dashboard": "Nástěnka",
|
||||
"delete": "Odstranit",
|
||||
"deletedCountSuccessfully": "Úspěšně smazáno {{count}} {{label}}.",
|
||||
"deletedSuccessfully": "Úspěšně odstraněno.",
|
||||
"deleting": "Odstraňování...",
|
||||
"descending": "Sestupně",
|
||||
@@ -167,6 +174,9 @@
|
||||
"edit": "Upravit",
|
||||
"editLabel": "Upravit {{label}}",
|
||||
"editing": "Úpravy",
|
||||
"editingLabel_many": "Úprava {{count}} {{label}}",
|
||||
"editingLabel_one": "Úprava {{count}} {{label}}",
|
||||
"editingLabel_other": "Úprava {{count}} {{label}}",
|
||||
"email": "E-mail",
|
||||
"emailAddress": "E-mailová adresa",
|
||||
"enterAValue": "Zadejte hodnotu",
|
||||
@@ -205,7 +215,9 @@
|
||||
"save": "Uložit",
|
||||
"saving": "Ukládání...",
|
||||
"searchBy": "Vyhledat podle {{label}}",
|
||||
"selectAll": "Vybrat vše {{count}} {{label}}",
|
||||
"selectValue": "Vyberte hodnotu",
|
||||
"selectedCount": "Vybráno {{count}} {{label}}",
|
||||
"sorryNotFound": "Je nám líto, ale neexistuje nic, co by odpovídalo vašemu požadavku.",
|
||||
"sort": "Třídit",
|
||||
"stayOnThisPage": "Zůstat na této stránce",
|
||||
@@ -219,6 +231,7 @@
|
||||
"unsavedChangesDuplicate": "Máte neuložené změny. Chtěli byste pokračovat v duplikování?",
|
||||
"untitled": "Bez názvu",
|
||||
"updatedAt": "Aktualizováno v",
|
||||
"updatedCountSuccessfully": "Úspěšně aktualizováno {{count}} {{label}}.",
|
||||
"updatedSuccessfully": "Úspěšně aktualizováno.",
|
||||
"updating": "Aktualizace",
|
||||
"uploading": "Nahrávání",
|
||||
@@ -273,15 +286,18 @@
|
||||
"validUploadID": "Toto pole není platné ID pro odeslání."
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "Chystáte se publikovat všechny {{label}} ve výběru. Jsi si jistá?",
|
||||
"aboutToRestore": "Chystáte se obnovit tento {{label}} dokument do stavu, v jakém byl {{versionDate}}.",
|
||||
"aboutToRestoreGlobal": "Chystáte se obnovit globální {{label}} do stavu, v jakém byl {{versionDate}}.",
|
||||
"aboutToRevertToPublished": "Chystáte se vrátit změny tohoto dokumentu do jeho publikovaného stavu. Jste si jisti?",
|
||||
"aboutToUnpublish": "Chystáte se zrušit publikování tohoto dokumentu. Jste si jisti?",
|
||||
"aboutToUnpublishSelection": "Chystáte se zrušit publikování všech {{label}} ve výběru. Jsi si jistá?",
|
||||
"autosave": "Automatické uložení",
|
||||
"autosavedSuccessfully": "Úspěšně uloženo automaticky.",
|
||||
"autosavedVersion": "Verze automatického uložení",
|
||||
"changed": "Změněno",
|
||||
"compareVersion": "Porovnat verzi s:",
|
||||
"confirmPublish": "Potvrďte publikování",
|
||||
"confirmRevertToSaved": "Potvrdit vrácení k uloženému",
|
||||
"confirmUnpublish": "Potvrdit zrušení publikování",
|
||||
"confirmVersionRestoration": "Potvrdit obnovení verze",
|
||||
@@ -293,6 +309,7 @@
|
||||
"noRowsFound": "Nenalezen {{label}}",
|
||||
"preview": "Náhled",
|
||||
"problemRestoringVersion": "Při obnovování této verze došlo k problému",
|
||||
"publish": "Publikovat",
|
||||
"publishChanges": "Publikovat změny",
|
||||
"published": "Publikováno",
|
||||
"restoreThisVersion": "Obnovit tuto verzi",
|
||||
@@ -303,8 +320,8 @@
|
||||
"saveDraft": "Uložit koncept",
|
||||
"selectLocales": "Vyberte místní verze pro zobrazení",
|
||||
"selectVersionToCompare": "Vyberte verzi pro porovnání",
|
||||
"showingVersionsFor": "Zobrazují se verze pro:",
|
||||
"showLocales": "Zobrazit místní verze:",
|
||||
"showingVersionsFor": "Zobrazují se verze pro:",
|
||||
"status": "Stav",
|
||||
"type": "Typ",
|
||||
"unpublish": "Zrušit publikování",
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
"accountAlreadyActivated": "Dieses Konto wurde bereits aktiviert",
|
||||
"autosaving": "Es gab ein Problem während der automatischen Speicherung für dieses Dokument",
|
||||
"correctInvalidFields": "Bitte ungültige Felder korrigieren.",
|
||||
"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_many": "Die folgenden Felder sind nicht korrekt:",
|
||||
@@ -81,6 +82,8 @@
|
||||
"problemUploadingFile": "Es gab ein Problem während des Hochladens der Datei.",
|
||||
"tokenInvalidOrExpired": "Token ist entweder ungültig oder abgelaufen.",
|
||||
"unPublishingDocument": "Es gab ein Problem, dieses Dokument auf Entwurf zu setzen.",
|
||||
"unableToDeleteCount": "{{count}} von {{total}} {{label}} konnte nicht gelöscht werden.",
|
||||
"unableToUpdateCount": "{{count}} von {{total}} {{label}} konnte nicht aktualisiert werden.",
|
||||
"unauthorized": "Nicht autorisiert - du musst angemeldet sein, um diese Anfrage zu stellen.",
|
||||
"unknown": "Ein unbekannter Fehler ist aufgetreten.",
|
||||
"unspecific": "Ein Fehler ist aufgetreten.",
|
||||
@@ -89,24 +92,24 @@
|
||||
"verificationTokenInvalid": "Verifizierungs-Token ist nicht korrekt."
|
||||
},
|
||||
"fields": {
|
||||
"block": "Block",
|
||||
"blocks": "Blöcke",
|
||||
"addLabel": "{{label}} hinzufügen",
|
||||
"addLink": "Link Hinzufügen",
|
||||
"addNew": "Neu erstellen",
|
||||
"addNewLabel": "{{label}} erstellen",
|
||||
"addRelationship": "Verknüpfung Hinzufügen",
|
||||
"addUpload": "Hochladen Hinzufügen",
|
||||
"block": "Block",
|
||||
"blockType": "Block-Typ",
|
||||
"blocks": "Blöcke",
|
||||
"chooseBetweenCustomTextOrDocument": "Wähle zwischen einer eigenen Text-URL oder verlinke zu einem anderen Dokument.",
|
||||
"chooseDocumentToLink": "Wähle ein Dokument zum Verlinken",
|
||||
"chooseFromExisting": "Aus vorhandenen auswählen",
|
||||
"chooseLabel": "{{label}} auswählen",
|
||||
"collapseAll": "Alle einklappen",
|
||||
"customURL": "Eigene URL",
|
||||
"editLabelData": "{{label}} bearbeiten",
|
||||
"editLink": "Bearbeite Link",
|
||||
"editRelationship": "Beziehung Hinzufügen",
|
||||
"editLabelData": "{{label}} bearbeiten",
|
||||
"enterURL": "URL eingeben",
|
||||
"internalLink": "Interner Link",
|
||||
"itemsAndMore": "{{items}} und {{count}} mehr",
|
||||
@@ -125,6 +128,7 @@
|
||||
"saveChanges": "Änderungen speichern",
|
||||
"searchForBlock": "Nach Block suchen",
|
||||
"selectExistingLabel": "{{label}} auswählen (vorhandene)",
|
||||
"selectFieldsToEdit": "Wählen Sie die zu bearbeitenden Felder aus",
|
||||
"showAll": "Alle anzeigen",
|
||||
"swapRelationship": "Beziehung Tauschen",
|
||||
"swapUpload": "Datei Austauschen",
|
||||
@@ -134,10 +138,14 @@
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "Du bist dabei {{label}} <1>{{title}}</1> zu löschen. Bist du dir sicher?",
|
||||
"aboutToDeleteCount_many": "Sie sind dabei, {{count}} {{label}} zu löschen",
|
||||
"aboutToDeleteCount_one": "Sie sind dabei, {{count}} {{label}} zu löschen",
|
||||
"aboutToDeleteCount_other": "Sie sind dabei, {{count}} {{label}} zu löschen",
|
||||
"addBelow": "Darunter hinzufügen",
|
||||
"addFilter": "Filter hinzufügen",
|
||||
"adminTheme": "Admin-Farbthema",
|
||||
"and": "Und",
|
||||
"ascending": "Aufsteigend",
|
||||
"automatic": "Automatisch",
|
||||
"backToDashboard": "Zurück zur Übersicht",
|
||||
"cancel": "Abbrechen",
|
||||
@@ -160,6 +168,7 @@
|
||||
"dark": "Dunkel",
|
||||
"dashboard": "Übersicht",
|
||||
"delete": "Löschen",
|
||||
"deletedCountSuccessfully": "{{count}} {{label}} erfolgreich gelöscht.",
|
||||
"deletedSuccessfully": "Erfolgreich gelöscht.",
|
||||
"deleting": "Lösche...",
|
||||
"descending": "Absteigend",
|
||||
@@ -168,6 +177,9 @@
|
||||
"edit": "Bearbeiten",
|
||||
"editLabel": "{{label}} bearbeiten",
|
||||
"editing": "Bearbeite",
|
||||
"editingLabel_many": "Bearbeiten von {{count}} {{label}}",
|
||||
"editingLabel_one": "Bearbeiten von {{count}} {{label}}",
|
||||
"editingLabel_other": "Bearbeiten von {{count}} {{label}}",
|
||||
"email": "E-Mail",
|
||||
"emailAddress": "E-Mail-Adresse",
|
||||
"enterAValue": "Gib einen Wert ein",
|
||||
@@ -206,7 +218,9 @@
|
||||
"save": "Speichern",
|
||||
"saving": "Speichert...",
|
||||
"searchBy": "Suche nach {{label}}",
|
||||
"selectAll": "Alle auswählen {{count}} {{label}}",
|
||||
"selectValue": "Wert auswählen",
|
||||
"selectedCount": "{{count}} {{label}} ausgewählt",
|
||||
"sorryNotFound": "Entschuldige, es entspricht nichts deiner Anfrage",
|
||||
"sort": "Sortieren",
|
||||
"stayOnThisPage": "Auf dieser Seite bleiben",
|
||||
@@ -220,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "Du hast ungespeicherte Änderungen, möchtest du mit dem Duplizieren fortfahren?",
|
||||
"untitled": "ohne Titel",
|
||||
"updatedAt": "Aktualisiert am",
|
||||
"updatedCountSuccessfully": "{{count}} {{label}} erfolgreich aktualisiert.",
|
||||
"updatedSuccessfully": "Erfolgreich aktualisiert.",
|
||||
"updating": "Aktualisierung",
|
||||
"uploading": "Hochladen",
|
||||
@@ -228,20 +243,21 @@
|
||||
"welcome": "Willkommen"
|
||||
},
|
||||
"operators": {
|
||||
"contains": "enthält",
|
||||
"equals": "gleich",
|
||||
"isNotEqualTo": "ist nicht gleich",
|
||||
"isIn": "ist drin",
|
||||
"isNotIn": "ist nicht drin",
|
||||
"exists": "existiert",
|
||||
"isGreaterThan": "ist größer als",
|
||||
"isGreaterThanOrEqualTo": "ist größer oder gleich",
|
||||
"isIn": "ist drin",
|
||||
"isLessThan": "ist kleiner als",
|
||||
"isLessThanOrEqualTo": "ist kleiner oder gleich",
|
||||
"isGreaterThanOrEqualTo": "ist größer oder gleich",
|
||||
"near": "in der Nähe",
|
||||
"isLike": "ist wie",
|
||||
"contains": "enthält"
|
||||
"isNotEqualTo": "ist nicht gleich",
|
||||
"isNotIn": "ist nicht drin",
|
||||
"near": "in der Nähe"
|
||||
},
|
||||
"upload": {
|
||||
"dragAndDrop": "Ziehen Sie eine Datei per Drag-and-Drop",
|
||||
"dragAndDropHere": "oder ziehe eine Datei hier",
|
||||
"fileName": "Dateiname",
|
||||
"fileSize": "Dateigröße",
|
||||
@@ -250,7 +266,6 @@
|
||||
"moreInfo": "Mehr Info",
|
||||
"selectCollectionToBrowse": "Wähle eine Sammlung zum Durchsuchen aus",
|
||||
"selectFile": "Datei auswählen",
|
||||
"dragAndDrop": "Ziehen Sie eine Datei per Drag-and-Drop",
|
||||
"sizes": "Größen",
|
||||
"width": "Breite"
|
||||
},
|
||||
@@ -264,25 +279,28 @@
|
||||
"invalidSelections": "'Dieses Feld enthält die folgenden inkorrekten Auswahlen:'",
|
||||
"lessThanMin": "\"{{value}}\" ist weniger als der minimale erlaubte Wert von {{min}}.",
|
||||
"longerThanMin": "Dieser Wert muss länger als die minimale Länge von {{minLength}} Zeichen sein.",
|
||||
"requiresNoMoreThan": "Dieses Feld kann nicht mehr als {{count}} {{label}} enthalten.",
|
||||
"notValidDate": "\"{{value}}\" ist kein gültiges Datum.",
|
||||
"required": "Pflichtfeld",
|
||||
"requiresAtLeast": "Dieses Feld muss mindestens {{count}} {{label}} enthalten.",
|
||||
"requiresNoMoreThan": "Dieses Feld kann nicht mehr als {{count}} {{label}} enthalten.",
|
||||
"requiresTwoNumbers": "Dieses Feld muss zwei Nummern enthalten.",
|
||||
"shorterThanMax": "Dieser Wert muss kürzer als die maximale Länge von {{maxLength}} sein.",
|
||||
"trueOrFalse": "Dieses Feld kann nur wahr oder falsch sein.",
|
||||
"validUploadID": "'Dieses Feld enthält keine valide Upload-ID.'"
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "Sie sind dabei, alle {{label}} in der Auswahl zu veröffentlichen. Bist du dir sicher?",
|
||||
"aboutToRestore": "Du bist dabei, {{label}} auf den Stand vom {{versionDate}} zurücksetzen.",
|
||||
"aboutToRestoreGlobal": "Du bist dabei, das Globale Dokument {{label}} auf den Stand vom {{versionDate}} zurückzusetzen.",
|
||||
"aboutToRevertToPublished": "Du bist dabei, dieses Dokument auf den Stand des ersten Veröffentlichungsdatums zurückzusetzen - Bist du sicher?",
|
||||
"aboutToUnpublish": "Du bist dabei dieses Dokument auf Entwurf zu setzen - bist du dir sicher?",
|
||||
"aboutToUnpublishSelection": "Sie sind dabei, die Veröffentlichung aller {{label}} in der Auswahl aufzuheben. Bist du dir sicher?",
|
||||
"autosave": "Automatische Speicherung",
|
||||
"autosavedSuccessfully": "Erfolgreich automatisch gespeichert.",
|
||||
"autosavedVersion": "Automatisch gespeicherte Version",
|
||||
"changed": "Geändert",
|
||||
"compareVersion": "Vergleiche Version zu:",
|
||||
"confirmPublish": "Veröffentlichung bestätigen",
|
||||
"confirmRevertToSaved": "Zurücksetzen auf die letzte Speicherung bestätigen",
|
||||
"confirmUnpublish": "Setzen auf Entwurf bestätigen",
|
||||
"confirmVersionRestoration": " Wiederherstellung der Version bestätigen",
|
||||
@@ -294,6 +312,7 @@
|
||||
"noRowsFound": "Kein {{label}} gefunden",
|
||||
"preview": "Vorschau",
|
||||
"problemRestoringVersion": "Es gab ein Problem bei der Wiederherstellung dieser Version",
|
||||
"publish": "Veröffentlichen",
|
||||
"publishChanges": "Änderungen veröffentlichen",
|
||||
"published": "Veröffentlicht",
|
||||
"restoreThisVersion": "Diese Version wiederherstellen",
|
||||
@@ -305,6 +324,7 @@
|
||||
"selectLocales": "Wähle anzuzeigende Sprachumgebungen",
|
||||
"selectVersionToCompare": "Wähle Version zum Vergleich",
|
||||
"showLocales": "Sprachumgebungen anzeigen:",
|
||||
"showingVersionsFor": "Versionen anzeigen für:",
|
||||
"status": "Status",
|
||||
"type": "Typ",
|
||||
"unpublish": "Auf Entwurf setzen",
|
||||
@@ -313,6 +333,7 @@
|
||||
"versionCount_many": "{{count}} Versionen gefunden",
|
||||
"versionCount_none": "Keine Versionen gefunden",
|
||||
"versionCount_one": "{{count}} Version gefunden",
|
||||
"versionCount_other": "{{count}} Versionen gefunden",
|
||||
"versionCreatedOn": "{{version}} erstellt am:",
|
||||
"versionID": "Version ID",
|
||||
"versions": "Versionen",
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "There was a problem while uploading the file.",
|
||||
"tokenInvalidOrExpired": "Token is either invalid or has expired.",
|
||||
"unPublishingDocument": "There was a problem while un-publishing this document.",
|
||||
"unableToDeleteCount": "Unable to delete {{count}} out of {{total}} {{label}}.",
|
||||
"unableToUpdateCount": "Unable to update {{count}} out of {{total}} {{label}}.",
|
||||
"unauthorized": "Unauthorized, you must be logged in to make this request.",
|
||||
"unknown": "An unknown error has occurred.",
|
||||
"unspecific": "An error has occurred.",
|
||||
@@ -126,6 +128,7 @@
|
||||
"saveChanges": "Save changes",
|
||||
"searchForBlock": "Search for a block",
|
||||
"selectExistingLabel": "Select existing {{label}}",
|
||||
"selectFieldsToEdit": "Select fields to edit",
|
||||
"showAll": "Show All",
|
||||
"swapRelationship": "Swap Relationship",
|
||||
"swapUpload": "Swap Upload",
|
||||
@@ -135,6 +138,9 @@
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "You are about to delete the {{label}} <1>{{title}}</1>. Are you sure?",
|
||||
"aboutToDeleteCount_many": "You are about to delete {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "You are about to delete {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "You are about to delete {{count}} {{label}}",
|
||||
"addBelow": "Add Below",
|
||||
"addFilter": "Add Filter",
|
||||
"adminTheme": "Admin Theme",
|
||||
@@ -162,6 +168,7 @@
|
||||
"dark": "Dark",
|
||||
"dashboard": "Dashboard",
|
||||
"delete": "Delete",
|
||||
"deletedCountSuccessfully": "Deleted {{count}} {{label}} successfully.",
|
||||
"deletedSuccessfully": "Deleted successfully.",
|
||||
"deleting": "Deleting...",
|
||||
"descending": "Descending",
|
||||
@@ -170,6 +177,9 @@
|
||||
"edit": "Edit",
|
||||
"editLabel": "Edit {{label}}",
|
||||
"editing": "Editing",
|
||||
"editingLabel_many": "Editing {{count}} {{label}}",
|
||||
"editingLabel_one": "Editing {{count}} {{label}}",
|
||||
"editingLabel_other": "Editing {{count}} {{label}}",
|
||||
"email": "Email",
|
||||
"emailAddress": "Email Address",
|
||||
"enterAValue": "Enter a value",
|
||||
@@ -208,7 +218,9 @@
|
||||
"save": "Save",
|
||||
"saving": "Saving...",
|
||||
"searchBy": "Search by {{label}}",
|
||||
"selectAll": "Select all {{count}} {{label}}",
|
||||
"selectValue": "Select a value",
|
||||
"selectedCount": "{{count}} {{label}} selected",
|
||||
"sorryNotFound": "Sorry—there is nothing to correspond with your request.",
|
||||
"sort": "Sort",
|
||||
"stayOnThisPage": "Stay on this page",
|
||||
@@ -222,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "You have unsaved changes. Would you like to continue to duplicate?",
|
||||
"untitled": "Untitled",
|
||||
"updatedAt": "Updated At",
|
||||
"updatedCountSuccessfully": "Updated {{count}} {{label}} successfully.",
|
||||
"updatedSuccessfully": "Updated successfully.",
|
||||
"updating": "Updating",
|
||||
"uploading": "Uploading",
|
||||
@@ -230,20 +243,21 @@
|
||||
"welcome": "Welcome"
|
||||
},
|
||||
"operators": {
|
||||
"contains": "contains",
|
||||
"equals": "equals",
|
||||
"isNotEqualTo": "is not equal to",
|
||||
"isIn": "is in",
|
||||
"isNotIn": "is not in",
|
||||
"exists": "exists",
|
||||
"isGreaterThan": "is greater than",
|
||||
"isGreaterThanOrEqualTo": "is greater than or equal to",
|
||||
"isIn": "is in",
|
||||
"isLessThan": "is less than",
|
||||
"isLessThanOrEqualTo": "is less than or equal to",
|
||||
"isGreaterThanOrEqualTo": "is greater than or equal to",
|
||||
"near": "near",
|
||||
"isLike": "is like",
|
||||
"contains": "contains"
|
||||
"isNotEqualTo": "is not equal to",
|
||||
"isNotIn": "is not in",
|
||||
"near": "near"
|
||||
},
|
||||
"upload": {
|
||||
"dragAndDrop": "Drag and drop a file",
|
||||
"dragAndDropHere": "or drag and drop a file here",
|
||||
"fileName": "File Name",
|
||||
"fileSize": "File Size",
|
||||
@@ -252,7 +266,6 @@
|
||||
"moreInfo": "More info",
|
||||
"selectCollectionToBrowse": "Select a Collection to Browse",
|
||||
"selectFile": "Select a file",
|
||||
"dragAndDrop": "Drag and drop a file",
|
||||
"sizes": "Sizes",
|
||||
"width": "Width"
|
||||
},
|
||||
@@ -276,15 +289,18 @@
|
||||
"validUploadID": "This field is not a valid upload ID."
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "You are about to publish all {{label}} in the selection. Are you sure?",
|
||||
"aboutToRestore": "You are about to restore this {{label}} document to the state that it was in on {{versionDate}}.",
|
||||
"aboutToRestoreGlobal": "You are about to restore the global {{label}} to the state that it was in on {{versionDate}}.",
|
||||
"aboutToRevertToPublished": "You are about to revert this document's changes to its published state. Are you sure?",
|
||||
"aboutToUnpublish": "You are about to unpublish this document. Are you sure?",
|
||||
"aboutToUnpublishSelection": "You are about to unpublish all {{label}} in the selection. Are you sure?",
|
||||
"autosave": "Autosave",
|
||||
"autosavedSuccessfully": "Autosaved successfully.",
|
||||
"autosavedVersion": "Autosaved version",
|
||||
"changed": "Changed",
|
||||
"compareVersion": "Compare version against:",
|
||||
"confirmPublish": "Confirm publish",
|
||||
"confirmRevertToSaved": "Confirm revert to saved",
|
||||
"confirmUnpublish": "Confirm unpublish",
|
||||
"confirmVersionRestoration": "Confirm version Restoration",
|
||||
@@ -296,6 +312,7 @@
|
||||
"noRowsFound": "No {{label}} found",
|
||||
"preview": "Preview",
|
||||
"problemRestoringVersion": "There was a problem restoring this version",
|
||||
"publish": "Publish",
|
||||
"publishChanges": "Publish changes",
|
||||
"published": "Published",
|
||||
"restoreThisVersion": "Restore this version",
|
||||
@@ -306,8 +323,8 @@
|
||||
"saveDraft": "Save Draft",
|
||||
"selectLocales": "Select locales to display",
|
||||
"selectVersionToCompare": "Select a version to compare",
|
||||
"showingVersionsFor": "Showing versions for:",
|
||||
"showLocales": "Show locales:",
|
||||
"showingVersionsFor": "Showing versions for:",
|
||||
"status": "Status",
|
||||
"type": "Type",
|
||||
"unpublish": "Unpublish",
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "Ocurrió un problema al subir el archivo.",
|
||||
"tokenInvalidOrExpired": "El token es inválido o ya expiró.",
|
||||
"unPublishingDocument": "Ocurrió un error al despublicar este documento.",
|
||||
"unableToDeleteCount": "No se pudo eliminar {{count}} de {{total}} {{label}}.",
|
||||
"unableToUpdateCount": "No se puede actualizar {{count}} de {{total}} {{label}}.",
|
||||
"unauthorized": "No autorizado, debes iniciar sesión para realizar esta solicitud.",
|
||||
"unknown": "Ocurrió un error desconocido.",
|
||||
"unspecific": "Ocurrió un error.",
|
||||
@@ -126,6 +128,7 @@
|
||||
"saveChanges": "Guardar cambios",
|
||||
"searchForBlock": "Buscar bloque",
|
||||
"selectExistingLabel": "Seleccionar {{label}} existente",
|
||||
"selectFieldsToEdit": "Seleccionar campos para editar",
|
||||
"showAll": "Mostrar Todo",
|
||||
"swapRelationship": "Cambiar Relación",
|
||||
"swapUpload": "Cambiar carga",
|
||||
@@ -135,6 +138,9 @@
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "Estás por eliminar el {{label}} <1>{{title}}</1>. ¿Estás seguro?",
|
||||
"aboutToDeleteCount_many": "Está a punto de eliminar {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "Está a punto de eliminar {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "Está a punto de eliminar {{count}} {{label}}",
|
||||
"addBelow": "Agrega abajo",
|
||||
"addFilter": "Añadir filtro",
|
||||
"adminTheme": "Tema del admin",
|
||||
@@ -162,6 +168,7 @@
|
||||
"dark": "Oscuro",
|
||||
"dashboard": "Tablero",
|
||||
"delete": "Eliminar",
|
||||
"deletedCountSuccessfully": "Se eliminó {{count}} {{label}} con éxito.",
|
||||
"deletedSuccessfully": "Borrado exitosamente.",
|
||||
"deleting": "Eliminando...",
|
||||
"descending": "Descendente",
|
||||
@@ -170,6 +177,9 @@
|
||||
"edit": "Editar",
|
||||
"editLabel": "Editar {{label}}",
|
||||
"editing": "Editando",
|
||||
"editingLabel_many": "Edición de {{count}} {{label}}",
|
||||
"editingLabel_one": "Editando {{count}} {{label}}",
|
||||
"editingLabel_other": "Edición de {{count}} {{label}}",
|
||||
"email": "Correo electrónico",
|
||||
"emailAddress": "Dirección de Correo Electrónico",
|
||||
"enterAValue": "Introduce un valor",
|
||||
@@ -208,7 +218,9 @@
|
||||
"save": "Guardar",
|
||||
"saving": "Guardando...",
|
||||
"searchBy": "Buscar por {{label}}",
|
||||
"selectAll": "Seleccionar todo {{count}} {{label}}",
|
||||
"selectValue": "Selecciona un valor",
|
||||
"selectedCount": "{{count}} {{label}} seleccionado",
|
||||
"sorryNotFound": "Lo sentimos. No hay nada que corresponda con tu solicitud.",
|
||||
"sort": "Ordenar",
|
||||
"stayOnThisPage": "Permanecer en esta página",
|
||||
@@ -222,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "Tienes cambios sin guardar. ¿Deseas continuar para duplicar?",
|
||||
"untitled": "Sin título",
|
||||
"updatedAt": "Fecha de modificado",
|
||||
"updatedCountSuccessfully": "{{count}} {{label}} actualizado con éxito.",
|
||||
"updatedSuccessfully": "Actualizado con éxito.",
|
||||
"updating": "Actualizando",
|
||||
"uploading": "Subiendo",
|
||||
@@ -230,20 +243,21 @@
|
||||
"welcome": "Bienvenido"
|
||||
},
|
||||
"operators": {
|
||||
"contains": "contiene",
|
||||
"equals": "igual",
|
||||
"isNotEqualTo": "no es igual a",
|
||||
"isIn": "está en",
|
||||
"isNotIn": "no está en",
|
||||
"exists": "existe",
|
||||
"isGreaterThan": "es mayor que",
|
||||
"isGreaterThanOrEqualTo": "es mayor o igual que",
|
||||
"isIn": "está en",
|
||||
"isLessThan": "es menor que",
|
||||
"isLessThanOrEqualTo": "es menor o igual que",
|
||||
"isGreaterThanOrEqualTo": "es mayor o igual que",
|
||||
"near": "cerca",
|
||||
"isLike": "es como",
|
||||
"contains": "contiene"
|
||||
"isNotEqualTo": "no es igual a",
|
||||
"isNotIn": "no está en",
|
||||
"near": "cerca"
|
||||
},
|
||||
"upload": {
|
||||
"dragAndDrop": "Arrastra y suelta un archivo",
|
||||
"dragAndDropHere": "o arrastra un archivo aquí",
|
||||
"fileName": "Nombre del archivo",
|
||||
"fileSize": "Tamaño del archivo",
|
||||
@@ -252,7 +266,6 @@
|
||||
"moreInfo": "Más info",
|
||||
"selectCollectionToBrowse": "Selecciona una Colección",
|
||||
"selectFile": "Selecciona un archivo",
|
||||
"dragAndDrop": "Arrastra y suelta un archivo",
|
||||
"sizes": "Tamaños",
|
||||
"width": "Ancho"
|
||||
},
|
||||
@@ -276,15 +289,18 @@
|
||||
"validUploadID": "'Este campo no es una ID de subida válida.'"
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "Está a punto de publicar todas las {{etiquetas}} de la selección. ¿Está seguro?",
|
||||
"aboutToRestore": "Estás a punto de restaurar este documento de {{label}} al estado en el que estaba en la fecha {{versionDate}}.",
|
||||
"aboutToRestoreGlobal": "Estás a punto de restaurar el {{label}} global al estado en el que estaba en la fecha {{versionDate}}.",
|
||||
"aboutToRevertToPublished": "Estás a punto de revertir los cambios de este documento a su estado publicado. ¿Estás seguro?",
|
||||
"aboutToUnpublish": "Estás a punto de despublicar este documento. ¿Estás seguro?",
|
||||
"aboutToUnpublishSelection": "Está a punto de anular la publicación de todos los {{label}} de la selección. ¿Está seguro?",
|
||||
"autosave": "Autoguardar",
|
||||
"autosavedSuccessfully": "Guardado automáticamente con éxito.",
|
||||
"autosavedVersion": "Versión Autoguardada",
|
||||
"changed": "Modificado",
|
||||
"compareVersion": "Comparar versión con:",
|
||||
"confirmPublish": "Confirmar publicación",
|
||||
"confirmRevertToSaved": "Confirmar revertir a guardado",
|
||||
"confirmUnpublish": "Confirmar despublicado",
|
||||
"confirmVersionRestoration": "Confirmar restauración de versión",
|
||||
@@ -296,6 +312,7 @@
|
||||
"noRowsFound": "No encontramos {{label}}",
|
||||
"preview": "Previsualizar",
|
||||
"problemRestoringVersion": "Ocurrió un problema al restaurar esta versión",
|
||||
"publish": "Publicar",
|
||||
"publishChanges": "Publicar cambios",
|
||||
"published": "Publicado",
|
||||
"restoreThisVersion": "Restaurar esta versión",
|
||||
@@ -306,8 +323,8 @@
|
||||
"saveDraft": "Guardar Borrador",
|
||||
"selectLocales": "Selecciona idiomas a mostrar",
|
||||
"selectVersionToCompare": "Selecciona versión a comparar",
|
||||
"showingVersionsFor": "Mostrando versiones para:",
|
||||
"showLocales": "Mostrar idiomas:",
|
||||
"showingVersionsFor": "Mostrando versiones para:",
|
||||
"status": "Estado",
|
||||
"type": "Tipo",
|
||||
"unpublish": "Despublicar",
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "Il y a eu un problème lors du téléversement du fichier.",
|
||||
"tokenInvalidOrExpired": "Le jeton n'est soit pas valide ou a expiré.",
|
||||
"unPublishingDocument": "Un problème est survenu lors de l'annulation de la publication de ce document.",
|
||||
"unableToDeleteCount": "Impossible de supprimer {{count}} sur {{total}} {{label}}.",
|
||||
"unableToUpdateCount": "Impossible de mettre à jour {{count}} sur {{total}} {{label}}.",
|
||||
"unauthorized": "Non autorisé, vous devez être connecté pour effectuer cette demande.",
|
||||
"unknown": "Une erreur inconnue s'est produite.",
|
||||
"unspecific": "Une erreur est survenue.",
|
||||
@@ -90,15 +92,15 @@
|
||||
"verificationTokenInvalid": "Le jeton de vérification n'est pas valide."
|
||||
},
|
||||
"fields": {
|
||||
"block": "bloc",
|
||||
"blocks": "blocs",
|
||||
"addLabel": "Ajouter {{label}}",
|
||||
"addLink": "Ajouter un Lien",
|
||||
"addNew": "Ajouter nouveau ou nouvelle",
|
||||
"addNewLabel": "Ajouter nouveau ou nouvelle {{label}}",
|
||||
"addRelationship": "Ajouter une relation",
|
||||
"addUpload": "Ajouter le téléchargement",
|
||||
"block": "bloc",
|
||||
"blockType": "Type de bloc",
|
||||
"blocks": "blocs",
|
||||
"chooseBetweenCustomTextOrDocument": "Choisissez entre saisir une URL personnalisée ou créer un lien vers un autre document.",
|
||||
"chooseDocumentToLink": "Choisissez un document vers lequel établir un lien",
|
||||
"chooseFromExisting": "Choisir parmi les existant(e)s",
|
||||
@@ -126,6 +128,7 @@
|
||||
"saveChanges": "Sauvegarder les modifications",
|
||||
"searchForBlock": "Rechercher un bloc",
|
||||
"selectExistingLabel": "Sélectionnez {{label}} existant",
|
||||
"selectFieldsToEdit": "Sélectionnez les champs à modifier",
|
||||
"showAll": "Afficher tout",
|
||||
"swapRelationship": "Changer de relation",
|
||||
"swapUpload": "Changer de Fichier",
|
||||
@@ -135,10 +138,14 @@
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "Vous êtes sur le point de supprimer ce ou cette {{label}} <1>{{title}}</1>. Êtes-vous sûr ?",
|
||||
"aboutToDeleteCount_many": "Vous êtes sur le point de supprimer {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "Vous êtes sur le point de supprimer {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "Vous êtes sur le point de supprimer {{count}} {{label}}",
|
||||
"addBelow": "Ajoutez ci-dessous",
|
||||
"addFilter": "Ajouter un filtre",
|
||||
"adminTheme": "Thème d'administration",
|
||||
"and": "Et",
|
||||
"ascending": "Ascendant",
|
||||
"automatic": "Automatique",
|
||||
"backToDashboard": "Retour au tableau de bord",
|
||||
"cancel": "Annuler",
|
||||
@@ -161,6 +168,7 @@
|
||||
"dark": "Nuit",
|
||||
"dashboard": "Tableau de bord",
|
||||
"delete": "Supprimer",
|
||||
"deletedCountSuccessfully": "{{count}} {{label}} supprimé avec succès.",
|
||||
"deletedSuccessfully": "Supprimé(e) avec succès.",
|
||||
"deleting": "Suppression en cours...",
|
||||
"descending": "Descendant(e)",
|
||||
@@ -169,6 +177,9 @@
|
||||
"edit": "Éditer",
|
||||
"editLabel": "Modifier {{label}}",
|
||||
"editing": "Modification en cours",
|
||||
"editingLabel_many": "Modification des {{count}} {{label}}",
|
||||
"editingLabel_one": "Modification de {{count}} {{label}}",
|
||||
"editingLabel_other": "Modification des {{count}} {{label}}",
|
||||
"email": "E-mail",
|
||||
"emailAddress": "Adresse e-mail",
|
||||
"enterAValue": "Entrez une valeur",
|
||||
@@ -207,7 +218,9 @@
|
||||
"save": "Sauvegarder",
|
||||
"saving": "Sauvegarde en cours...",
|
||||
"searchBy": "Rechercher par {{label}}",
|
||||
"selectAll": "Tout sélectionner {{count}} {{label}}",
|
||||
"selectValue": "Sélectionnez une valeur",
|
||||
"selectedCount": "{{count}} {{label}} sélectionné",
|
||||
"sorryNotFound": "Désolé, rien ne correspond à votre demande.",
|
||||
"sort": "Trier",
|
||||
"stayOnThisPage": "Rester sur cette page",
|
||||
@@ -221,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "Vous avez des changements non enregistrés. Souhaitez-vous continuer la duplication ?",
|
||||
"untitled": "Sans titre",
|
||||
"updatedAt": "Modifié le",
|
||||
"updatedCountSuccessfully": "{{count}} {{label}} mis à jour avec succès.",
|
||||
"updatedSuccessfully": "Mis à jour avec succés.",
|
||||
"updating": "Mise à jour",
|
||||
"uploading": "Téléchargement",
|
||||
@@ -229,20 +243,21 @@
|
||||
"welcome": "Bienvenu(e)"
|
||||
},
|
||||
"operators": {
|
||||
"contains": "contient",
|
||||
"equals": "est égal à",
|
||||
"isNotEqualTo": "n'est pas égal à",
|
||||
"isIn": "est dans",
|
||||
"isNotIn": "n'est pas dans",
|
||||
"exists": "existe",
|
||||
"isGreaterThan": "est supérieur à",
|
||||
"isGreaterThanOrEqualTo": "est supérieur ou égal à",
|
||||
"isIn": "est dans",
|
||||
"isLessThan": "est inférieur à",
|
||||
"isLessThanOrEqualTo": "est inférieur ou égal à",
|
||||
"isGreaterThanOrEqualTo": "est supérieur ou égal à",
|
||||
"near": "proche",
|
||||
"isLike": "est comme",
|
||||
"contains": "contient"
|
||||
"isNotEqualTo": "n'est pas égal à",
|
||||
"isNotIn": "n'est pas dans",
|
||||
"near": "proche"
|
||||
},
|
||||
"upload": {
|
||||
"dragAndDrop": "Glisser-déposer un fichier",
|
||||
"dragAndDropHere": "ou glissez-déposez un fichier ici",
|
||||
"fileName": "Nom du fichier",
|
||||
"fileSize": "Taille du fichier",
|
||||
@@ -251,7 +266,6 @@
|
||||
"moreInfo": "Plus d'infos",
|
||||
"selectCollectionToBrowse": "Sélectionnez une collection à parcourir",
|
||||
"selectFile": "Sélectionnez un fichier",
|
||||
"dragAndDrop": "Glisser-déposer un fichier",
|
||||
"sizes": "Tailles",
|
||||
"width": "Largeur"
|
||||
},
|
||||
@@ -275,15 +289,18 @@
|
||||
"validUploadID": "Ce champ n'est pas un valide identifiant de fichier."
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "Vous êtes sur le point de publier tous les {{label}} de la sélection. Es-tu sûr?",
|
||||
"aboutToRestore": "Vous êtes sur le point de restaurer le document {{label}} à l'état où il se trouvait le {{versionDate}}.",
|
||||
"aboutToRestoreGlobal": "Vous êtes sur le point de restaurer le ou la {{label}} global(e) à l'état où il ou elle se trouvait le {{versionDate}}.",
|
||||
"aboutToRevertToPublished": "Vous êtes sur le point de rétablir les modifications apportées à ce document à la version publiée. Êtes-vous sûr ?",
|
||||
"aboutToUnpublish": "Vous êtes sur le point d'annuler la publication de ce document. Êtes-vous sûr ?",
|
||||
"aboutToUnpublishSelection": "Vous êtes sur le point de dépublier tous les {{label}} de la sélection. Es-tu sûr?",
|
||||
"autosave": "Enregistrement automatique",
|
||||
"autosavedSuccessfully": "Enregistrement automatique réussi.",
|
||||
"autosavedVersion": "Version enregistrée automatiquement",
|
||||
"changed": "Modifié",
|
||||
"compareVersion": "Comparez cette version à :",
|
||||
"confirmPublish": "Confirmer la publication",
|
||||
"confirmRevertToSaved": "Confirmer la restauration",
|
||||
"confirmUnpublish": "Confirmer l'annulation",
|
||||
"confirmVersionRestoration": "Confirmer la restauration de la version",
|
||||
@@ -295,6 +312,7 @@
|
||||
"noRowsFound": "Aucun(e) {{label}} trouvé(e)",
|
||||
"preview": "Aperçu",
|
||||
"problemRestoringVersion": "Un problème est survenu lors de la restauration de cette version",
|
||||
"publish": "Publier",
|
||||
"publishChanges": "Publier les modifications",
|
||||
"published": "Publié",
|
||||
"restoreThisVersion": "Restaurer cette version",
|
||||
@@ -303,9 +321,10 @@
|
||||
"revertToPublished": "Republier",
|
||||
"reverting": "Republication en cours...",
|
||||
"saveDraft": "Enregistrer le brouillon",
|
||||
"selectLocals": "Sélectionnez les paramètres régionaux à afficher",
|
||||
"selectLocales": "Sélectionnez les paramètres régionaux à afficher",
|
||||
"selectVersionToCompare": "Sélectionnez une version à comparer",
|
||||
"showLocales": "Afficher les paramètres régionaux :",
|
||||
"showingVersionsFor": "Affichage des versions pour :",
|
||||
"status": "Statut",
|
||||
"type": "Type",
|
||||
"unpublish": "Annuler la publication",
|
||||
@@ -314,6 +333,7 @@
|
||||
"versionCount_many": "{{count}} versions trouvées",
|
||||
"versionCount_none": "Aucune version trouvée",
|
||||
"versionCount_one": "{{count}} version trouvée",
|
||||
"versionCount_other": "{{count}} versions trouvées",
|
||||
"versionCreatedOn": "{{version}} créé(e) le :",
|
||||
"versionID": "Identifiant de la version",
|
||||
"versions": "Versions",
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "Pojavio se problem pri učitavanju datoteke.",
|
||||
"tokenInvalidOrExpired": "Token je nevaljan ili je istekao.",
|
||||
"unPublishingDocument": "Pojavio se problem pri poništavanju objave ovog dokumenta.",
|
||||
"unableToDeleteCount": "Nije moguće izbrisati {{count}} od {{total}} {{label}}.",
|
||||
"unableToUpdateCount": "Nije moguće ažurirati {{count}} od {{total}} {{label}}.",
|
||||
"unauthorized": "Neovlašten, morate biti prijavljeni da biste uputili ovaj zahtjev.",
|
||||
"unknown": "Došlo je do nepoznate pogreške.",
|
||||
"unspecific": "Došlo je do pogreške.",
|
||||
@@ -126,6 +128,7 @@
|
||||
"saveChanges": "Spremi promjene",
|
||||
"searchForBlock": "Potraži blok",
|
||||
"selectExistingLabel": "Odaberi postojeće{{label}}",
|
||||
"selectFieldsToEdit": "Odaberite polja za uređivanje",
|
||||
"showAll": "Pokaži sve",
|
||||
"swapRelationship": "Zamijeni vezu",
|
||||
"swapUpload": "Zamijeni prijenos",
|
||||
@@ -135,6 +138,9 @@
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "Izbrisat ćete {{label}} <1>{{title}}</1>. Jeste li sigurni?",
|
||||
"aboutToDeleteCount_many": "Upravo ćete izbrisati {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "Upravo ćete izbrisati {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "Upravo ćete izbrisati {{count}} {{label}}",
|
||||
"addBelow": "Dodaj ispod",
|
||||
"addFilter": "Dodaj filter",
|
||||
"adminTheme": "Administratorska tema",
|
||||
@@ -162,6 +168,7 @@
|
||||
"dark": "Tamno",
|
||||
"dashboard": "Nadzorna ploča",
|
||||
"delete": "Obriši",
|
||||
"deletedCountSuccessfully": "Uspješno izbrisano {{count}} {{label}}.",
|
||||
"deletedSuccessfully": "Uspješno obrisano.",
|
||||
"deleting": "Brisanje...",
|
||||
"descending": "Silazno",
|
||||
@@ -170,6 +177,9 @@
|
||||
"edit": "Uredi",
|
||||
"editLabel": "Uredi {{label}}",
|
||||
"editing": "Uređivanje",
|
||||
"editingLabel_many": "Uređivanje {{count}} {{label}}",
|
||||
"editingLabel_one": "Uređivanje {{count}} {{label}}",
|
||||
"editingLabel_other": "Uređivanje {{count}} {{label}}",
|
||||
"email": "Email",
|
||||
"emailAddress": "Email adresa",
|
||||
"enterAValue": "Unesi vrijednost",
|
||||
@@ -208,7 +218,9 @@
|
||||
"save": "Spremi",
|
||||
"saving": "Spremanje...",
|
||||
"searchBy": "Traži po {{label}}",
|
||||
"selectAll": "Odaberite sve {{count}} {{label}}",
|
||||
"selectValue": "Odaberi vrijednost",
|
||||
"selectedCount": "{{count}} {{label}} odabrano",
|
||||
"sorryNotFound": "Nažalost, ne postoji ništa što odgovara vašem zahtjevu.",
|
||||
"sort": "Sortiraj",
|
||||
"stayOnThisPage": "Ostani na ovoj stranici",
|
||||
@@ -222,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "Imate nespremljene promjene. Želite li nastaviti s dupliciranjem?",
|
||||
"untitled": "Bez naslova",
|
||||
"updatedAt": "Ažurirano u",
|
||||
"updatedCountSuccessfully": "Uspješno ažurirano {{count}} {{label}}.",
|
||||
"updatedSuccessfully": "Uspješno ažurirano.",
|
||||
"updating": "Ažuriranje",
|
||||
"uploading": "Prijenos",
|
||||
@@ -230,20 +243,21 @@
|
||||
"welcome": "Dobrodošli"
|
||||
},
|
||||
"operators": {
|
||||
"contains": "sadrži",
|
||||
"equals": "jednako",
|
||||
"isNotEqualTo": "nije jednako",
|
||||
"isIn": "je u",
|
||||
"isNotIn": "nije unutra",
|
||||
"exists": "postoji",
|
||||
"isGreaterThan": "je veće od",
|
||||
"isGreaterThanOrEqualTo": "je veće od ili jednako",
|
||||
"isIn": "je u",
|
||||
"isLessThan": "manje je od",
|
||||
"isLessThanOrEqualTo": "manje je ili jednako",
|
||||
"isGreaterThanOrEqualTo": "je veće od ili jednako",
|
||||
"near": "blizu",
|
||||
"isLike": "je kao",
|
||||
"contains": "sadrži"
|
||||
"isNotEqualTo": "nije jednako",
|
||||
"isNotIn": "nije unutra",
|
||||
"near": "blizu"
|
||||
},
|
||||
"upload": {
|
||||
"dragAndDrop": "Povucite i ispustite datoteku",
|
||||
"dragAndDropHere": "ili povucite i ispustite datoteku ovdje",
|
||||
"fileName": "Ime datoteke",
|
||||
"fileSize": "Veličina datoteke",
|
||||
@@ -252,7 +266,6 @@
|
||||
"moreInfo": "Više informacija",
|
||||
"selectCollectionToBrowse": "Odaberite kolekciju za pregled",
|
||||
"selectFile": "Odaberite datoteku",
|
||||
"dragAndDrop": "Povucite i ispustite datoteku",
|
||||
"sizes": "Veličine",
|
||||
"width": "Širina"
|
||||
},
|
||||
@@ -276,15 +289,18 @@
|
||||
"validUploadID": "Ovo polje nije valjani ID prijenosa."
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "Upravo ćete objaviti sve {{label}} u izboru. Jesi li siguran?",
|
||||
"aboutToRestore": "Vratit ćete {{label}} dokument u stanje u kojem je bio {{versionDate}}",
|
||||
"aboutToRestoreGlobal": "Vratit ćete globalni {{label}} u stanje u kojem je bio {{versionDate}}.",
|
||||
"aboutToRevertToPublished": "Vratit ćete promjene u dokumentu u objavljeno stanje. Jeste li sigurni? ",
|
||||
"aboutToUnpublish": "Poništit ćete objavu ovog dokumenta. Jeste li sigurni?",
|
||||
"aboutToUnpublishSelection": "Upravo ćete poništiti objavu svih {{label}} u odabiru. Jesi li siguran?",
|
||||
"autosave": "Automatsko spremanje",
|
||||
"autosavedSuccessfully": "Automatsko spremanje uspješno.",
|
||||
"autosavedVersion": "Verzija automatski spremljenog dokumenta",
|
||||
"changed": "Promijenjeno",
|
||||
"compareVersion": "Usporedi verziju sa:",
|
||||
"confirmPublish": "Potvrdi objavu",
|
||||
"confirmRevertToSaved": "Potvrdite vraćanje na spremljeno",
|
||||
"confirmUnpublish": "Potvrdite poništavanje objave",
|
||||
"confirmVersionRestoration": "Potvrdite vraćanje verzije",
|
||||
@@ -296,6 +312,7 @@
|
||||
"noRowsFound": "{{label}} nije pronađeno",
|
||||
"preview": "Pregled",
|
||||
"problemRestoringVersion": "Nastao je problem pri vraćanju ove verzije",
|
||||
"publish": "Objaviti",
|
||||
"publishChanges": "Objavi promjene",
|
||||
"published": "Objavljeno",
|
||||
"restoreThisVersion": "Vrati ovu verziju",
|
||||
@@ -306,8 +323,8 @@
|
||||
"saveDraft": "Sačuvaj nacrt",
|
||||
"selectLocales": "Odaberite jezike",
|
||||
"selectVersionToCompare": "Odaberite verziju za usporedbu",
|
||||
"showingVersionsFor": "Pokazujem verzije za:",
|
||||
"showLocales": "Prikaži jezike:",
|
||||
"showingVersionsFor": "Pokazujem verzije za:",
|
||||
"status": "Status",
|
||||
"type": "Tip",
|
||||
"unpublish": "Poništi objavu",
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "Hiba történt a fájl feltöltése közben.",
|
||||
"tokenInvalidOrExpired": "A token érvénytelen vagy lejárt.",
|
||||
"unPublishingDocument": "Hiba történt a dokumentum közzétételének visszavonása közben.",
|
||||
"unableToDeleteCount": "Nem sikerült törölni {{count}}/{{total}} {{label}}.",
|
||||
"unableToUpdateCount": "Nem sikerült frissíteni {{count}}/{{total}} {{label}}.",
|
||||
"unauthorized": "Jogosulatlan, a kéréshez be kell jelentkeznie.",
|
||||
"unknown": "Ismeretlen hiba történt.",
|
||||
"unspecific": "Hiba történt.",
|
||||
@@ -126,6 +128,7 @@
|
||||
"saveChanges": "Módosítások mentése",
|
||||
"searchForBlock": "Blokk keresése",
|
||||
"selectExistingLabel": "Meglévő {{label}} kiválasztása",
|
||||
"selectFieldsToEdit": "Válassza ki a szerkeszteni kívánt mezőket",
|
||||
"showAll": "Az összes megjelenítése",
|
||||
"swapRelationship": "Kapcsolat csere",
|
||||
"swapUpload": "Feltöltés csere",
|
||||
@@ -135,6 +138,9 @@
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "A {{label}} <1>{{title}}</1> törlésére készül. Biztos benne?",
|
||||
"aboutToDeleteCount_many": "Törölni készül {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "Törölni készül {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "Törölni készül {{count}} {{label}}",
|
||||
"addBelow": "Hozzáadás lent",
|
||||
"addFilter": "Szűrő hozzáadása",
|
||||
"adminTheme": "Admin téma",
|
||||
@@ -162,6 +168,7 @@
|
||||
"dark": "Sötét",
|
||||
"dashboard": "Irányítópult",
|
||||
"delete": "Törlés",
|
||||
"deletedCountSuccessfully": "{{count}} {{label}} sikeresen törölve.",
|
||||
"deletedSuccessfully": "Sikeresen törölve.",
|
||||
"deleting": "Törlés...",
|
||||
"descending": "Csökkenő",
|
||||
@@ -170,6 +177,9 @@
|
||||
"edit": "Szerkesztés",
|
||||
"editLabel": "{{label}} szerkesztése",
|
||||
"editing": "Szerkesztés",
|
||||
"editingLabel_many": "{{count}} {{label}} szerkesztése",
|
||||
"editingLabel_one": "{{count}} {{label}} szerkesztése",
|
||||
"editingLabel_other": "{{count}} {{label}} szerkesztése",
|
||||
"email": "E-mail",
|
||||
"emailAddress": "E-mail cím",
|
||||
"enterAValue": "Adjon meg egy értéket",
|
||||
@@ -208,7 +218,9 @@
|
||||
"save": "Mentés",
|
||||
"saving": "Mentés...",
|
||||
"searchBy": "Keresés a következő szerint: {{label}}",
|
||||
"selectAll": "Az összes kijelölése: {{count}} {{label}}",
|
||||
"selectValue": "Válasszon ki egy értéket",
|
||||
"selectedCount": "{{count}} {{label}} kiválasztva",
|
||||
"sorryNotFound": "Sajnáljuk – nincs semmi, ami megfelelne a kérésének.",
|
||||
"sort": "Rendezés",
|
||||
"stayOnThisPage": "Maradjon ezen az oldalon",
|
||||
@@ -222,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "Nem mentett módosításai vannak. Szeretné folytatni a duplikációt?",
|
||||
"untitled": "Névtelen",
|
||||
"updatedAt": "Frissítve:",
|
||||
"updatedCountSuccessfully": "{{count}} {{label}} sikeresen frissítve.",
|
||||
"updatedSuccessfully": "Sikeresen frissítve.",
|
||||
"updating": "Frissítés",
|
||||
"uploading": "Feltöltés",
|
||||
@@ -276,15 +289,18 @@
|
||||
"validUploadID": "Ez a mező nem érvényes feltöltési azonosító."
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "Arra készül, hogy az összes {{label}} elemet közzétegye a kijelölésben. biztos vagy ebben?",
|
||||
"aboutToRestore": "Arra készül, hogy visszaállítsa ezt a {{label}} dokumentumot arra az állapotra, amelyben {{versionDate}} napon volt.",
|
||||
"aboutToRestoreGlobal": "Arra készül, hogy visszaállítsa a {{label}} arra az állapotra, amelyben {{versionDate}} napon volt.",
|
||||
"aboutToRevertToPublished": "Arra készül, hogy visszaállítsa a dokumentum módosításait a közzétett állapotába. Biztos benne?",
|
||||
"aboutToUnpublish": "A dokumentum közzétételének visszavonására készül. Biztos benne?",
|
||||
"aboutToUnpublishSelection": "Arra készül, hogy visszavonja a kijelölésben szereplő összes {{label}} közzétételét. biztos vagy ebben?",
|
||||
"autosave": "Automatikus mentés",
|
||||
"autosavedSuccessfully": "Automatikus mentés sikeres.",
|
||||
"autosavedVersion": "Automatikusan mentett verzió",
|
||||
"changed": "Megváltozott",
|
||||
"compareVersion": "Hasonlítsa össze a verziót a következőkkel:",
|
||||
"confirmPublish": "A közzététel megerősítése",
|
||||
"confirmRevertToSaved": "Erősítse meg a mentett verzióra való visszatérést",
|
||||
"confirmUnpublish": "A közzététel visszavonásának megerősítése",
|
||||
"confirmVersionRestoration": "Verzió-visszaállítás megerősítése",
|
||||
@@ -296,6 +312,7 @@
|
||||
"noRowsFound": "Nem található {{label}}",
|
||||
"preview": "Előnézet",
|
||||
"problemRestoringVersion": "Hiba történt a verzió visszaállításakor",
|
||||
"publish": "Közzététel",
|
||||
"publishChanges": "Módosítások közzététele",
|
||||
"published": "Közzétett",
|
||||
"restoreThisVersion": "A verzió visszaállítása",
|
||||
@@ -306,8 +323,8 @@
|
||||
"saveDraft": "Piszkozat mentése",
|
||||
"selectLocales": "Megjelenítendő nyelvek kiválasztása",
|
||||
"selectVersionToCompare": "Válassza ki az összehasonlítani kívánt verziót",
|
||||
"showingVersionsFor": "Verziók megjelenítése a következőkhöz:",
|
||||
"showLocales": "Nyelvek megjelenítése:",
|
||||
"showingVersionsFor": "Verziók megjelenítése a következőkhöz:",
|
||||
"status": "Állapot",
|
||||
"type": "Típus",
|
||||
"unpublish": "Közzététel visszavonása",
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "Si è verificato un problema durante il caricamento del file.",
|
||||
"tokenInvalidOrExpired": "Il token non è valido o è scaduto.",
|
||||
"unPublishingDocument": "Si è verificato un problema durante l'annullamento della pubblicazione di questo documento.",
|
||||
"unableToDeleteCount": "Impossibile eliminare {{count}} su {{total}} {{label}}.",
|
||||
"unableToUpdateCount": "Impossibile aggiornare {{count}} su {{total}} {{label}}.",
|
||||
"unauthorized": "Non autorizzato, devi essere loggato per effettuare questa richiesta.",
|
||||
"unknown": "Si è verificato un errore sconosciuto.",
|
||||
"unspecific": "Si è verificato un errore.",
|
||||
@@ -90,27 +92,34 @@
|
||||
"verificationTokenInvalid": "Il token di verifica non è valido."
|
||||
},
|
||||
"fields": {
|
||||
"block": "blocco",
|
||||
"blocks": "blocchi",
|
||||
"addLabel": "Aggiungi {{label}}",
|
||||
"addLink": "Aggiungi Collegamento",
|
||||
"addNew": "Aggiungi nuovo",
|
||||
"addNewLabel": "Aggiungi nuovo {{label}}",
|
||||
"addRelationship": "Aggiungi Relazione",
|
||||
"addUpload": "aggiungi Carica",
|
||||
"block": "blocco",
|
||||
"blockType": "Tipo di Blocco",
|
||||
"blocks": "blocchi",
|
||||
"chooseBetweenCustomTextOrDocument": "Scegli tra l'inserimento di un URL di testo personalizzato o il collegamento a un altro documento.",
|
||||
"chooseDocumentToLink": "Scegli un documento a cui collegarti",
|
||||
"chooseFromExisting": "Scegli tra esistente",
|
||||
"chooseLabel": "Scegli {{label}}",
|
||||
"collapseAll": "Comprimi tutto",
|
||||
"customURL": "URL personalizzato",
|
||||
"editLabelData": "Modifica i dati di {{label}}",
|
||||
"editLink": "Modifica Collegamento",
|
||||
"editRelationship": "Modifica Relazione",
|
||||
"enterURL": "Inserisci un URL",
|
||||
"internalLink": "Collegamento interno",
|
||||
"itemsAndMore": "{{items}} e altri {{count}}",
|
||||
"labelRelationship": "Relazione {{label}}",
|
||||
"latitude": "Latitudine",
|
||||
"linkType": "Tipo di collegamento",
|
||||
"linkedTo": "Collegato a <0>{{label}}</0>",
|
||||
"longitude": "Longitudine",
|
||||
"newLabel": "Nuovo {{label}}",
|
||||
"openInNewTab": "Apri in una nuova scheda",
|
||||
"passwordsDoNotMatch": "Le password non corrispondono.",
|
||||
"relatedDocument": "Documento Correlato",
|
||||
"relationTo": "Correla a",
|
||||
@@ -119,18 +128,24 @@
|
||||
"saveChanges": "Salva modifiche",
|
||||
"searchForBlock": "Cerca un blocco",
|
||||
"selectExistingLabel": "Seleziona {{label}} esistente",
|
||||
"selectFieldsToEdit": "Seleziona i campi da modificare",
|
||||
"showAll": "Mostra tutto",
|
||||
"swapRelationship": "Cambia Relationship",
|
||||
"swapUpload": "Cambia Upload",
|
||||
"textToDisplay": "Testo da visualizzare",
|
||||
"toggleBlock": "Apri/chiudi blocco",
|
||||
"uploadNewLabel": "Carica nuovo {{label}}"
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "Stai per eliminare {{label}} <1>{{title}}</1>. Sei sicuro?",
|
||||
"aboutToDeleteCount_many": "Stai per eliminare {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "Stai per eliminare {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "Stai per eliminare {{count}} {{label}}",
|
||||
"addBelow": "Aggiungi sotto",
|
||||
"addFilter": "Aggiungi Filtro",
|
||||
"adminTheme": "Tema Admin",
|
||||
"and": "E",
|
||||
"ascending": "Ascendente",
|
||||
"automatic": "Automatico",
|
||||
"backToDashboard": "Torna alla Dashboard",
|
||||
"cancel": "Cancella",
|
||||
@@ -153,6 +168,7 @@
|
||||
"dark": "Scuro",
|
||||
"dashboard": "Dashboard",
|
||||
"delete": "Elimina",
|
||||
"deletedCountSuccessfully": "{{count}} {{label}} eliminato con successo.",
|
||||
"deletedSuccessfully": "Eliminato con successo.",
|
||||
"deleting": "Sto eliminando...",
|
||||
"descending": "Decrescente",
|
||||
@@ -161,6 +177,9 @@
|
||||
"edit": "Modificare",
|
||||
"editLabel": "Modifica {{label}}",
|
||||
"editing": "Modifica",
|
||||
"editingLabel_many": "Modificare {{count}} {{label}}",
|
||||
"editingLabel_one": "Modifica {{count}} {{label}}",
|
||||
"editingLabel_other": "Modificare {{count}} {{label}}",
|
||||
"email": "Email",
|
||||
"emailAddress": "Indirizzo Email",
|
||||
"enterAValue": "Inserisci un valore",
|
||||
@@ -199,7 +218,9 @@
|
||||
"save": "Salva",
|
||||
"saving": "Salvo...",
|
||||
"searchBy": "Cerca per {{label}}",
|
||||
"selectAll": "Seleziona tutto {{count}} {{label}}",
|
||||
"selectValue": "Seleziona un valore",
|
||||
"selectedCount": "{{count}} {{label}} selezionato",
|
||||
"sorryNotFound": "Siamo spiacenti, non c'è nulla che corrisponda alla tua richiesta.",
|
||||
"sort": "Ordina",
|
||||
"stayOnThisPage": "Rimani su questa pagina",
|
||||
@@ -213,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "Sono presenti modifiche non salvate. Vuoi continuare a duplicare?",
|
||||
"untitled": "Senza titolo",
|
||||
"updatedAt": "Aggiornato il",
|
||||
"updatedCountSuccessfully": "{{count}} {{label}} aggiornato con successo.",
|
||||
"updatedSuccessfully": "Aggiornato con successo.",
|
||||
"updating": "Aggiornamento",
|
||||
"uploading": "Caricamento",
|
||||
@@ -221,20 +243,21 @@
|
||||
"welcome": "Benvenuto"
|
||||
},
|
||||
"operators": {
|
||||
"contains": "contiene",
|
||||
"equals": "uguale",
|
||||
"isNotEqualTo": "non è uguale a",
|
||||
"isIn": "è in",
|
||||
"isNotIn": "non è in",
|
||||
"exists": "esiste",
|
||||
"isGreaterThan": "è maggiore di",
|
||||
"isGreaterThanOrEqualTo": "è maggiore o uguale a",
|
||||
"isIn": "è in",
|
||||
"isLessThan": "è minore di",
|
||||
"isLessThanOrEqualTo": "è minore o uguale a",
|
||||
"isGreaterThanOrEqualTo": "è maggiore o uguale a",
|
||||
"near": "vicino",
|
||||
"isLike": "è come",
|
||||
"contains": "contiene"
|
||||
"isNotEqualTo": "non è uguale a",
|
||||
"isNotIn": "non è in",
|
||||
"near": "vicino"
|
||||
},
|
||||
"upload": {
|
||||
"dragAndDrop": "Trascina e rilascia un file",
|
||||
"dragAndDropHere": "oppure trascina e rilascia un file qui",
|
||||
"fileName": "Nome File",
|
||||
"fileSize": "Dimensione File",
|
||||
@@ -243,7 +266,6 @@
|
||||
"moreInfo": "Più info",
|
||||
"selectCollectionToBrowse": "Seleziona una Collezione da Sfogliare",
|
||||
"selectFile": "Seleziona un file",
|
||||
"dragAndDrop": "Trascina e rilascia un file",
|
||||
"sizes": "Formati",
|
||||
"width": "Larghezza"
|
||||
},
|
||||
@@ -267,15 +289,18 @@
|
||||
"validUploadID": "'Questo campo non è un ID di Upload valido.'"
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "Stai per pubblicare tutte le {{label}} nella selezione. Sei sicuro?",
|
||||
"aboutToRestore": "Stai per ripristinare questo documento {{label}} allo stato in cui si trovava il {{versionDate}}.",
|
||||
"aboutToRestoreGlobal": "Stai per ripristinare {{label}} allo stato in cui si trovava il {{versionDate}}.",
|
||||
"aboutToRevertToPublished": "Stai per ripristinare le modifiche di questo documento al suo stato pubblicato. Sei sicuro?",
|
||||
"aboutToUnpublish": "Stai per annullare la pubblicazione di questo documento. Sei sicuro?",
|
||||
"aboutToUnpublishSelection": "Stai per annullare la pubblicazione di tutte le {{label}} nella selezione. Sei sicuro?",
|
||||
"autosave": "Salvataggio automatico",
|
||||
"autosavedSuccessfully": "Salvataggio automatico riuscito.",
|
||||
"autosavedVersion": "Versione salvata automaticamente",
|
||||
"changed": "Modificato",
|
||||
"compareVersion": "Confronta versione con:",
|
||||
"confirmPublish": "Conferma la pubblicazione",
|
||||
"confirmRevertToSaved": "Conferma il ripristino dei salvataggi",
|
||||
"confirmUnpublish": "Conferma annullamento della pubblicazione",
|
||||
"confirmVersionRestoration": "Conferma il ripristino della versione",
|
||||
@@ -287,6 +312,7 @@
|
||||
"noRowsFound": "Nessun {{label}} trovato",
|
||||
"preview": "Anteprima",
|
||||
"problemRestoringVersion": "Si è verificato un problema durante il ripristino di questa versione",
|
||||
"publish": "Pubblicare",
|
||||
"publishChanges": "Pubblica modifiche",
|
||||
"published": "Pubblicato",
|
||||
"restoreThisVersion": "Ripristina questa versione",
|
||||
@@ -297,8 +323,8 @@
|
||||
"saveDraft": "Salva Bozza",
|
||||
"selectLocales": "Seleziona le lingue da visualizzare",
|
||||
"selectVersionToCompare": "Seleziona una versione da confrontare",
|
||||
"showingVersionsFor": "Mostra le versioni per:",
|
||||
"showLocales": "Mostra localizzazioni:",
|
||||
"showingVersionsFor": "Mostra le versioni per:",
|
||||
"status": "Stato",
|
||||
"type": "Tipo",
|
||||
"unpublish": "Annulla pubblicazione",
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
"accountAlreadyActivated": "このアカウントはすでに有効です。",
|
||||
"autosaving": "このデータを自動保存する際に問題が発生しました。",
|
||||
"correctInvalidFields": "無効なフィールドを修正してください。",
|
||||
"deletingFile": "ファイルの削除中にエラーが発生しました。",
|
||||
"deletingTitle": "{{title}} を削除する際にエラーが発生しました。接続を確認してからもう一度お試しください。",
|
||||
"emailOrPasswordIncorrect": "メールアドレス、または、パスワードが正しくありません。",
|
||||
"followingFieldsInvalid_many": "次のフィールドは無効です:",
|
||||
@@ -81,6 +82,8 @@
|
||||
"problemUploadingFile": "ファイルのアップロード中に問題が発生しました。",
|
||||
"tokenInvalidOrExpired": "トークンが無効、または、有効期限が切れています。",
|
||||
"unPublishingDocument": "このデータを非公開する際に問題が発生しました。",
|
||||
"unableToDeleteCount": "{{total}} {{label}} から {{count}} を削除できません。",
|
||||
"unableToUpdateCount": "{{total}} {{label}} のうち {{count}} 個を更新できません。",
|
||||
"unauthorized": "認証されていません。このリクエストを行うにはログインが必要です。",
|
||||
"unknown": "不明なエラーが発生しました。",
|
||||
"unspecific": "エラーが発生しました。",
|
||||
@@ -89,27 +92,34 @@
|
||||
"verificationTokenInvalid": "認証トークンが無効です。"
|
||||
},
|
||||
"fields": {
|
||||
"block": "ブロック",
|
||||
"blocks": "ブロック",
|
||||
"addLabel": "{{label}} を追加",
|
||||
"addLink": "リンクを追加",
|
||||
"addNew": "新規追加",
|
||||
"addNewLabel": "{{label}} を新規追加",
|
||||
"addRelationship": "リレーションシップを追加",
|
||||
"addUpload": "アップロードを追加",
|
||||
"block": "ブロック",
|
||||
"blockType": "ブロックタイプ",
|
||||
"blocks": "ブロック",
|
||||
"chooseBetweenCustomTextOrDocument": "",
|
||||
"chooseDocumentToLink": "",
|
||||
"chooseFromExisting": "既存から選択",
|
||||
"chooseLabel": "{{label}} を選択",
|
||||
"collapseAll": "すべて閉じる",
|
||||
"customURL": "カスタムURL",
|
||||
"editLabelData": "{{label}} データを編集",
|
||||
"editLink": "リンクを編集",
|
||||
"editRelationship": "リレーションシップを編集",
|
||||
"enterURL": "URL を入力してください",
|
||||
"internalLink": "内部リンク",
|
||||
"itemsAndMore": "{{items}} 他{{count}}件",
|
||||
"labelRelationship": "{{label}} リレーションシップ",
|
||||
"latitude": "緯度",
|
||||
"linkType": "リンクタイプ",
|
||||
"linkedTo": "<0>{{label}}</0> にリンク",
|
||||
"longitude": "経度",
|
||||
"newLabel": "新規 {{label}}",
|
||||
"openInNewTab": "新しいタブで開く",
|
||||
"passwordsDoNotMatch": "パスワードが一致しません",
|
||||
"relatedDocument": "リレーションデータ",
|
||||
"relationTo": "リレーション",
|
||||
@@ -118,9 +128,11 @@
|
||||
"saveChanges": "変更を保存",
|
||||
"searchForBlock": "ブロックを検索",
|
||||
"selectExistingLabel": "既存 {{label}} を選択",
|
||||
"selectFieldsToEdit": "編集するフィールドを選択",
|
||||
"showAll": "すべて開く",
|
||||
"swapRelationship": "スワップ関係",
|
||||
"swapUpload": "差し替え",
|
||||
"textToDisplay": "",
|
||||
"toggleBlock": "ブロックを切り替え",
|
||||
"uploadNewLabel": "新規 {{label}} アップロード"
|
||||
},
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
"accountAlreadyActivated": "ဤအကောင့်ကို အသက်သွင်းပြီးဖြစ်သည်။",
|
||||
"autosaving": "ဖိုင်ကို အလိုအလျောက်သိမ်းဆည်းရာတွင် ပြဿနာတစ်ခုရှိနေသည်။",
|
||||
"correctInvalidFields": "ကျေးဇူးပြု၍ အချက်အလက်များကို ပြန်လည် စစ်ဆေးပါ။",
|
||||
"deletingFile": "ဖိုင်ကိုဖျက်ရာတွင် အမှားအယွင်းရှိနေသည်။",
|
||||
"deletingTitle": "{{title}} ကို ဖျက်ရာတွင် အမှားအယွင်းရှိခဲ့သည်။ သင့် အင်တာနက်လိုင်းအား စစ်ဆေးပြီး ထပ်မံကြို့စားကြည့်ပါ။",
|
||||
"emailOrPasswordIncorrect": "ထည့်သွင်းထားသော အီးမေးလ် သို့မဟုတ် စကားဝှက်သည် မမှန်ပါ။",
|
||||
"followingFieldsInvalid_many": "ထည့်သွင်းထားသော အချက်အလက်များသည် မမှန်ကန်ပါ။",
|
||||
@@ -81,6 +82,8 @@
|
||||
"problemUploadingFile": "ဖိုင်ကို အပ်လုဒ်တင်ရာတွင် ပြဿနာရှိနေသည်။",
|
||||
"tokenInvalidOrExpired": "တိုကင်သည် မမှန်ကန်ပါ သို့မဟုတ် သက်တမ်းကုန်သွားပါပြီ။",
|
||||
"unPublishingDocument": "ဖိုင်ကို ပြန်လည့် သိမ်းဆည်းခြင်းမှာ ပြဿနာရှိနေသည်။",
|
||||
"unableToDeleteCount": "{{total}} {{label}} မှ {{count}} ကို ဖျက်၍မရပါ။",
|
||||
"unableToUpdateCount": "{{total}} {{label}} မှ {{count}} ကို အပ်ဒိတ်လုပ်၍မရပါ။",
|
||||
"unauthorized": "အခွင့်မရှိပါ။ ဤတောင်းဆိုချက်ကို လုပ်ဆောင်နိုင်ရန် သင်သည် လော့ဂ်အင်ဝင်ရပါမည်။",
|
||||
"unknown": "ဘာမှန်းမသိသော error တက်သွားပါသည်။",
|
||||
"unspecific": "Error တက်နေပါသည်။",
|
||||
@@ -98,18 +101,25 @@
|
||||
"block": "ဘလောက်",
|
||||
"blockType": "ဘလောက် အမျိုးအစား",
|
||||
"blocks": "ဘလောက်များ",
|
||||
"chooseBetweenCustomTextOrDocument": "စိတ်ကြိုက်စာသား URL ကိုထည့်ခြင်း သို့မဟုတ် အခြားစာရွက်စာတမ်းတစ်ခုသို့ လင့်ခ်ချိတ်ခြင်းအကြား ရွေးချယ်ပါ။",
|
||||
"chooseDocumentToLink": "ချိတ်ဆက်ရန် စာရွက်စာတမ်းကို ရွေးပါ။",
|
||||
"chooseFromExisting": "ရှိပြီးသားထဲကပဲ ရွေးချယ်ပါ။",
|
||||
"chooseLabel": "{{label}} အားရွေးချယ်ပါ။",
|
||||
"collapseAll": "အားလုံးကို ခေါက်သိမ်းပါ။",
|
||||
"customURL": "စိတ်ကြိုက် URL",
|
||||
"editLabelData": "ဒေတာ {{label}} ကို တည်းဖြတ်ပါ။",
|
||||
"editLink": "လင့်ခ်ကို တည်းဖြတ်ပါ။",
|
||||
"editRelationship": "Relationship ကို တည်းဖြတ်ပါ။",
|
||||
"enterURL": "URL တစ်ခုထည့်ပါ။",
|
||||
"internalLink": "Internal Link",
|
||||
"itemsAndMore": "{{items}} နှင့် နောက်ထပ် {{count}} ခု",
|
||||
"labelRelationship": "{{label}} Relationship",
|
||||
"latitude": "vĩ độ",
|
||||
"linkType": "လင့်အမျိုးအစား",
|
||||
"linkedTo": "<0>{{label}}</0> ချိတ်ဆက်ထားသည်။",
|
||||
"longitude": "kinh độ",
|
||||
"newLabel": "{{label}} အသစ်",
|
||||
"openInNewTab": "တက်ဘ်အသစ်တွင် ဖွင့်ပါ။",
|
||||
"passwordsDoNotMatch": "စကားဝှက်များနှင့် မကိုက်ညီပါ။",
|
||||
"relatedDocument": "ဆက်စပ် ဖိုင်",
|
||||
"relationTo": "ဆက်စပ်မှု",
|
||||
@@ -118,18 +128,24 @@
|
||||
"saveChanges": "သိမ်းဆည်းမည်။",
|
||||
"searchForBlock": "ဘလောက်တစ်ခုရှာမည်။",
|
||||
"selectExistingLabel": "ရှိပြီးသား {{label}} ကို ရွေးပါ",
|
||||
"selectFieldsToEdit": "တည်းဖြတ်ရန် အကွက်များကို ရွေးပါ။",
|
||||
"showAll": "အကုန် ကြည့်မည်။",
|
||||
"swapRelationship": "လဲလှယ်ဆက်ဆံရေး",
|
||||
"swapUpload": "အပ်လုဒ်ဖလှယ်ပါ။",
|
||||
"textToDisplay": "ပြသရန် စာသား",
|
||||
"toggleBlock": "Toggle block",
|
||||
"uploadNewLabel": "{{label}} အသစ်တင်မည်။"
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "{{label}} <1>{{title}}</1> ကို ဖျက်ပါတော့မည်။ သေချာပြီလား။ ဖျက်ပြီးရင် ပြန်မရဘူးနော်။",
|
||||
"aboutToDeleteCount_many": "သင်သည် {{count}} {{label}} ကို ဖျက်ပါတော့မည်။",
|
||||
"aboutToDeleteCount_one": "သင်သည် {{count}} {{label}} ကို ဖျက်ပါတော့မည်။",
|
||||
"aboutToDeleteCount_other": "သင်သည် {{count}} {{label}} ကို ဖျက်ပါတော့မည်။",
|
||||
"addBelow": "အောက်တွင်ထည့်ပါ။",
|
||||
"addFilter": "ဇကာထည့်ပါ။",
|
||||
"adminTheme": "Admin Theme",
|
||||
"and": "နှင့်",
|
||||
"ascending": "တက်နေသည်",
|
||||
"automatic": "အော်တို",
|
||||
"backToDashboard": "ပင်မစာမျက်နှာသို့ ပြန်သွားမည်။",
|
||||
"cancel": "မလုပ်တော့ပါ။",
|
||||
@@ -152,6 +168,7 @@
|
||||
"dark": "အမှောင်",
|
||||
"dashboard": "ပင်မစာမျက်နှာ",
|
||||
"delete": "ဖျက်မည်။",
|
||||
"deletedCountSuccessfully": "{{count}} {{label}} ကို အောင်မြင်စွာ ဖျက်လိုက်ပါပြီ။",
|
||||
"deletedSuccessfully": "အောင်မြင်စွာ ဖျက်လိုက်ပါပြီ။",
|
||||
"deleting": "ဖျက်နေဆဲ ...",
|
||||
"descending": "Descending",
|
||||
@@ -160,6 +177,9 @@
|
||||
"edit": "တည်းဖြတ်ပါ။",
|
||||
"editLabel": "{{label}} ပြင်ဆင်မည်။",
|
||||
"editing": "ပြင်ဆင်နေသည်။",
|
||||
"editingLabel_many": "တည်းဖြတ်ခြင်း {{count}} {{label}}",
|
||||
"editingLabel_one": "တည်းဖြတ်ခြင်း {{count}} {{label}}",
|
||||
"editingLabel_other": "တည်းဖြတ်ခြင်း {{count}} {{label}}",
|
||||
"email": "အီးမေးလ်",
|
||||
"emailAddress": "အီးမေးလ် လိပ်စာ",
|
||||
"enterAValue": "တန်ဖိုးတစ်ခုထည့်ပါ။",
|
||||
@@ -198,7 +218,9 @@
|
||||
"save": "သိမ်းဆည်းမည်။",
|
||||
"saving": "သိမ်းနေဆဲ ...",
|
||||
"searchBy": "ရှာဖွေပါ။",
|
||||
"selectAll": "{{count}} {{label}} အားလုံးကို ရွေးပါ",
|
||||
"selectValue": "တစ်ခုခုကို ရွေးချယ်ပါ။",
|
||||
"selectedCount": "{{count}} {{label}} ကို ရွေးထားသည်။",
|
||||
"sorryNotFound": "ဝမ်းနည်းပါသည်။ သင်ရှာနေတဲ့ဟာ ဒီမှာမရှိပါ။",
|
||||
"sort": "အစဉ်လိုက်",
|
||||
"stayOnThisPage": "ဒီမှာပဲ ဆက်နေမည်။",
|
||||
@@ -212,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "သင့်တွင် မသိမ်းဆည်းရသေးသော ပြောင်းလဲမှုများ ရှိနေပါသည်။ ပုံတူပွားမှာ သေချာပြီလား။",
|
||||
"untitled": "ခေါင်းစဥ်မဲ့",
|
||||
"updatedAt": "ပြင်ဆင်ခဲ့သည့်အချိန်",
|
||||
"updatedCountSuccessfully": "{{count}} {{label}} ကို အောင်မြင်စွာ အပ်ဒိတ်လုပ်ခဲ့သည်။",
|
||||
"updatedSuccessfully": "အပ်ဒိတ်လုပ်ပြီးပါပြီ။",
|
||||
"updating": "ပြင်ဆင်ရန်",
|
||||
"uploading": "တင်ပေးနေသည်",
|
||||
@@ -220,20 +243,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": "ဖိုင် အရွယ်အစား",
|
||||
@@ -242,14 +266,13 @@
|
||||
"moreInfo": "More info",
|
||||
"selectCollectionToBrowse": "စုစည်းမှု တစ်ခုခုကို ရွေးချယ်ပါ။",
|
||||
"selectFile": "ဖိုင်ရွေးပါ။",
|
||||
"dragAndDrop": "ဖိုင်တစ်ဖိုင်ကို ဆွဲချလိုက်ပါ။",
|
||||
"sizes": "အရွယ်အစားများ",
|
||||
"width": "အကျယ်"
|
||||
},
|
||||
"validation": {
|
||||
"fieldHasNo": "ဤအကွက်တွင် {{label}} မရှိပါ။",
|
||||
"emailAddress": "မှန်ကန်သော အီးမေးလ်လိပ်စာကို ထည့်သွင်းပါ။",
|
||||
"enterNumber": "မှန်ကန်သောနံပါတ်တစ်ခုထည့်ပါ။",
|
||||
"fieldHasNo": "ဤအကွက်တွင် {{label}} မရှိပါ။",
|
||||
"greaterThanMax": "\"{{value}}\" သည် {{max}} ၏ အများဆုံးခွင့်ပြုထားသော တန်ဖိုးထက် ကြီးသည်။",
|
||||
"invalidInput": "ဤအကွက်တွင် မမှန်ကန်သော ထည့်သွင်းမှုတစ်ခုရှိသည်။",
|
||||
"invalidSelection": "ဤအကွက်တွင် မမှန်ကန်သော ရွေးချယ်မှုတစ်ခုရှိသည်။",
|
||||
@@ -266,15 +289,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": "ဗားရှင်းပြန်လည် အသုံးပြုခြင်းကို အတည်ပြုပါ။",
|
||||
@@ -286,6 +312,7 @@
|
||||
"noRowsFound": "{{label}} အားမတွေ့ပါ။",
|
||||
"preview": "နမူနာပြရန်",
|
||||
"problemRestoringVersion": "ဤဗားရှင်းကို ပြန်လည်ရယူရာတွင် ပြဿနာရှိနေသည်။",
|
||||
"publish": "ထုတ်ဝေသည်။",
|
||||
"publishChanges": "အပြောင်းအလဲများကို တင်ခဲ့သည်။",
|
||||
"published": "တင်ပြီးပြီ။",
|
||||
"restoreThisVersion": "ဤဗားရှင်းကိုကို ပြန်ယူမည်။",
|
||||
@@ -297,6 +324,7 @@
|
||||
"selectLocales": "ပြသရန် ဒေသန္တရများကို ရွေးပါ။",
|
||||
"selectVersionToCompare": "နှိုင်းယှဉ်ရန် ဗားရှင်းကို ရွေးပါ။",
|
||||
"showLocales": "ဒေသန္တရများကိုပြပါ။:",
|
||||
"showingVersionsFor": "အတွက် ဗားရှင်းများကို ပြသနေသည်-",
|
||||
"status": "အခြေအနေ",
|
||||
"type": "အမျိုးအစား",
|
||||
"unpublish": "ပြန်ဖြုတ်မည်။",
|
||||
@@ -305,6 +333,7 @@
|
||||
"versionCount_many": "{{count}} ဗားရှင်းများကို တွေ့ပါသည်။",
|
||||
"versionCount_none": "ဗားရှင်းရှာဖွေ့ပါ။",
|
||||
"versionCount_one": "{{count}} ဗားရှင်အား တွေ့ပါသည်။",
|
||||
"versionCount_other": "ဗားရှင်း {{count}} ခု တွေ့ရှိပါသည်။",
|
||||
"versionCreatedOn": "{{version}} အား ဖန်တီးခဲ့သည်။",
|
||||
"versionID": "ဗားရှင်း ID",
|
||||
"versions": "ဗားရှင်းများ",
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "Det oppstod et problem under opplasting av filen.",
|
||||
"tokenInvalidOrExpired": "Token er enten ugyldig eller har utløpt.",
|
||||
"unPublishingDocument": "Det oppstod et problem under avpublisering av dokumentet.",
|
||||
"unableToDeleteCount": "Kan ikke slette {{count}} av {{total}} {{label}}.",
|
||||
"unableToUpdateCount": "Kan ikke oppdatere {{count}} av {{total}} {{label}}.",
|
||||
"unauthorized": "Uautorisert, du må være innlogget for å gjøre denne forespørselen.",
|
||||
"unknown": "En ukjent feil har oppstått.",
|
||||
"unspecific": "En feil har oppstått.",
|
||||
@@ -126,6 +128,7 @@
|
||||
"saveChanges": "Lagre endringer",
|
||||
"searchForBlock": "Søk etter en blokk",
|
||||
"selectExistingLabel": "Velg eksisterende {{label}}",
|
||||
"selectFieldsToEdit": "Velg felt som skal redigeres",
|
||||
"showAll": "Vis alle",
|
||||
"swapRelationship": "Bytte Forhold",
|
||||
"swapUpload": "Bytt Opplasting",
|
||||
@@ -135,10 +138,14 @@
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "Du er i ferd med å slette {{label}} <1>{{title}}</1>. Er du sikker?",
|
||||
"aboutToDeleteCount_many": "Du er i ferd med å slette {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "Du er i ferd med å slette {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "Du er i ferd med å slette {{count}} {{label}}",
|
||||
"addBelow": "Legg til under",
|
||||
"addFilter": "Legg til filter",
|
||||
"adminTheme": "Admin-tema",
|
||||
"and": "Og",
|
||||
"ascending": "Stigende",
|
||||
"automatic": "Automatisk",
|
||||
"backToDashboard": "Tilbake til kontrollpanel",
|
||||
"cancel": "Avbryt",
|
||||
@@ -161,6 +168,7 @@
|
||||
"dark": "Mørk",
|
||||
"dashboard": "Kontrollpanel",
|
||||
"delete": "Slett",
|
||||
"deletedCountSuccessfully": "Slettet {{count}} {{label}}.",
|
||||
"deletedSuccessfully": "Slettet.",
|
||||
"deleting": "Sletter...",
|
||||
"descending": "Synkende",
|
||||
@@ -169,6 +177,9 @@
|
||||
"edit": "Redigere",
|
||||
"editLabel": "Rediger {{label}}",
|
||||
"editing": "Redigerer",
|
||||
"editingLabel_many": "Redigerer {{count}} {{label}}",
|
||||
"editingLabel_one": "Redigerer {{count}} {{label}}",
|
||||
"editingLabel_other": "Redigerer {{count}} {{label}}",
|
||||
"email": "E-post",
|
||||
"emailAddress": "E-postadresse",
|
||||
"enterAValue": "Skriv inn en verdi",
|
||||
@@ -207,7 +218,9 @@
|
||||
"save": "Lagre",
|
||||
"saving": "Lagrer...",
|
||||
"searchBy": "Søk etter {{label}}",
|
||||
"selectAll": "Velg alle {{count}} {{label}}",
|
||||
"selectValue": "Velg en verdi",
|
||||
"selectedCount": "{{count}} {{label}} valgt",
|
||||
"sorryNotFound": "Beklager, det er ingenting som samsvarer med forespørselen din.",
|
||||
"sort": "Sortér",
|
||||
"stayOnThisPage": "Bli på denne siden",
|
||||
@@ -221,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "Du har ulagrede endringer. Vil du fortsette å duplisere?",
|
||||
"untitled": "Uten tittel",
|
||||
"updatedAt": "Oppdatert",
|
||||
"updatedCountSuccessfully": "Oppdaterte {{count}} {{label}} vellykket.",
|
||||
"updatedSuccessfully": "Oppdatert.",
|
||||
"updating": "Oppdatering",
|
||||
"uploading": "Opplasting",
|
||||
@@ -229,20 +243,21 @@
|
||||
"welcome": "Velkommen"
|
||||
},
|
||||
"operators": {
|
||||
"contains": "contains",
|
||||
"equals": "lik",
|
||||
"isNotEqualTo": "er ikke lik",
|
||||
"isIn": "er i",
|
||||
"isNotIn": "er ikke med",
|
||||
"exists": "eksisterer",
|
||||
"isGreaterThan": "er større enn",
|
||||
"isGreaterThanOrEqualTo": "er større enn eller lik",
|
||||
"isIn": "er i",
|
||||
"isLessThan": "er mindre enn",
|
||||
"isLessThanOrEqualTo": "er mindre enn eller lik",
|
||||
"isGreaterThanOrEqualTo": "er større enn eller lik",
|
||||
"near": "nær",
|
||||
"isLike": "er som",
|
||||
"contains": "contains"
|
||||
"isNotEqualTo": "er ikke lik",
|
||||
"isNotIn": "er ikke med",
|
||||
"near": "nær"
|
||||
},
|
||||
"upload": {
|
||||
"dragAndDrop": "Dra og slipp en fil",
|
||||
"dragAndDropHere": "eller dra og slipp en fil her",
|
||||
"fileName": "Filnavn",
|
||||
"fileSize": "Filstørrelse",
|
||||
@@ -251,7 +266,6 @@
|
||||
"moreInfo": "Mer info",
|
||||
"selectCollectionToBrowse": "Velg en samling å bla i",
|
||||
"selectFile": "Velg en fil",
|
||||
"dragAndDrop": "Dra og slipp en fil",
|
||||
"sizes": "Størrelser",
|
||||
"width": "Bredde"
|
||||
},
|
||||
@@ -275,15 +289,18 @@
|
||||
"validUploadID": "Dette feltet er ikke en gyldig opplastings-ID."
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "Du er i ferd med å publisere alle {{label}} i utvalget. Er du sikker?",
|
||||
"aboutToRestore": "Du er i ferd med å gjenopprette denne {{label}} dokumentet til tilstanden det var i på {{versionDate}}.",
|
||||
"aboutToRestoreGlobal": "Du er i ferd med å gjenopprette den globale variabelen {{label}} til tilstanden det var i på {{versionDate}}.",
|
||||
"aboutToRevertToPublished": "Du er i ferd med å tilbakestille endringene i dette dokumentet til den publiserte tilstanden. Er du sikker?",
|
||||
"aboutToUnpublish": "Du er i ferd med å avpublisere dette dokumentet. Er du sikker?",
|
||||
"aboutToUnpublishSelection": "Du er i ferd med å oppheve publiseringen av alle {{label}} i utvalget. Er du sikker?",
|
||||
"autosave": "Lagre automatisk",
|
||||
"autosavedSuccessfully": "Lagret automatisk.",
|
||||
"autosavedVersion": "Automatisk lagret versjon",
|
||||
"changed": "Endret",
|
||||
"compareVersion": "Sammenlign versjon mot:",
|
||||
"confirmPublish": "Bekreft publisering",
|
||||
"confirmRevertToSaved": "Bekreft tilbakestilling til lagret",
|
||||
"confirmUnpublish": "Bekreft avpublisering",
|
||||
"confirmVersionRestoration": "Bekreft versjon-gjenoppretting",
|
||||
@@ -295,6 +312,7 @@
|
||||
"noRowsFound": "Ingen {{label}} funnet",
|
||||
"preview": "Forhåndsvisning",
|
||||
"problemRestoringVersion": "Det oppstod et problem med gjenoppretting av denne versjonen",
|
||||
"publish": "Publisere",
|
||||
"publishChanges": "Publiser endringer",
|
||||
"published": "Publisert",
|
||||
"restoreThisVersion": "Gjenopprett denne versjonen",
|
||||
@@ -305,8 +323,8 @@
|
||||
"saveDraft": "Lagre utkast",
|
||||
"selectLocales": "Velg språk å vise",
|
||||
"selectVersionToCompare": "Velg en versjon å sammenligne",
|
||||
"showingVersionsFor": "Viser versjoner for:",
|
||||
"showLocales": "Vis språk:",
|
||||
"showingVersionsFor": "Viser versjoner for:",
|
||||
"status": "Status",
|
||||
"type": "Type",
|
||||
"unpublish": "Avpubliser",
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "Er was een probleem bij het uploaden van het bestand.",
|
||||
"tokenInvalidOrExpired": "Token is ongeldig of verlopen.",
|
||||
"unPublishingDocument": "Er was een probleem met het depubliceren van dit document.",
|
||||
"unableToDeleteCount": "Kan {{count}} van {{total}} {{label}} niet verwijderen.",
|
||||
"unableToUpdateCount": "Kan {{count}} van {{total}} {{label}} niet updaten.",
|
||||
"unauthorized": "Ongeautoriseerd, u moet ingelogd zijn om dit verzoek te doen.",
|
||||
"unknown": "Er is een onbekende fout opgetreden.",
|
||||
"unspecific": "Er is een fout opgetreden.",
|
||||
@@ -90,27 +92,34 @@
|
||||
"verificationTokenInvalid": "Verificatietoken is ongeldig."
|
||||
},
|
||||
"fields": {
|
||||
"block": "blok",
|
||||
"blocks": "blokken",
|
||||
"addLabel": "Voeg {{label}} toe",
|
||||
"addLink": "Voeg een link toe",
|
||||
"addNew": "Nieuw(e)",
|
||||
"addNewLabel": "Nieuw(e) {{label}} toevoegen",
|
||||
"addRelationship": "Nieuwe Relatie",
|
||||
"addUpload": "Upload Toevoegen",
|
||||
"block": "blok",
|
||||
"blockType": "Bloktype",
|
||||
"blocks": "blokken",
|
||||
"chooseBetweenCustomTextOrDocument": "Kies tussen het invoeren van een aangepaste tekst-URL of een koppeling naar een ander document.",
|
||||
"chooseDocumentToLink": "Kies een document om naar te linken",
|
||||
"chooseFromExisting": "Kies uit bestaande",
|
||||
"chooseLabel": "Kies {{label}}",
|
||||
"collapseAll": "Alles samenvouwen",
|
||||
"customURL": "Eigen URL",
|
||||
"editLabelData": "Bewerk gegevens van {{label}}",
|
||||
"editLink": "Link bewerken",
|
||||
"editRelationship": "Relatie Relatie",
|
||||
"enterURL": "Voer een URL in",
|
||||
"internalLink": "Interne koppeling",
|
||||
"itemsAndMore": "{{items}} en {{count}} meer",
|
||||
"labelRelationship": "{{label}} relatie",
|
||||
"latitude": "Breedtegraad",
|
||||
"linkType": "Koppelingstype",
|
||||
"linkedTo": "Gekoppeld aan aan <0>{{label}}</0>",
|
||||
"longitude": "Lengtegraad",
|
||||
"newLabel": "Nieuw(e) {{label}}",
|
||||
"openInNewTab": "Openen in nieuw tabblad",
|
||||
"passwordsDoNotMatch": "Wachtwoorden komen niet overeen.",
|
||||
"relatedDocument": "Gerelateerd document",
|
||||
"relationTo": "Relatie tot",
|
||||
@@ -119,18 +128,24 @@
|
||||
"saveChanges": "Bewaar aanpassingen",
|
||||
"searchForBlock": "Zoeken naar een blok",
|
||||
"selectExistingLabel": "Selecteer bestaand(e) {{label}}",
|
||||
"selectFieldsToEdit": "Selecteer velden om te bewerken",
|
||||
"showAll": "Alles tonen",
|
||||
"swapRelationship": "Relatie Wisselen",
|
||||
"swapUpload": "Upload Verwisselen",
|
||||
"textToDisplay": "Tekst om weer te geven",
|
||||
"toggleBlock": "Blok togglen",
|
||||
"uploadNewLabel": "Upload nieuw(e) {{label}}"
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "U staat op het punt om {{label}} <1>{{title}}</1> te verwijderen. Weet u het zeker?",
|
||||
"aboutToDeleteCount_many": "Je staat op het punt {{count}} {{label}} te verwijderen",
|
||||
"aboutToDeleteCount_one": "Je staat op het punt {{count}} {{label}} te verwijderen",
|
||||
"aboutToDeleteCount_other": "Je staat op het punt {{count}} {{label}} te verwijderen",
|
||||
"addBelow": "Onderaan toevoegen",
|
||||
"addFilter": "Filter toevoegen",
|
||||
"adminTheme": "Adminthema",
|
||||
"and": "En",
|
||||
"ascending": "Oplopend",
|
||||
"automatic": "Automatisch",
|
||||
"backToDashboard": "Terug naar dashboard",
|
||||
"cancel": "Annuleren",
|
||||
@@ -153,6 +168,7 @@
|
||||
"dark": "Donker",
|
||||
"dashboard": "Dashboard",
|
||||
"delete": "Verwijderen",
|
||||
"deletedCountSuccessfully": "{{count}} {{label}} succesvol verwijderd.",
|
||||
"deletedSuccessfully": "Succesvol verwijderd.",
|
||||
"deleting": "Verwijderen...",
|
||||
"descending": "Aflopend",
|
||||
@@ -161,6 +177,9 @@
|
||||
"edit": "Bewerk",
|
||||
"editLabel": "Bewerk {{label}}",
|
||||
"editing": "Bewerken",
|
||||
"editingLabel_many": "Bewerken {{count}} {{label}}",
|
||||
"editingLabel_one": "Bewerken {{count}} {{label}}",
|
||||
"editingLabel_other": "Bewerken {{count}} {{label}}",
|
||||
"email": "E-mail",
|
||||
"emailAddress": "E-maildres",
|
||||
"enterAValue": "Waarde invoeren",
|
||||
@@ -199,7 +218,9 @@
|
||||
"save": "Bewaar",
|
||||
"saving": "Bewaren...",
|
||||
"searchBy": "Zoeken op {{label}}",
|
||||
"selectAll": "Alles selecteren {{count}} {{label}}",
|
||||
"selectValue": "Selecteer een waarde",
|
||||
"selectedCount": "{{count}} {{label}} geselecteerd",
|
||||
"sorryNotFound": "Sorry, er is niets dat overeen komt met uw verzoek.",
|
||||
"sort": "Sorteer",
|
||||
"stayOnThisPage": "Blijf op deze pagina",
|
||||
@@ -213,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "U heeft onbewaarde wijzigingen. Wilt u doorgaan met dupliceren?",
|
||||
"untitled": "Zonder titel",
|
||||
"updatedAt": "Aangepast op",
|
||||
"updatedCountSuccessfully": "{{count}} {{label}} succesvol bijgewerkt.",
|
||||
"updatedSuccessfully": "Succesvol aangepast.",
|
||||
"updating": "Bijwerken",
|
||||
"uploading": "Uploaden",
|
||||
@@ -221,20 +243,21 @@
|
||||
"welcome": "Welkom"
|
||||
},
|
||||
"operators": {
|
||||
"contains": "bevat",
|
||||
"equals": "is gelijk aan",
|
||||
"isNotEqualTo": "is niet gelijk aan",
|
||||
"isIn": "is binnen",
|
||||
"isNotIn": "zit er niet in",
|
||||
"exists": "bestaat",
|
||||
"isGreaterThan": "is groter dan",
|
||||
"isGreaterThanOrEqualTo": "is groter dan of gelijk aan",
|
||||
"isIn": "is binnen",
|
||||
"isLessThan": "is kleiner dan",
|
||||
"isLessThanOrEqualTo": "is kleiner dan of gelijk aan",
|
||||
"isGreaterThanOrEqualTo": "is groter dan of gelijk aan",
|
||||
"near": "nabij",
|
||||
"isLike": "is als",
|
||||
"contains": "bevat"
|
||||
"isNotEqualTo": "is niet gelijk aan",
|
||||
"isNotIn": "zit er niet in",
|
||||
"near": "nabij"
|
||||
},
|
||||
"upload": {
|
||||
"dragAndDrop": "Sleep een bestand",
|
||||
"dragAndDropHere": "of sleep een bestand naar hier",
|
||||
"fileName": "Bestandsnaam",
|
||||
"fileSize": "Bestandsgrootte",
|
||||
@@ -243,7 +266,6 @@
|
||||
"moreInfo": "Meer info",
|
||||
"selectCollectionToBrowse": "Selecteer een collectie om door te bladeren",
|
||||
"selectFile": "Selecteer een bestand",
|
||||
"dragAndDrop": "Sleep een bestand",
|
||||
"sizes": "Groottes",
|
||||
"width": "Breedte"
|
||||
},
|
||||
@@ -267,15 +289,18 @@
|
||||
"validUploadID": "Dit veld is geen geldige upload-ID."
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "Je staat op het punt om alle {{label}} in de selectie te publiceren. Weet je het zeker?",
|
||||
"aboutToRestore": "U staat op het punt dit {{label}} document te herstellen in de staat waarin het zich bevond op {{versionDate}}.",
|
||||
"aboutToRestoreGlobal": "U staat op het punt om de global {{label}} te herstellen in de staat waarin het zich bevond op {{versionDate}}.",
|
||||
"aboutToRevertToPublished": "U staat op het punt om de wijzigingen van dit document terug te draaien naar de gepubliceerde staat. Weet u het zeker?",
|
||||
"aboutToUnpublish": "U staat op het punt om de publicatie van dit document ongedaan te maken. Weet u het zeker?",
|
||||
"aboutToUnpublishSelection": "You are about to unpublish all {{label}} in the selection. Are you sure?",
|
||||
"autosave": "Automatisch bewaren",
|
||||
"autosavedSuccessfully": "Succesvol automatisch bewaard.",
|
||||
"autosavedVersion": "Automatisch bewaarde versie",
|
||||
"changed": "Gewijzigd",
|
||||
"compareVersion": "Vergelijk versie met:",
|
||||
"confirmPublish": "Bevestig publiceren",
|
||||
"confirmRevertToSaved": "Bevestig terugdraaien naar bewaarde versie",
|
||||
"confirmUnpublish": "Bevestig depubliceren",
|
||||
"confirmVersionRestoration": "Bevestig te herstellen versie",
|
||||
@@ -287,6 +312,7 @@
|
||||
"noRowsFound": "Geen {{label}} gevonden",
|
||||
"preview": "Voorbeeld",
|
||||
"problemRestoringVersion": "Er was een probleem bij het herstellen van deze versie",
|
||||
"publish": "Publiceren",
|
||||
"publishChanges": "Publiceer wijzigingen",
|
||||
"published": "Gepubliceerd",
|
||||
"restoreThisVersion": "Herstel deze versie",
|
||||
@@ -298,6 +324,7 @@
|
||||
"selectLocales": "Selecteer locales om weer te geven",
|
||||
"selectVersionToCompare": "Selecteer een versie om te vergelijken",
|
||||
"showLocales": "Toon locales:",
|
||||
"showingVersionsFor": "Versies tonen voor:",
|
||||
"status": "Status",
|
||||
"type": "Type",
|
||||
"unpublish": "Publicatie ongedaan maken",
|
||||
@@ -306,6 +333,7 @@
|
||||
"versionCount_many": "{{count}} versies gevonden",
|
||||
"versionCount_none": "Geen versies gevonden",
|
||||
"versionCount_one": "{{count}} versie gevonden",
|
||||
"versionCount_other": "{{count}} versies gevonden",
|
||||
"versionCreatedOn": "{{version}} aangemaakt op:",
|
||||
"versionID": "Versie-ID",
|
||||
"versions": "Versies",
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
"accountAlreadyActivated": "To konto zostało już aktywowane.",
|
||||
"autosaving": "Wystąpił problem podczas automatycznego zapisywania tego dokumentu.",
|
||||
"correctInvalidFields": "Popraw nieprawidłowe pola.",
|
||||
"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_many": "Następujące pola są nieprawidłowe:",
|
||||
@@ -81,6 +82,8 @@
|
||||
"problemUploadingFile": "Wystąpił problem podczas przesyłania pliku.",
|
||||
"tokenInvalidOrExpired": "Token jest nieprawidłowy lub wygasł.",
|
||||
"unPublishingDocument": "Wystąpił problem podczas cofania publikacji tego dokumentu.",
|
||||
"unableToDeleteCount": "Nie można usunąć {{count}} z {{total}} {{label}}.",
|
||||
"unableToUpdateCount": "Nie można zaktualizować {{count}} z {{total}} {{label}}.",
|
||||
"unauthorized": "Brak dostępu, musisz być zalogowany.",
|
||||
"unknown": "Wystąpił nieznany błąd.",
|
||||
"unspecific": "Wystąpił błąd",
|
||||
@@ -89,27 +92,34 @@
|
||||
"verificationTokenInvalid": "Token weryfikacyjny jest nieprawidłowy."
|
||||
},
|
||||
"fields": {
|
||||
"block": "Blok",
|
||||
"blocks": "Bloki",
|
||||
"addLabel": "Dodaj {{label}}",
|
||||
"addLink": "Dodaj Link",
|
||||
"addNew": "Dodaj nowy",
|
||||
"addNewLabel": "Dodaj nowy {{label}}",
|
||||
"addRelationship": "Dodaj Relacje",
|
||||
"addUpload": "Dodaj ładowanie",
|
||||
"block": "Blok",
|
||||
"blockType": "Typ Bloku",
|
||||
"blocks": "Bloki",
|
||||
"chooseBetweenCustomTextOrDocument": "Wybierz między wprowadzeniem niestandardowego tekstowego adresu URL a linkiem do innego dokumentu.",
|
||||
"chooseDocumentToLink": "Wybierz dokument, do którego chcesz utworzyć łącze",
|
||||
"chooseFromExisting": "Wybierz z istniejących",
|
||||
"chooseLabel": "Wybierz {{label}}",
|
||||
"collapseAll": "Zwiń wszystko",
|
||||
"customURL": "Niestandardowy adres URL",
|
||||
"editLabelData": "Edytuj dane {{label}}",
|
||||
"editLink": "Edytuj Link",
|
||||
"editRelationship": "Edytuj Relacje",
|
||||
"enterURL": "Wpisz adres URL",
|
||||
"internalLink": "Link wewnętrzny",
|
||||
"itemsAndMore": "{{items}} i {{count}} więcej",
|
||||
"labelRelationship": "Relacja {{label}}",
|
||||
"latitude": "Szerokość",
|
||||
"linkType": "Typ łącza",
|
||||
"linkedTo": "Połączony z <0>{{etykietą}}</0>",
|
||||
"longitude": "Długość geograficzna",
|
||||
"newLabel": "Nowy {{label}}",
|
||||
"openInNewTab": "Otwórz w nowej karcie",
|
||||
"passwordsDoNotMatch": "Hasła nie pasują",
|
||||
"relatedDocument": "Powiązany dokument",
|
||||
"relationTo": "Powiązany z",
|
||||
@@ -118,18 +128,24 @@
|
||||
"saveChanges": "Zapisz zmiany",
|
||||
"searchForBlock": "Szukaj bloku",
|
||||
"selectExistingLabel": "Wybierz istniejący {{label}}",
|
||||
"selectFieldsToEdit": "Wybierz pola do edycji",
|
||||
"showAll": "Pokaż wszystkie",
|
||||
"swapRelationship": "Zamiana Relacji",
|
||||
"swapUpload": "Zamień Wrzucone",
|
||||
"textToDisplay": "Tekst do wyświetlenia",
|
||||
"toggleBlock": "Przełącz blok",
|
||||
"uploadNewLabel": "Wrzuć nowy {{label}}"
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "Zamierzasz usunąć {{label}} <1>{{title}}</1>. Jesteś pewien?",
|
||||
"aboutToDeleteCount_many": "Zamierzasz usunąć {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "Zamierzasz usunąć {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "Zamierzasz usunąć {{count}} {{label}}",
|
||||
"addBelow": "Dodaj boniżej",
|
||||
"addFilter": "Dodaj filtr",
|
||||
"adminTheme": "Motyw administratora",
|
||||
"and": "I",
|
||||
"ascending": "Rosnąco",
|
||||
"automatic": "Automatyczny",
|
||||
"backToDashboard": "Powrót do panelu",
|
||||
"cancel": "Anuluj",
|
||||
@@ -152,6 +168,7 @@
|
||||
"dark": "Ciemny",
|
||||
"dashboard": "Panel",
|
||||
"delete": "Usuń",
|
||||
"deletedCountSuccessfully": "",
|
||||
"deletedSuccessfully": "Skutecznie usunięte.",
|
||||
"deleting": "Usuwanie...",
|
||||
"descending": "Malejąco",
|
||||
@@ -160,6 +177,9 @@
|
||||
"edit": "Edytować",
|
||||
"editLabel": "Edytuj {{label}}",
|
||||
"editing": "Edycja",
|
||||
"editingLabel_many": "Edytowanie {{count}} {{label}}",
|
||||
"editingLabel_one": "Edytowanie {{count}} {{label}}",
|
||||
"editingLabel_other": "Edytowanie {{count}} {{label}}",
|
||||
"email": "Email",
|
||||
"emailAddress": "Adres email",
|
||||
"enterAValue": "Wpisz wartość",
|
||||
@@ -198,7 +218,9 @@
|
||||
"save": "Zapisz",
|
||||
"saving": "Zapisywanie...",
|
||||
"searchBy": "Szukaj według",
|
||||
"selectAll": "Wybierz wszystkie {{liczba}} {{etykieta}}",
|
||||
"selectValue": "Wybierz wartość",
|
||||
"selectedCount": "Wybrano {{count}} {{label}}",
|
||||
"sorryNotFound": "Przepraszamy — nie ma nic, co odpowiadałoby twojej prośbie.",
|
||||
"sort": "Sortuj",
|
||||
"stayOnThisPage": "Pozostań na stronie",
|
||||
@@ -212,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "Masz niezapisane zmiany. Czy chcesz kontynuować duplikowanie?",
|
||||
"untitled": "Bez nazwy",
|
||||
"updatedAt": "Data edycji",
|
||||
"updatedCountSuccessfully": "Pomyślnie zaktualizowano {{count}} {{label}}.",
|
||||
"updatedSuccessfully": "Aktualizacja zakończona sukcesem.",
|
||||
"updating": "Aktualizacja",
|
||||
"uploading": "Wgrywanie",
|
||||
@@ -220,20 +243,21 @@
|
||||
"welcome": "Witaj"
|
||||
},
|
||||
"operators": {
|
||||
"contains": "zawiera",
|
||||
"equals": "równe",
|
||||
"isNotEqualTo": "nie jest równe",
|
||||
"isIn": "jest w",
|
||||
"isNotIn": "nie ma go w",
|
||||
"exists": "istnieje",
|
||||
"isGreaterThan": "jest większy niż",
|
||||
"isGreaterThanOrEqualTo": "jest większe lub równe",
|
||||
"isIn": "jest w",
|
||||
"isLessThan": "jest mniejsze niż",
|
||||
"isLessThanOrEqualTo": "jest mniejsze lub równe",
|
||||
"isGreaterThanOrEqualTo": "jest większe lub równe",
|
||||
"near": "blisko",
|
||||
"isLike": "jest jak",
|
||||
"contains": "zawiera"
|
||||
"isNotEqualTo": "nie jest równe",
|
||||
"isNotIn": "nie ma go w",
|
||||
"near": "blisko"
|
||||
},
|
||||
"upload": {
|
||||
"dragAndDrop": "Przeciągnij i upuść plik",
|
||||
"dragAndDropHere": "lub złap i upuść plik tutaj",
|
||||
"fileName": "Nazwa pliku",
|
||||
"fileSize": "Rozmiar pliku",
|
||||
@@ -242,7 +266,6 @@
|
||||
"moreInfo": "Więcej informacji",
|
||||
"selectCollectionToBrowse": "Wybierz kolekcję aby przejrzeć",
|
||||
"selectFile": "Wybierz plik",
|
||||
"dragAndDrop": "Przeciągnij i upuść plik",
|
||||
"sizes": "Rozmiary",
|
||||
"width": "Szerokość"
|
||||
},
|
||||
@@ -266,15 +289,18 @@
|
||||
"validUploadID": "To pole nie jest prawidłowym identyfikatorem przesyłania."
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "Za chwilę opublikujesz wszystkie {{label}} w zaznaczeniu. Jesteś pewny?",
|
||||
"aboutToRestore": "Zamierzasz przywrócić dokument {{label}} do stanu, w jakim znajdował się w dniu {{versionDate}}.",
|
||||
"aboutToRestoreGlobal": "Zamierzasz przywrócić globalny rekord {{label}} do stanu, w którym znajdował się w dniu {{versionDate}}.",
|
||||
"aboutToRevertToPublished": "Zamierzasz przywrócić zmiany w tym dokumencie do stanu opublikowanego. Jesteś pewien?",
|
||||
"aboutToUnpublish": "Zamierzasz cofnąć publikację tego dokumentu. Jesteś pewien?",
|
||||
"aboutToUnpublishSelection": "Zamierzasz cofnąć publikację wszystkich {{label}} w zaznaczeniu. Jesteś pewny?",
|
||||
"autosave": "Autozapis",
|
||||
"autosavedSuccessfully": "Pomyślnie zapisano automatycznie.",
|
||||
"autosavedVersion": "Wersja zapisana automatycznie",
|
||||
"changed": "Zmieniono",
|
||||
"compareVersion": "Porównaj wersję z:",
|
||||
"confirmPublish": "Potwierdź publikację",
|
||||
"confirmRevertToSaved": "Potwierdź powrót do zapisanego",
|
||||
"confirmUnpublish": "Potwierdź cofnięcie publikacji",
|
||||
"confirmVersionRestoration": "Potwierdź przywrócenie wersji",
|
||||
@@ -286,6 +312,7 @@
|
||||
"noRowsFound": "Nie znaleziono {{label}}",
|
||||
"preview": "Podgląd",
|
||||
"problemRestoringVersion": "Wystąpił problem podczas przywracania tej wersji",
|
||||
"publish": "Publikować",
|
||||
"publishChanges": "Opublikuj zmiany",
|
||||
"published": "Opublikowano",
|
||||
"restoreThisVersion": "Przywróć tę wersję",
|
||||
@@ -297,6 +324,7 @@
|
||||
"selectLocales": "Wybierz lokalizacje do wyświetlenia",
|
||||
"selectVersionToCompare": "Wybierz wersję do porównania",
|
||||
"showLocales": "Pokaż lokalizacje:",
|
||||
"showingVersionsFor": "Wyświetlanie wersji dla:",
|
||||
"status": "Status",
|
||||
"type": "Typ",
|
||||
"unpublish": "Cofnij publikację",
|
||||
@@ -305,6 +333,7 @@
|
||||
"versionCount_many": "Znalezionych wersji: {{count}}",
|
||||
"versionCount_none": "Nie znaleziono wersji",
|
||||
"versionCount_one": "Znaleziono {{count}} wersję",
|
||||
"versionCount_other": "Znaleziono {{count}} wersji",
|
||||
"versionCreatedOn": "Wersja {{version}} utworzona:",
|
||||
"versionID": "ID wersji",
|
||||
"versions": "Wersje",
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
"accountAlreadyActivated": "Essa conta já foi ativada.",
|
||||
"autosaving": "Ocorreu um problema ao salvar automaticamente esse documento.",
|
||||
"correctInvalidFields": "Por favor, corrija os campos inválidos.",
|
||||
"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_many": "Os campos a seguir estão inválidos:",
|
||||
@@ -81,6 +82,8 @@
|
||||
"problemUploadingFile": "Ocorreu um problema ao carregar o arquivo.",
|
||||
"tokenInvalidOrExpired": "Token expirado ou inválido.",
|
||||
"unPublishingDocument": "Ocorreu um problema ao despublicar esse documento",
|
||||
"unableToDeleteCount": "Não é possível excluir {{count}} de {{total}} {{label}}.",
|
||||
"unableToUpdateCount": "Não foi possível atualizar {{count}} de {{total}} {{label}}.",
|
||||
"unauthorized": "Não autorizado. Você deve estar logado para fazer essa requisição",
|
||||
"unknown": "Ocorreu um erro desconhecido.",
|
||||
"unspecific": "Ocorreu um erro.",
|
||||
@@ -89,27 +92,34 @@
|
||||
"verificationTokenInvalid": "Token de verificação inválido."
|
||||
},
|
||||
"fields": {
|
||||
"block": "bloco",
|
||||
"blocks": "blocos",
|
||||
"addLabel": "Adicionar {{label}}",
|
||||
"addLink": "Adicionar Link",
|
||||
"addNew": "Adicionar novo",
|
||||
"addNewLabel": "Adicionar novo {{label}}",
|
||||
"addRelationship": "Adicionar Relação",
|
||||
"addUpload": "Adicionar Upload",
|
||||
"block": "bloco",
|
||||
"blockType": "Tipo de bloco",
|
||||
"blocks": "blocos",
|
||||
"chooseBetweenCustomTextOrDocument": "Escolha entre inserir um URL de texto personalizado ou vincular a outro documento.",
|
||||
"chooseDocumentToLink": "Escolha um documento para vincular",
|
||||
"chooseFromExisting": "Escolher entre os existentes",
|
||||
"chooseLabel": "Escolher {{label}}",
|
||||
"collapseAll": "Recolher todos",
|
||||
"customURL": "URL personalizado",
|
||||
"editLabelData": "Editar dados de {{label}}",
|
||||
"editLink": "Editar Link",
|
||||
"editRelationship": "Editar Relacionamento",
|
||||
"enterURL": "Insira um URL",
|
||||
"internalLink": "Link Interno",
|
||||
"itemsAndMore": "{{items}} e mais {{count}}",
|
||||
"labelRelationship": "Relacionado a {{label}}",
|
||||
"latitude": "Latitude",
|
||||
"linkType": "Tipo de link",
|
||||
"linkedTo": "Ligado a <0>{{label}}</0>",
|
||||
"longitude": "Longitude",
|
||||
"newLabel": "Novo(a) {{label}}",
|
||||
"openInNewTab": "Abrir em nova aba",
|
||||
"passwordsDoNotMatch": "Senhas não coincidem.",
|
||||
"relatedDocument": "Documento Relacionado",
|
||||
"relationTo": "Relacionado a",
|
||||
@@ -118,18 +128,24 @@
|
||||
"saveChanges": "Salvar alterações",
|
||||
"searchForBlock": "Procurar bloco",
|
||||
"selectExistingLabel": "Selecionar {{label}} existente",
|
||||
"selectFieldsToEdit": "Selecione os campos para editar",
|
||||
"showAll": "Mostrar Tudo",
|
||||
"swapRelationship": "Relação de Troca",
|
||||
"swapUpload": "Substituir Upload",
|
||||
"textToDisplay": "Texto a ser exibido",
|
||||
"toggleBlock": "Alternar bloco",
|
||||
"uploadNewLabel": "Carregar novo(a) {{label}}"
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "Você está prestes a excluir o/a {{label}} <1>{{title}}</1>. Tem certeza?",
|
||||
"aboutToDeleteCount_many": "Você está prestes a deletar {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "Você está prestes a deletar {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "Você está prestes a deletar {{count}} {{label}}",
|
||||
"addBelow": "Adicionar abaixo",
|
||||
"addFilter": "Adicionar Filtro",
|
||||
"adminTheme": "Tema do Admin",
|
||||
"and": "E",
|
||||
"ascending": "Ascendente",
|
||||
"automatic": "Automático",
|
||||
"backToDashboard": "Voltar para Painel de Controle",
|
||||
"cancel": "Cancelar",
|
||||
@@ -152,6 +168,7 @@
|
||||
"dark": "Escuro",
|
||||
"dashboard": "Painel de Controle",
|
||||
"delete": "Excluir",
|
||||
"deletedCountSuccessfully": "Excluído {{count}} {{label}} com sucesso.",
|
||||
"deletedSuccessfully": "Apagado com sucesso.",
|
||||
"deleting": "Excluindo...",
|
||||
"descending": "Decrescente",
|
||||
@@ -160,6 +177,9 @@
|
||||
"edit": "Editar",
|
||||
"editLabel": "Editar {{label}}",
|
||||
"editing": "Editando",
|
||||
"editingLabel_many": "Editando {{count}} {{label}}",
|
||||
"editingLabel_one": "Editando {{count}} {{label}}",
|
||||
"editingLabel_other": "Editando {{count}} {{label}}",
|
||||
"email": "Email",
|
||||
"emailAddress": "Endereço de Email",
|
||||
"enterAValue": "Insira um valor",
|
||||
@@ -198,7 +218,9 @@
|
||||
"save": "Salvar",
|
||||
"saving": "Salvando...",
|
||||
"searchBy": "Buscar por {{label}}",
|
||||
"selectAll": "Selecione tudo {{count}} {{label}}",
|
||||
"selectValue": "Selecione um valor",
|
||||
"selectedCount": "{{count}} {{label}} selecionado",
|
||||
"sorryNotFound": "Desculpe—não há nada que corresponda à sua requisição.",
|
||||
"sort": "Ordenar",
|
||||
"stayOnThisPage": "Permanecer nessa página",
|
||||
@@ -212,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "Você tem mudanças não salvas. Você gostaria de continuar a duplicar?",
|
||||
"untitled": "Sem título",
|
||||
"updatedAt": "Atualizado Em",
|
||||
"updatedCountSuccessfully": "Atualizado {{count}} {{label}} com sucesso.",
|
||||
"updatedSuccessfully": "Atualizado com sucesso.",
|
||||
"updating": "Atualizando",
|
||||
"uploading": "Fazendo upload",
|
||||
@@ -220,20 +243,21 @@
|
||||
"welcome": "Boas vindas"
|
||||
},
|
||||
"operators": {
|
||||
"contains": "contém",
|
||||
"equals": "igual",
|
||||
"isNotEqualTo": "não é igual a",
|
||||
"isIn": "está em",
|
||||
"isNotIn": "não está em",
|
||||
"exists": "existe",
|
||||
"isGreaterThan": "é maior que",
|
||||
"isGreaterThanOrEqualTo": "é maior ou igual a",
|
||||
"isIn": "está em",
|
||||
"isLessThan": "é menor que",
|
||||
"isLessThanOrEqualTo": "é menor ou igual a",
|
||||
"isGreaterThanOrEqualTo": "é maior ou igual a",
|
||||
"near": "perto",
|
||||
"isLike": "é como",
|
||||
"contains": "contém"
|
||||
"isNotEqualTo": "não é igual a",
|
||||
"isNotIn": "não está em",
|
||||
"near": "perto"
|
||||
},
|
||||
"upload": {
|
||||
"dragAndDrop": "Arraste e solte um arquivo",
|
||||
"dragAndDropHere": "ou arraste um arquivo aqui",
|
||||
"fileName": "Nome do Arquivo",
|
||||
"fileSize": "Tamanho do Arquivo",
|
||||
@@ -242,7 +266,6 @@
|
||||
"moreInfo": "Ver mais",
|
||||
"selectCollectionToBrowse": "Selecione uma Coleção para Navegar",
|
||||
"selectFile": "Selecione um arquivo",
|
||||
"dragAndDrop": "Arraste e solte um arquivo",
|
||||
"sizes": "Tamanhos",
|
||||
"width": "Largura"
|
||||
},
|
||||
@@ -266,15 +289,18 @@
|
||||
"validUploadID": "'Esse campo não é um ID de upload válido.'"
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "Você está prestes a publicar todos os {{label}} da seleção. Tem certeza?",
|
||||
"aboutToRestore": "Você está prestes a restaurar o documento {{label}} para o estado em que ele se encontrava em {{versionDate}}.",
|
||||
"aboutToRestoreGlobal": "Você está prestes a restaurar o Global {{label}} para o estado em que ele se encontrava em {{versionDate}}.",
|
||||
"aboutToRevertToPublished": "Você está prestes a reverter as alterações desse documento para seu estado de publicação. Tem certeza?",
|
||||
"aboutToUnpublish": "Você está prestes a despublicar esse documento. Tem certeza?",
|
||||
"aboutToUnpublishSelection": "Você está prestes a cancelar a publicação de todos os {{label}} na seleção. Tem certeza?",
|
||||
"autosave": "Salvamento automático",
|
||||
"autosavedSuccessfully": "Salvamento automático com sucesso.",
|
||||
"autosavedVersion": "Versão de salvamento automático",
|
||||
"changed": "Alterado",
|
||||
"compareVersion": "Comparar versão com:",
|
||||
"confirmPublish": "Confirmar publicação",
|
||||
"confirmRevertToSaved": "Confirmar a reversão para o salvo",
|
||||
"confirmUnpublish": "Confirmar despublicação",
|
||||
"confirmVersionRestoration": "Confirmar Restauração de versão",
|
||||
@@ -286,6 +312,7 @@
|
||||
"noRowsFound": "Nenhum(a) {{label}} encontrado(a)",
|
||||
"preview": "Pré-visualização",
|
||||
"problemRestoringVersion": "Ocorreu um problema ao restaurar essa versão",
|
||||
"publish": "Publicar",
|
||||
"publishChanges": "Publicar alterações",
|
||||
"published": "Publicado",
|
||||
"restoreThisVersion": "Restaurar essa versão",
|
||||
@@ -297,6 +324,7 @@
|
||||
"selectLocales": "Selecione as localizações para exibir",
|
||||
"selectVersionToCompare": "Selecione uma versão para comparar",
|
||||
"showLocales": "Exibir localizações:",
|
||||
"showingVersionsFor": "Mostrando versões para:",
|
||||
"status": "Status",
|
||||
"type": "Tipo",
|
||||
"unpublish": "Despublicar",
|
||||
@@ -305,6 +333,7 @@
|
||||
"versionCount_many": "{{count}} versões encontradas",
|
||||
"versionCount_none": "Nenhuma versão encontrada",
|
||||
"versionCount_one": "{{count}} versão encontrada",
|
||||
"versionCount_other": "{{count}} versões encontradas",
|
||||
"versionCreatedOn": "{{version}} criada em:",
|
||||
"versionID": "ID da versão",
|
||||
"versions": "Versões",
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "Возникла проблема при загрузке файла.",
|
||||
"tokenInvalidOrExpired": "Токен либо недействителен, либо срок его действия истек.",
|
||||
"unPublishingDocument": "При отмене публикации этого документа возникла проблема.",
|
||||
"unableToDeleteCount": "Не удалось удалить {{count}} из {{total}} {{label}}.",
|
||||
"unableToUpdateCount": "Не удалось обновить {{count}} из {{total}} {{label}}.",
|
||||
"unauthorized": "Нет доступа, вы должны войти, чтобы сделать этот запрос.",
|
||||
"unknown": "Произошла неизвестная ошибка.",
|
||||
"unspecific": "Произошла ошибка.",
|
||||
@@ -126,6 +128,7 @@
|
||||
"saveChanges": "Сохранить изменения",
|
||||
"searchForBlock": "Найти Блок",
|
||||
"selectExistingLabel": "Выберите существующий {{label}}",
|
||||
"selectFieldsToEdit": "Выберите поля для редактирования",
|
||||
"showAll": "Показать все",
|
||||
"swapRelationship": "Поменять отношения",
|
||||
"swapUpload": "Заменить загруженное",
|
||||
@@ -135,10 +138,14 @@
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "Вы собираетесь удалить {{label}} <1>{{title}}</1>. Вы уверены?",
|
||||
"aboutToDeleteCount_many": "Вы собираетесь удалить {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "Вы собираетесь удалить {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "Вы собираетесь удалить {{count}} {{label}}",
|
||||
"addBelow": "Добавить ниже",
|
||||
"addFilter": "Добавить фильтр",
|
||||
"adminTheme": "Тема Панели",
|
||||
"and": "А также",
|
||||
"ascending": "Восходящий",
|
||||
"automatic": "Автоматически",
|
||||
"backToDashboard": "Назад к Панели",
|
||||
"cancel": "Отмена",
|
||||
@@ -161,6 +168,7 @@
|
||||
"dark": "Тёмная",
|
||||
"dashboard": "Панель",
|
||||
"delete": "Удалить",
|
||||
"deletedCountSuccessfully": "Удалено {{count}} {{label}} успешно.",
|
||||
"deletedSuccessfully": "Удален успешно.",
|
||||
"deleting": "Удаление...",
|
||||
"descending": "Уменьшение",
|
||||
@@ -169,6 +177,9 @@
|
||||
"edit": "Редактировать",
|
||||
"editLabel": "Редактировать {{label}}",
|
||||
"editing": "Редактирование",
|
||||
"editingLabel_many": "Редактирование {{count}} {{label}}",
|
||||
"editingLabel_one": "Редактирование {{count}} {{label}}",
|
||||
"editingLabel_other": "Редактирование {{count}} {{label}}",
|
||||
"email": "Email",
|
||||
"emailAddress": "Email",
|
||||
"enterAValue": "Введите значение",
|
||||
@@ -207,7 +218,9 @@
|
||||
"save": "Сохранить",
|
||||
"saving": "Сохранение...",
|
||||
"searchBy": "Искать по",
|
||||
"selectAll": "Выбрать все {{count}} {{label}}",
|
||||
"selectValue": "Выбрать значение",
|
||||
"selectedCount": "{{count}} {{label}} выбрано",
|
||||
"sorryNotFound": "К сожалению, ничего подходящего под ваш запрос нет.",
|
||||
"sort": "Сортировать",
|
||||
"stayOnThisPage": "Остаться на этой странице",
|
||||
@@ -221,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "У вас есть несохраненные изменения. Вы хотите продолжить дублирование?",
|
||||
"untitled": "Без названия",
|
||||
"updatedAt": "Дата правки",
|
||||
"updatedCountSuccessfully": "Обновлено {{count}} {{label}} успешно.",
|
||||
"updatedSuccessfully": "Успешно Обновлено.",
|
||||
"updating": "Обновление",
|
||||
"uploading": "Загрузка",
|
||||
@@ -229,20 +243,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": "Размер файла",
|
||||
@@ -251,7 +266,6 @@
|
||||
"moreInfo": "Больше информации",
|
||||
"selectCollectionToBrowse": "Выберите Коллекцию для просмотра",
|
||||
"selectFile": "Выберите файл",
|
||||
"dragAndDrop": "Перетащите файл",
|
||||
"sizes": "Размеры",
|
||||
"width": "Ширина"
|
||||
},
|
||||
@@ -265,25 +279,28 @@
|
||||
"invalidSelections": "'Это поле содержит следующие неправильные варианты:'",
|
||||
"lessThanMin": "\"{{value}}\" меньше минимально допустимого значения {{min}}.",
|
||||
"longerThanMin": "Это значение должно быть больше минимальной длины символов: {{minLength}}.",
|
||||
"requiresAtLeast": "Это поле требует не менее {{count}} {{label}}",
|
||||
"requiresNoMoreThan": "Это поле требует не более {{count}} {{label}}",
|
||||
"notValidDate": "\"{{value}}\" это не действительная дата.",
|
||||
"required": "Это обязательное поле.",
|
||||
"requiresAtLeast": "Это поле требует не менее {{count}} {{label}}",
|
||||
"requiresNoMoreThan": "Это поле требует не более {{count}} {{label}}",
|
||||
"requiresTwoNumbers": "В этом поле требуется два числа.",
|
||||
"shorterThanMax": "Это значение должно быть короче максимальной длины символов {{maxLength}}.",
|
||||
"trueOrFalse": "Это поле может быть равно только true или false.",
|
||||
"validUploadID": "'Это поле не является действительным ID загрузки.'"
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "Вы собираетесь опубликовать все {{label}} в выборе. Вы уверены?",
|
||||
"aboutToRestore": "Вы собираетесь восстановить этот документ {{label}} в состояние, в котором он находился {{versionDate}}.",
|
||||
"aboutToRestoreGlobal": "Вы собираетесь восстановить глобальную запись {{label}} в состояние, в котором она находилась {{versionDate}}.",
|
||||
"aboutToRevertToPublished": "Вы собираетесь вернуть изменения этого документа к его опубликованному состоянию. Вы уверены?",
|
||||
"aboutToUnpublish": "Вы собираетесь отменить публикацию этого документа. Вы уверены?",
|
||||
"aboutToUnpublishSelection": "Вы собираетесь отменить публикацию всех выбранных {{label}}. Вы уверены?",
|
||||
"autosave": "Автосохранение",
|
||||
"autosavedSuccessfully": "Автосохранение успешно.",
|
||||
"autosavedVersion": "Автоматически сохраненная версия",
|
||||
"changed": "Изменено",
|
||||
"compareVersion": "Сравнить версию с:",
|
||||
"confirmPublish": "Подтвердить публикацию",
|
||||
"confirmRevertToSaved": "Подтвердить возврат к сохраненному",
|
||||
"confirmUnpublish": "Подтвердить отмену публикации",
|
||||
"confirmVersionRestoration": "Подтвердить восстановление версии",
|
||||
@@ -295,6 +312,7 @@
|
||||
"noRowsFound": "Не найдено {{label}}",
|
||||
"preview": "Предпросмотр",
|
||||
"problemRestoringVersion": "Возникла проблема с восстановлением этой версии",
|
||||
"publish": "Публиковать",
|
||||
"publishChanges": "Опубликовать изменения",
|
||||
"published": "Опубликовано",
|
||||
"restoreThisVersion": "Восстановить эту версию",
|
||||
@@ -305,8 +323,8 @@
|
||||
"saveDraft": "Сохранить черновик",
|
||||
"selectLocales": "Выберите локали для отображения",
|
||||
"selectVersionToCompare": "Выбрать версию для сравнения",
|
||||
"showingVersionsFor": "Показаны версии для:",
|
||||
"showLocales": "Показать локали:",
|
||||
"showingVersionsFor": "Показаны версии для:",
|
||||
"status": "Статус",
|
||||
"type": "Тип",
|
||||
"unpublish": "Отменить публикацию",
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "Det uppstod ett problem när filen laddades upp.",
|
||||
"tokenInvalidOrExpired": "Token är antingen ogiltig eller har löpt ut.",
|
||||
"unPublishingDocument": "Det uppstod ett problem när det här dokumentet skulle avpubliceras.",
|
||||
"unableToDeleteCount": "Det gick inte att ta bort {{count}} av {{total}} {{label}}.",
|
||||
"unableToUpdateCount": "Det gick inte att uppdatera {{count}} av {{total}} {{label}}.",
|
||||
"unauthorized": "Obehörig, du måste vara inloggad för att göra denna begäran.",
|
||||
"unknown": "Ett okänt fel har uppstått.",
|
||||
"unspecific": "Ett fel har uppstått.",
|
||||
@@ -90,27 +92,34 @@
|
||||
"verificationTokenInvalid": "Verifieringstoken är ogiltig."
|
||||
},
|
||||
"fields": {
|
||||
"block": "block",
|
||||
"blocks": "block",
|
||||
"addLabel": "Lägg till {{label}}",
|
||||
"addLink": "Lägg till Länk",
|
||||
"addNew": "Lägg till ny",
|
||||
"addNewLabel": "Lägg till ny {{label}}",
|
||||
"addRelationship": "Lägg till Relation",
|
||||
"addUpload": "Lägg till Uppladdning",
|
||||
"block": "block",
|
||||
"blockType": "Block Typ",
|
||||
"blocks": "block",
|
||||
"chooseBetweenCustomTextOrDocument": "Välj mellan att ange en anpassad text-URL eller länka till ett annat dokument.",
|
||||
"chooseDocumentToLink": "Välj ett dokument att länka till",
|
||||
"chooseFromExisting": "Välj bland befintliga",
|
||||
"chooseLabel": "Välj {{label}}",
|
||||
"collapseAll": "kollapsa Alla",
|
||||
"customURL": "Anpassad URL",
|
||||
"editLabelData": "Redigera {{label}} data",
|
||||
"editLink": "Redigera Länk",
|
||||
"editRelationship": "Redigera Relation",
|
||||
"enterURL": "Ange en URL",
|
||||
"internalLink": "Intern länk",
|
||||
"itemsAndMore": "{{items}} och {{count}} mer",
|
||||
"labelRelationship": "{{label}} Relation",
|
||||
"latitude": "Latitud",
|
||||
"linkType": "Länktyp",
|
||||
"linkedTo": "Länkad till <0>{{label}}</0>",
|
||||
"longitude": "Longitud",
|
||||
"newLabel": "Ny {{label}}",
|
||||
"openInNewTab": "Öppna i ny flik",
|
||||
"passwordsDoNotMatch": "Lösenorden matchar inte.",
|
||||
"relatedDocument": "Relaterat Dokument",
|
||||
"relationTo": "Relation till",
|
||||
@@ -119,18 +128,24 @@
|
||||
"saveChanges": "Spara ändringar",
|
||||
"searchForBlock": "Sök efter ett block",
|
||||
"selectExistingLabel": "Välj befintlig {{label}}",
|
||||
"selectFieldsToEdit": "Välj fält att redigera",
|
||||
"showAll": "Visa Alla",
|
||||
"swapRelationship": "Byt Förhållande",
|
||||
"swapUpload": "Byt Uppladdning",
|
||||
"textToDisplay": "Text att visa",
|
||||
"toggleBlock": "Växla block",
|
||||
"uploadNewLabel": "Ladda upp ny {{label}}"
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "Du är på väg att ta bort {{label}} <1>{{title}}</1>. Är du säker?",
|
||||
"aboutToDeleteCount_many": "Du är på väg att ta bort {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "Du är på väg att ta bort {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "Du är på väg att ta bort {{count}} {{label}}",
|
||||
"addBelow": "Lägg Till Nedanför",
|
||||
"addFilter": "Lägg Till Filter",
|
||||
"adminTheme": "Admin Tema",
|
||||
"and": "Och",
|
||||
"ascending": "Stigande",
|
||||
"automatic": "Automatisk",
|
||||
"backToDashboard": "Tillbaka till Manöverpanelen",
|
||||
"cancel": "Avbryt",
|
||||
@@ -153,6 +168,7 @@
|
||||
"dark": "Mörk",
|
||||
"dashboard": "Manöverpanel",
|
||||
"delete": "Ta bort",
|
||||
"deletedCountSuccessfully": "Raderade {{count}} {{label}} framgångsrikt.",
|
||||
"deletedSuccessfully": "Togs bort framgångsrikt.",
|
||||
"deleting": "Tar bort...",
|
||||
"descending": "Fallande",
|
||||
@@ -161,6 +177,9 @@
|
||||
"edit": "Redigera",
|
||||
"editLabel": "Redigera {{label}}",
|
||||
"editing": "Redigerar",
|
||||
"editingLabel_many": "Redigerar {{count}} {{label}}",
|
||||
"editingLabel_one": "Redigerar {{count}} {{label}}",
|
||||
"editingLabel_other": "Redigerar {{count}} {{label}}",
|
||||
"email": "E-post",
|
||||
"emailAddress": "E-postadress",
|
||||
"enterAValue": "Ange ett värde",
|
||||
@@ -199,7 +218,9 @@
|
||||
"save": "Spara",
|
||||
"saving": "Sparar...",
|
||||
"searchBy": "Sök efter {{label}}",
|
||||
"selectAll": "Välj alla {{count}} {{label}}",
|
||||
"selectValue": "Välj ett värde",
|
||||
"selectedCount": "{{count}} {{label}} har valts",
|
||||
"sorryNotFound": "Tyvärr–det finns inget som motsvarar din begäran.",
|
||||
"sort": "Sortera",
|
||||
"stayOnThisPage": "Stanna på denna sida",
|
||||
@@ -213,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "Du har osparade ändringar. Vill du fortsätta att duplicera?",
|
||||
"untitled": "Namnlös",
|
||||
"updatedAt": "Uppdaterades Vid",
|
||||
"updatedCountSuccessfully": "Uppdaterade {{count}} {{label}} framgångsrikt.",
|
||||
"updatedSuccessfully": "Uppdaterades framgångsrikt.",
|
||||
"updating": "Uppdatering",
|
||||
"uploading": "Uppladdning",
|
||||
@@ -221,20 +243,21 @@
|
||||
"welcome": "Välkommen"
|
||||
},
|
||||
"operators": {
|
||||
"contains": "innehåller",
|
||||
"equals": "likar med",
|
||||
"isNotEqualTo": "är inte lika med",
|
||||
"isIn": "är med",
|
||||
"isNotIn": "är inte med",
|
||||
"exists": "finns",
|
||||
"isGreaterThan": "är större än",
|
||||
"isGreaterThanOrEqualTo": "är större än eller lika med",
|
||||
"isIn": "är med",
|
||||
"isLessThan": "är mindre än",
|
||||
"isLessThanOrEqualTo": "är mindre än eller lika med",
|
||||
"isGreaterThanOrEqualTo": "är större än eller lika med",
|
||||
"near": "nära",
|
||||
"isLike": "är som",
|
||||
"contains": "innehåller"
|
||||
"isNotEqualTo": "är inte lika med",
|
||||
"isNotIn": "är inte med",
|
||||
"near": "nära"
|
||||
},
|
||||
"upload": {
|
||||
"dragAndDrop": "Dra och släpp en fil",
|
||||
"dragAndDropHere": "eller dra och släpp en fil här",
|
||||
"fileName": "Filnamn",
|
||||
"fileSize": "Filstorlek",
|
||||
@@ -243,7 +266,6 @@
|
||||
"moreInfo": "Mer info",
|
||||
"selectCollectionToBrowse": "Välj en Samling att Bläddra i",
|
||||
"selectFile": "Välj en fil",
|
||||
"dragAndDrop": "Dra och släpp en fil",
|
||||
"sizes": "Storlekar",
|
||||
"width": "Bredd"
|
||||
},
|
||||
@@ -267,15 +289,18 @@
|
||||
"validUploadID": "Det här fältet är inte ett giltigt uppladdnings-ID"
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "Du är på väg att publicera alla {{label}} i urvalet. Är du säker?",
|
||||
"aboutToRestore": "Du är på väg att återställa detta {{label}} dokumentet till det tillståndet som det var den {{versionDate}}.",
|
||||
"aboutToRestoreGlobal": "Du är på väg att återställa det globala {{label}} till det tillståndet som det var den {{versionDate}}.",
|
||||
"aboutToRevertToPublished": "Du är på väg att återställa det här dokumentets ändringar till dess publicerade tillstånd. Är du säker?",
|
||||
"aboutToUnpublish": "Du håller på att avpublicera detta dokumentet. Är du säker?",
|
||||
"aboutToUnpublishSelection": "Du är på väg att avpublicera alla {{label}} i urvalet. Är du säker?",
|
||||
"autosave": "Automatisk sparning",
|
||||
"autosavedSuccessfully": "Autosparades framgångsrikt.",
|
||||
"autosavedVersion": "Autosparad version",
|
||||
"changed": "Ändrad",
|
||||
"compareVersion": "Jämför version med:",
|
||||
"confirmPublish": "Bekräfta publicering",
|
||||
"confirmRevertToSaved": "Bekräfta återgång till sparad",
|
||||
"confirmUnpublish": "Bekräfta avpublicering",
|
||||
"confirmVersionRestoration": "Bekräfta Versionsåterställning",
|
||||
@@ -287,6 +312,7 @@
|
||||
"noRowsFound": "Inga {{label}} hittades",
|
||||
"preview": "Förhandsvisa",
|
||||
"problemRestoringVersion": "Det uppstod ett problem när den här versionen skulle återställas",
|
||||
"publish": "Publicera",
|
||||
"publishChanges": "Publicera ändringar",
|
||||
"published": "Publicerad",
|
||||
"restoreThisVersion": "Återställ den här versionen",
|
||||
@@ -298,6 +324,7 @@
|
||||
"selectLocales": "Välj språk att visa",
|
||||
"selectVersionToCompare": "Välj en version att jämföra",
|
||||
"showLocales": "Visa språk:",
|
||||
"showingVersionsFor": "Visar versioner för:",
|
||||
"status": "Status",
|
||||
"type": "Typ",
|
||||
"unpublish": "Avpublicera",
|
||||
@@ -306,6 +333,7 @@
|
||||
"versionCount_many": "{{count}} versioner hittades",
|
||||
"versionCount_none": "Inga versioner hittades",
|
||||
"versionCount_one": "{{count}} version hittades",
|
||||
"versionCount_other": "{{count}} versioner hittades",
|
||||
"versionCreatedOn": "{{version}} skapad den:",
|
||||
"versionID": "Versions-ID",
|
||||
"versions": "Versioner",
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "เกิดปัญหาระหว่างการอัปโหลดไฟล์",
|
||||
"tokenInvalidOrExpired": "Token ไม่ถูกต้องหรือหมดอายุ",
|
||||
"unPublishingDocument": "เกิดปัญหาระหว่างการยกเลิกการเผยแพร่เอกสารนี้",
|
||||
"unableToDeleteCount": "ไม่สามารถลบ {{count}} จาก {{total}} {{label}}",
|
||||
"unableToUpdateCount": "ไม่สามารถอัปเดต {{count}} จาก {{total}} {{label}}",
|
||||
"unauthorized": "คุณไม่ได้รับอนุญาต กรุณาเข้าสู่ระบบเพื่อทำคำขอนี้",
|
||||
"unknown": "เกิดปัญหาบางอย่างที่ไม่ทราบสาเหตุ",
|
||||
"unspecific": "เกิดปัญหาบางอย่าง",
|
||||
@@ -91,8 +93,8 @@
|
||||
},
|
||||
"fields": {
|
||||
"addLabel": "เพิ่ม {{label}}",
|
||||
"addNew": "เพิ่ม",
|
||||
"addLink": "เพิ่มลิงค์",
|
||||
"addNew": "เพิ่ม",
|
||||
"addNewLabel": "เพิ่ม {{label}} ใหม่",
|
||||
"addRelationship": "เพิ่มความสัมพันธ์",
|
||||
"addUpload": "เพิ่มการอัปโหลด",
|
||||
@@ -126,6 +128,7 @@
|
||||
"saveChanges": "บันทึก",
|
||||
"searchForBlock": "ค้นหา Block",
|
||||
"selectExistingLabel": "เลือก {{label}} ที่มีอยู่",
|
||||
"selectFieldsToEdit": "เลือกช่องที่จะแก้ไข",
|
||||
"showAll": "แสดงทั้งหมด",
|
||||
"swapRelationship": "สลับความสัมพันธ์",
|
||||
"swapUpload": "สลับอัปโหลด",
|
||||
@@ -135,6 +138,9 @@
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "คุณกำลังจะลบ {{label}} <1>{{title}}</1> ต้องการดำเนินการต่อหรือไม่?",
|
||||
"aboutToDeleteCount_many": "คุณกำลังจะลบ {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "คุณกำลังจะลบ {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "คุณกำลังจะลบ {{count}} {{label}}",
|
||||
"addBelow": "เพิ่มด้านล่าง",
|
||||
"addFilter": "เพิ่มการกรอง",
|
||||
"adminTheme": "ธีมผู้ดูแลระบบ",
|
||||
@@ -162,6 +168,7 @@
|
||||
"dark": "มืด",
|
||||
"dashboard": "แดชบอร์ด",
|
||||
"delete": "ลบ",
|
||||
"deletedCountSuccessfully": "Deleted {{count}} {{label}} successfully.",
|
||||
"deletedSuccessfully": "ลบสำเร็จ",
|
||||
"deleting": "กำลังลบ...",
|
||||
"descending": "มากไปน้อย",
|
||||
@@ -170,6 +177,9 @@
|
||||
"edit": "แก้ไข",
|
||||
"editLabel": "แก้ไข {{label}}",
|
||||
"editing": "แก้ไข",
|
||||
"editingLabel_many": "กำลังแก้ไข {{count}} {{label}}",
|
||||
"editingLabel_one": "กำลังแก้ไข {{count}} {{label}}",
|
||||
"editingLabel_other": "กำลังแก้ไข {{count}} {{label}}",
|
||||
"email": "อีเมล",
|
||||
"emailAddress": "อีเมล",
|
||||
"enterAValue": "ระบุค่า",
|
||||
@@ -208,7 +218,9 @@
|
||||
"save": "บันทึก",
|
||||
"saving": "กำลังบันทึก...",
|
||||
"searchBy": "ค้นหาด้วย {{label}}",
|
||||
"selectAll": "เลือกทั้งหมด {{count}} {{label}}",
|
||||
"selectValue": "เลือกค่า",
|
||||
"selectedCount": "เลือก {{count}} {{label}} แล้ว",
|
||||
"sorryNotFound": "ขออภัย ไม่สามารถทำตามคำขอของคุณได้",
|
||||
"sort": "เรียง",
|
||||
"stayOnThisPage": "อยู่หน้านี้ต่อ",
|
||||
@@ -222,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "คุณมีการแก้ไขที่ยังไม่ถูกบันทึก คุณต้องการทำสำเนาต่อหรือไม่?",
|
||||
"untitled": "ไม่มีชื่อ",
|
||||
"updatedAt": "แก้ไขเมื่อ",
|
||||
"updatedCountSuccessfully": "อัปเดต {{count}} {{label}} เรียบร้อยแล้ว",
|
||||
"updatedSuccessfully": "แก้ไขสำเร็จ",
|
||||
"updating": "กำลังอัปเดต",
|
||||
"uploading": "กำลังอัปโหลด",
|
||||
@@ -230,20 +243,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": "ขนาดไฟล์",
|
||||
@@ -252,7 +266,6 @@
|
||||
"moreInfo": "แสดงข้อมูล",
|
||||
"selectCollectionToBrowse": "เลือก Collection ที่ต้องการค้นหา",
|
||||
"selectFile": "เลือกไฟล์",
|
||||
"dragAndDrop": "ลากและวางไฟล์",
|
||||
"sizes": "ขนาด",
|
||||
"width": "ความกว้าง"
|
||||
},
|
||||
@@ -276,15 +289,18 @@
|
||||
"validUploadID": "ไม่ใช่ ID ของการอัปโหลดที่ถูกต้อง"
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "คุณกำลังจะเผยแพร่ {{label}} ทั้งหมดในส่วนที่เลือก คุณแน่ใจไหม?",
|
||||
"aboutToRestore": "คุณกำลังจะคืนค่าเอกสาร {{label}} นี้กลับไปอยู่ในเวอร์ชันเมื่อวันที่ {{versionDate}}",
|
||||
"aboutToRestoreGlobal": "คุณกำลังจะคืนค่า global {{label}} กลับไปอยู่ในเวอร์ชันเมื่อวันที่ {{versionDate}}.",
|
||||
"aboutToRevertToPublished": "คุณกำลังจะย้อนการเปลี่ยนแปลงของเอกสารนี้ไปยังเวอร์ชันที่เผยแพร่อยู่ คุณต้องการดำเนินการต่อหรือไม่?",
|
||||
"aboutToUnpublish": "คุณกำลังจะยกเลิกเผยแพร่เอกสารนี้ คุณต้องการดำเนินการต่อหรือไม่?",
|
||||
"aboutToUnpublishSelection": "คุณกำลังจะเลิกเผยแพร่ {{label}} ทั้งหมดในส่วนที่เลือก คุณแน่ใจไหม?",
|
||||
"autosave": "บันทึกอัตโนมัติ",
|
||||
"autosavedSuccessfully": "บันทึกอัตโนมัติสำเร็จ",
|
||||
"autosavedVersion": "เวอร์ชันบันทึกอัตโนมัติ",
|
||||
"changed": "มีการแก้ไข",
|
||||
"compareVersion": "เปรียบเทียบเวอร์ชันกับ:",
|
||||
"confirmPublish": "ยืนยันการเผยแพร่",
|
||||
"confirmRevertToSaved": "ยืนยันย้อนการแก้ไข",
|
||||
"confirmUnpublish": "ยืนยันการยกเลิกการเผยแพร่",
|
||||
"confirmVersionRestoration": "ยืนยันการกู้คืนเวอร์ชัน",
|
||||
@@ -296,6 +312,7 @@
|
||||
"noRowsFound": "ไม่พบ {{label}}",
|
||||
"preview": "ตัวอย่าง",
|
||||
"problemRestoringVersion": "เกิดปัญหาระหว่างการกู้คืนเวอร์ชันนี้",
|
||||
"publish": "เผยแพร่",
|
||||
"publishChanges": "เผยแพร่การแก้ไข",
|
||||
"published": "เผยแพร่แล้ว",
|
||||
"restoreThisVersion": "กู้คืนเวอร์ชันนี้",
|
||||
@@ -306,8 +323,8 @@
|
||||
"saveDraft": "บันทึกร่าง",
|
||||
"selectLocales": "เลือกภาษาที่ต้องการแสดง",
|
||||
"selectVersionToCompare": "เลือกเวอร์ชันที่ต้องการเปรียบเทียบ",
|
||||
"showingVersionsFor": "กำลังแสดงเวอร์ชันของ:",
|
||||
"showLocales": "แสดงภาษา:",
|
||||
"showingVersionsFor": "กำลังแสดงเวอร์ชันของ:",
|
||||
"status": "สถานะ",
|
||||
"type": "ประเภท",
|
||||
"unpublish": "หยุดเผยแพร่",
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
"accountAlreadyActivated": "Hesap zaten etkinleştirildi.",
|
||||
"autosaving": "Otomatik kaydetme başarısız oldu",
|
||||
"correctInvalidFields": "Lütfen geçersiz alanları düzeltin.",
|
||||
"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_many": "Lütfen geçersiz alanları düzeltin:",
|
||||
@@ -81,44 +82,44 @@
|
||||
"problemUploadingFile": "Dosya yüklenirken bir sorun oluştu.",
|
||||
"tokenInvalidOrExpired": "Geçersiz veya süresi dolmuş token.",
|
||||
"unPublishingDocument": "Geçerli döküman yayından kaldırılırken bir sorun oluştu.",
|
||||
"unableToDeleteCount": "{{total}} {{label}} içinden {{count}} silinemiyor.",
|
||||
"unableToUpdateCount": "{{total}} {{label}} içinden {{count}} güncellenemiyor.",
|
||||
"unauthorized": "Bu işlemi gerçekleştirmek için lütfen giriş yapın.",
|
||||
"unknown": "Bilinmeyen bir hata oluştu.",
|
||||
"unspecific": "Bir hata oluştu.",
|
||||
"userLocked": "Hesabınız hatalı giriş denemeleri yüzünden geçici olarak kilitlendi. Lütfen daha sonra tekrar deneyin.",
|
||||
"valueMustBeUnique": "Değer benzersiz olmalıdır",
|
||||
"verificationTokenInvalid": "Doğrulama tokeni geçersiz.",
|
||||
"deletingFile": "Dosya silinirken bir hatayla karşılaşıldı."
|
||||
"verificationTokenInvalid": "Doğrulama tokeni geçersiz."
|
||||
},
|
||||
"fields": {
|
||||
"chooseBetweenCustomTextOrDocument": "Choose between entering a custom text URL or linking to another document.",
|
||||
"chooseDocumentToLink": "Bağlantı verilecek bir döküman seçin.",
|
||||
"customURL": "Özel URL",
|
||||
"editLink": "Bağlantıyı Düzenle",
|
||||
"editRelationship": "İlişkiyi Ekle",
|
||||
"enterURL": "Bir URL girin",
|
||||
"internalLink": "İç bağlantı",
|
||||
"linkType": "Bağlantı türü",
|
||||
"openInNewTab": "Yeni sekmede aç",
|
||||
"textToDisplay": "Görüntülenecek metin",
|
||||
"block": "blok",
|
||||
"blocks": "blok",
|
||||
"addLabel": "{{label}} ekle",
|
||||
"addLink": "Link Ekle",
|
||||
"addNew": "Yeni",
|
||||
"addNewLabel": "Yeni {{label}}",
|
||||
"addRelationship": "İlişki Ekle",
|
||||
"addUpload": "Yükleme Ekle",
|
||||
"block": "blok",
|
||||
"blockType": "Blok tipi",
|
||||
"blocks": "blok",
|
||||
"chooseBetweenCustomTextOrDocument": "Choose between entering a custom text URL or linking to another document.",
|
||||
"chooseDocumentToLink": "Bağlantı verilecek bir döküman seçin.",
|
||||
"chooseFromExisting": "Varolanlardan seç",
|
||||
"chooseLabel": "{{label}} seç",
|
||||
"collapseAll": "Tümünü daralt",
|
||||
"customURL": "Özel URL",
|
||||
"editLabelData": "{{label}} düzenle",
|
||||
"editLink": "Bağlantıyı Düzenle",
|
||||
"editRelationship": "İlişkiyi Ekle",
|
||||
"enterURL": "Bir URL girin",
|
||||
"internalLink": "İç bağlantı",
|
||||
"itemsAndMore": "{{items}} and {{count}} more",
|
||||
"labelRelationship": "{{label}} Relationship",
|
||||
"latitude": "Enlem",
|
||||
"linkType": "Bağlantı türü",
|
||||
"linkedTo": "<0>label</0> için bağlantı verildi",
|
||||
"longitude": "Boylam",
|
||||
"newLabel": "Yeni {{label}}",
|
||||
"openInNewTab": "Yeni sekmede aç",
|
||||
"passwordsDoNotMatch": "Parolalar eşleşmiyor.",
|
||||
"relatedDocument": "İlişkili döküman",
|
||||
"relationTo": "Relation To",
|
||||
@@ -127,22 +128,24 @@
|
||||
"saveChanges": "Değişiklikleri kaydet",
|
||||
"searchForBlock": "Blok ara",
|
||||
"selectExistingLabel": "Varolan {{label}} seç",
|
||||
"selectFieldsToEdit": "Düzenlenecek alanları seçin",
|
||||
"showAll": "Tümünü göster",
|
||||
"swapRelationship": "Takas Ilişkisi",
|
||||
"swapUpload": "Karşıya Yüklemeyi Değiştir",
|
||||
"textToDisplay": "Görüntülenecek metin",
|
||||
"toggleBlock": "Bloğu aç/kapat",
|
||||
"uploadNewLabel": "Karşıya {{label}} yükle"
|
||||
},
|
||||
"general": {
|
||||
"addBelow": "Altına ekle",
|
||||
"filter": "Filtrele",
|
||||
"none": "Hiç",
|
||||
"enterAValue": "Değer girin",
|
||||
"deletedSuccessfully": "Başarıyla silindi.",
|
||||
"aboutToDelete": "<1>{{title}}</1> {{label}} silinmek üzere. Silme işlemine devam etmek istiyor musunuz?",
|
||||
"aboutToDeleteCount_many": "{{count}} {{label}} silmek üzeresiniz",
|
||||
"aboutToDeleteCount_one": "{{count}} {{label}} silmek üzeresiniz",
|
||||
"aboutToDeleteCount_other": "{{count}} {{label}} silmek üzeresiniz",
|
||||
"addBelow": "Altına ekle",
|
||||
"addFilter": "Filtre ekle",
|
||||
"adminTheme": "Admin arayüzü",
|
||||
"and": "ve",
|
||||
"ascending": "artan",
|
||||
"automatic": "Otomatik",
|
||||
"backToDashboard": "Anasayfaya geri dön",
|
||||
"cancel": "İptal",
|
||||
@@ -165,6 +168,8 @@
|
||||
"dark": "Karanlık",
|
||||
"dashboard": "Anasayfa",
|
||||
"delete": "Sil",
|
||||
"deletedCountSuccessfully": "{{count}} {{label}} başarıyla silindi.",
|
||||
"deletedSuccessfully": "Başarıyla silindi.",
|
||||
"deleting": "Siliniyor...",
|
||||
"descending": "Azalan",
|
||||
"duplicate": "Çoğalt",
|
||||
@@ -172,9 +177,14 @@
|
||||
"edit": "Düzenle",
|
||||
"editLabel": "{{label}} düzenle",
|
||||
"editing": "Düzenleniyor",
|
||||
"editingLabel_many": "{{count}} {{label}} düzenleniyor",
|
||||
"editingLabel_one": "{{count}} {{label}} düzenleniyor",
|
||||
"editingLabel_other": "{{count}} {{label}} düzenleniyor",
|
||||
"email": "E-posta",
|
||||
"emailAddress": "E-posta adresi",
|
||||
"enterAValue": "Değer girin",
|
||||
"fallbackToDefaultLocale": "Varsayılan yerel ayara geri dönme",
|
||||
"filter": "Filtrele",
|
||||
"filterWhere": "{{label}} filtrele:",
|
||||
"filters": "Filtreler",
|
||||
"globals": "Globaller",
|
||||
@@ -183,8 +193,8 @@
|
||||
"leaveAnyway": "Yine de ayrıl",
|
||||
"leaveWithoutSaving": "Kaydetmeden ayrıl",
|
||||
"light": "Aydınlık",
|
||||
"locales": "Diller",
|
||||
"loading": "Yükleniyor",
|
||||
"locales": "Diller",
|
||||
"moveDown": "Aşağı taşı",
|
||||
"moveUp": "Yukarı taşı",
|
||||
"newPassword": "Yeni parola",
|
||||
@@ -192,6 +202,7 @@
|
||||
"noLabel": "<{{label}} yok>",
|
||||
"noResults": "{{label}} bulunamadı. Henüz bir {{label}} eklenmemiş olabilir veya seçtiğiniz filtrelerle eşleşen bir sonuç bulunamamış olabilir.",
|
||||
"noValue": "Değer yok",
|
||||
"none": "Hiç",
|
||||
"notFound": "Bulunamadı",
|
||||
"nothingFound": "Hiçbir şey bulunamadı",
|
||||
"of": "of",
|
||||
@@ -207,7 +218,9 @@
|
||||
"save": "Kaydet",
|
||||
"saving": "Kaydediliyor...",
|
||||
"searchBy": "Şuna göre sırala: {{label}}",
|
||||
"selectAll": "Tüm {{count}} {{label}}'ı seçin",
|
||||
"selectValue": "Bir değer seçin",
|
||||
"selectedCount": "{{count}} {{label}} seçildi",
|
||||
"sorryNotFound": "Üzgünüz, isteğinizle eşleşen bir sonuç bulunamadı.",
|
||||
"sort": "Sırala",
|
||||
"stayOnThisPage": "Bu sayfada kal",
|
||||
@@ -221,6 +234,7 @@
|
||||
"unsavedChangesDuplicate": "Kaydedilmemiş değişiklikler var. Çoğaltma işlemine devam etmek istiyor musunuz?",
|
||||
"untitled": "Başlıksız",
|
||||
"updatedAt": "Güncellenme tarihi",
|
||||
"updatedCountSuccessfully": "{{count}} {{label}} başarıyla güncellendi.",
|
||||
"updatedSuccessfully": "Başarıyla güncellendi.",
|
||||
"updating": "Güncelleniyor",
|
||||
"uploading": "Yükleniyor",
|
||||
@@ -229,18 +243,18 @@
|
||||
"welcome": "Hoşgeldiniz"
|
||||
},
|
||||
"operators": {
|
||||
"contains": "içerir",
|
||||
"equals": "eşittir",
|
||||
"isNotEqualTo": "eşit değildir",
|
||||
"isIn": "içinde",
|
||||
"isNotIn": "içinde değil",
|
||||
"exists": "var",
|
||||
"isGreaterThan": "şundan büyüktür",
|
||||
"isGreaterThanOrEqualTo": "büyüktür veya eşittir",
|
||||
"isIn": "içinde",
|
||||
"isLessThan": "küçüktür",
|
||||
"isLessThanOrEqualTo": "küçüktür veya eşittir",
|
||||
"isGreaterThanOrEqualTo": "büyüktür veya eşittir",
|
||||
"near": "yakın",
|
||||
"isLike": "gibidir",
|
||||
"contains": "içerir"
|
||||
"isNotEqualTo": "eşit değildir",
|
||||
"isNotIn": "içinde değil",
|
||||
"near": "yakın"
|
||||
},
|
||||
"upload": {
|
||||
"dragAndDrop": "Bir dosya sürükleyip bırakabilirsiniz",
|
||||
@@ -256,11 +270,9 @@
|
||||
"width": "Genişlik"
|
||||
},
|
||||
"validation": {
|
||||
"fieldHasNo": "Bu alanda {{label}} girili değil.",
|
||||
"requiresAtLeast": "Bu alan en az {{count}} adet {{label}} gerektirmektedir.",
|
||||
"requiresNoMoreThan": "Bu alana {{count}} adetten fazla {{label}} girilemez.",
|
||||
"emailAddress": "Lütfen geçerli bir e-posta adresi girin.",
|
||||
"enterNumber": "Lütfen geçerli bir sayı girin.",
|
||||
"fieldHasNo": "Bu alanda {{label}} girili değil.",
|
||||
"greaterThanMax": "\"{{value}}\", izin verilen maksimum değerden ({{max}}) fazla.",
|
||||
"invalidInput": "Bu alanda geçersiz bir giriş mevcut.",
|
||||
"invalidSelection": "Bu alanda geçersiz bir seçim mevcut.",
|
||||
@@ -269,45 +281,50 @@
|
||||
"longerThanMin": "Bu değer minimum {{minLength}} karakterden uzun olmalıdır.",
|
||||
"notValidDate": "\"{{value}}\" geçerli bir tarih değil.",
|
||||
"required": "Bu alan gereklidir.",
|
||||
"requiresAtLeast": "Bu alan en az {{count}} adet {{label}} gerektirmektedir.",
|
||||
"requiresNoMoreThan": "Bu alana {{count}} adetten fazla {{label}} girilemez.",
|
||||
"requiresTwoNumbers": "Bu alana en az iki rakam girilmesi zorunludur.",
|
||||
"shorterThanMax": "Bu alan {{maxLength}} karakterden daha kısa olmalıdır.",
|
||||
"trueOrFalse": "Bu alan yalnızca doğru ve yanlış olabilir.",
|
||||
"validUploadID": "'Bu alan geçerli bir karşıya yükleme ID'sine sahip değil.'"
|
||||
},
|
||||
"version": {
|
||||
"showingVersionsFor": "",
|
||||
"versionCount_other": "",
|
||||
"autosavedSuccessfully": "Otomatik kaydetme başarılı",
|
||||
"draftSavedSuccessfully": "Taslak başarıyla kaydedildi.",
|
||||
"restoredSuccessfully": "Geri getirme başarılı.",
|
||||
"selectLocales": "Görüntülenecek yerel ayarları seçin",
|
||||
"aboutToPublishSelection": "Seçimdeki tüm {{label}}'i yayınlamak üzeresiniz. Emin misin?",
|
||||
"aboutToRestore": "Döküman {{label}}, {{versionDate}} tarihindeki sürümüne geri döndürülecek.",
|
||||
"aboutToRestoreGlobal": "Global {{label}}, {{versionDate}} tarihindeki sürümüne geri döndürülecek.",
|
||||
"aboutToRevertToPublished": "Bu dökümanın değişikliklerini yayınladığı haline geri getirmek üzeresiniz. Devam etmek istiyor musunuz?",
|
||||
"aboutToUnpublish": "Bu dökümanı yayından kaldırmak üzeresiniz. Devam etmek istiyor musunuz?",
|
||||
"aboutToUnpublishSelection": "Seçimdeki tüm {{label}} yayınını kaldırmak üzeresiniz. Emin misin?",
|
||||
"autosave": "Otomatik kaydet",
|
||||
"autosavedSuccessfully": "Otomatik kaydetme başarılı",
|
||||
"autosavedVersion": "Otomatik kayıtlı sürüm",
|
||||
"changed": "Değişiklik yapıldı",
|
||||
"compareVersion": "Sürümü şununla karşılaştır:",
|
||||
"confirmPublish": "Yayınlamayı onayla",
|
||||
"confirmRevertToSaved": "Confirm revert to saved",
|
||||
"confirmUnpublish": "Yayından kaldırmayı onayla",
|
||||
"confirmVersionRestoration": "Sürümü Geri Getirmeyi Onayla",
|
||||
"currentDocumentStatus": "Şu an {{docStatus}} döküman",
|
||||
"draft": "Taslak",
|
||||
"draftSavedSuccessfully": "Taslak başarıyla kaydedildi.",
|
||||
"lastSavedAgo": "Son kaydedilme: {{distance, relativetime(minutes)}}",
|
||||
"noFurtherVersionsFound": "Başka sürüm bulunamadı.",
|
||||
"noRowsFound": "{{label}} bulunamadı",
|
||||
"preview": "Önizleme",
|
||||
"problemRestoringVersion": "Bu sürüme geri döndürürken bir hatayla karşılaşıldı.",
|
||||
"publish": "Yayınla",
|
||||
"publishChanges": "Değişiklikleri yayınla",
|
||||
"published": "Yayınlandı",
|
||||
"restoreThisVersion": "Bu sürüme geri döndür",
|
||||
"restoredSuccessfully": "Geri getirme başarılı.",
|
||||
"restoring": "Geri döndürülüyor...",
|
||||
"revertToPublished": "Yayınlanana geri döndür",
|
||||
"reverting": "Değişiklikler geri alınıyor...",
|
||||
"saveDraft": "Taslağı kaydet",
|
||||
"selectLocales": "Görüntülenecek yerel ayarları seçin",
|
||||
"selectVersionToCompare": "Karşılaştırılacak bir sürüm seçin",
|
||||
"showLocales": "Yerel ayarları göster:",
|
||||
"showingVersionsFor": "Şunun için sürümler gösteriliyor:",
|
||||
"status": "Durum",
|
||||
"type": "Tür",
|
||||
"unpublish": "Yayından Kaldır",
|
||||
@@ -316,6 +333,7 @@
|
||||
"versionCount_many": "{{count}} sürüm bulundu",
|
||||
"versionCount_none": "Sürüm bulunamadı",
|
||||
"versionCount_one": "{{count}} sürüm bulundu",
|
||||
"versionCount_other": "{{count}} sürüm bulundu",
|
||||
"versionCreatedOn": "{{version}} oluşturma tarihi:",
|
||||
"versionID": "Sürüm ID",
|
||||
"versions": "Sürümler",
|
||||
|
||||
@@ -318,6 +318,12 @@
|
||||
"unspecific": {
|
||||
"type": "string"
|
||||
},
|
||||
"unableToDeleteCount": {
|
||||
"type": "string"
|
||||
},
|
||||
"unableToUpdateCount": {
|
||||
"type": "string"
|
||||
},
|
||||
"userLocked": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -357,6 +363,8 @@
|
||||
"unauthorized",
|
||||
"unknown",
|
||||
"unspecific",
|
||||
"unableToDeleteCount",
|
||||
"unableToUpdateCount",
|
||||
"userLocked",
|
||||
"valueMustBeUnique",
|
||||
"verificationTokenInvalid"
|
||||
@@ -477,6 +485,9 @@
|
||||
"selectExistingLabel": {
|
||||
"type": "string"
|
||||
},
|
||||
"selectFieldsToEdit": {
|
||||
"type": "string"
|
||||
},
|
||||
"showAll": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -528,6 +539,7 @@
|
||||
"saveChanges",
|
||||
"searchForBlock",
|
||||
"selectExistingLabel",
|
||||
"selectFieldsToEdit",
|
||||
"showAll",
|
||||
"swapUpload",
|
||||
"toggleBlock",
|
||||
@@ -541,6 +553,15 @@
|
||||
"aboutToDelete": {
|
||||
"type": "string"
|
||||
},
|
||||
"aboutToDeleteCount_many": {
|
||||
"type": "string"
|
||||
},
|
||||
"aboutToDeleteCount_one": {
|
||||
"type": "string"
|
||||
},
|
||||
"aboutToDeleteCount_other": {
|
||||
"type": "string"
|
||||
},
|
||||
"addBelow": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -622,6 +643,9 @@
|
||||
"delete": {
|
||||
"type": "string"
|
||||
},
|
||||
"deletedCountSuccessfully": {
|
||||
"type": "string"
|
||||
},
|
||||
"deletedSuccessfully": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -646,6 +670,15 @@
|
||||
"editing": {
|
||||
"type": "string"
|
||||
},
|
||||
"editingLabel_many": {
|
||||
"type": "string"
|
||||
},
|
||||
"editingLabel_one": {
|
||||
"type": "string"
|
||||
},
|
||||
"editingLabel_other": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -760,9 +793,15 @@
|
||||
"searchBy": {
|
||||
"type": "string"
|
||||
},
|
||||
"selectAll": {
|
||||
"type": "string"
|
||||
},
|
||||
"selectValue": {
|
||||
"type": "string"
|
||||
},
|
||||
"selectedCount": {
|
||||
"type": "string"
|
||||
},
|
||||
"sorryNotFound": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -802,6 +841,9 @@
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedCountSuccessfully": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedSuccessfully": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -823,6 +865,9 @@
|
||||
},
|
||||
"required": [
|
||||
"aboutToDelete",
|
||||
"aboutToDeleteCount_many",
|
||||
"aboutToDeleteCount_one",
|
||||
"aboutToDeleteCount_other",
|
||||
"addBelow",
|
||||
"addFilter",
|
||||
"adminTheme",
|
||||
@@ -849,6 +894,7 @@
|
||||
"dark",
|
||||
"dashboard",
|
||||
"delete",
|
||||
"deletedCountSuccessfully",
|
||||
"deletedSuccessfully",
|
||||
"deleting",
|
||||
"descending",
|
||||
@@ -856,6 +902,9 @@
|
||||
"duplicateWithoutSaving",
|
||||
"editLabel",
|
||||
"editing",
|
||||
"editingLabel_many",
|
||||
"editingLabel_one",
|
||||
"editingLabel_other",
|
||||
"email",
|
||||
"emailAddress",
|
||||
"enterAValue",
|
||||
@@ -893,7 +942,9 @@
|
||||
"save",
|
||||
"saving",
|
||||
"searchBy",
|
||||
"selectAll",
|
||||
"selectValue",
|
||||
"selectedCount",
|
||||
"sorryNotFound",
|
||||
"sort",
|
||||
"stayOnThisPage",
|
||||
@@ -907,6 +958,7 @@
|
||||
"unsavedChangesDuplicate",
|
||||
"untitled",
|
||||
"updatedAt",
|
||||
"updatedCountSuccessfully",
|
||||
"updatedSuccessfully",
|
||||
"user",
|
||||
"users",
|
||||
@@ -1101,6 +1153,9 @@
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"aboutToPublishSelection": {
|
||||
"type": "string"
|
||||
},
|
||||
"aboutToRestore": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -1113,6 +1168,9 @@
|
||||
"aboutToUnpublish": {
|
||||
"type": "string"
|
||||
},
|
||||
"aboutToUnpublishSelection": {
|
||||
"type": "string"
|
||||
},
|
||||
"autosave": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -1128,6 +1186,9 @@
|
||||
"compareVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
"confirmPublish": {
|
||||
"type": "string"
|
||||
},
|
||||
"confirmRevertToSaved": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -1164,6 +1225,9 @@
|
||||
"publishChanges": {
|
||||
"type": "string"
|
||||
},
|
||||
"publish": {
|
||||
"type": "string"
|
||||
},
|
||||
"published": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -1247,15 +1311,18 @@
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"aboutToPublishSelection",
|
||||
"aboutToRestore",
|
||||
"aboutToRestoreGlobal",
|
||||
"aboutToRevertToPublished",
|
||||
"aboutToUnpublish",
|
||||
"aboutToUnpublishSelection",
|
||||
"autosave",
|
||||
"autosavedSuccessfully",
|
||||
"autosavedVersion",
|
||||
"changed",
|
||||
"compareVersion",
|
||||
"confirmPublish",
|
||||
"confirmRevertToSaved",
|
||||
"confirmUnpublish",
|
||||
"confirmVersionRestoration",
|
||||
@@ -1268,6 +1335,7 @@
|
||||
"preview",
|
||||
"problemRestoringVersion",
|
||||
"publishChanges",
|
||||
"publish",
|
||||
"published",
|
||||
"restoreThisVersion",
|
||||
"restoredSuccessfully",
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "Виникла помилка під час завантаження файлу.",
|
||||
"tokenInvalidOrExpired": "Токен або не дійсний, або його строк дії закінчився.",
|
||||
"unPublishingDocument": "Підчас відміни публікації даного документа, виникла помилка.",
|
||||
"unableToDeleteCount": "Не вдалося видалити {{count}} із {{total}} {{label}}.",
|
||||
"unableToUpdateCount": "Не вдалося оновити {{count}} із {{total}} {{label}}.",
|
||||
"unauthorized": "Немає доступу, ви повинні увійти, щоб виконати цей запит.",
|
||||
"unknown": "Виникла невідома помилка.",
|
||||
"unspecific": "Виникла помилка.",
|
||||
@@ -123,6 +125,7 @@
|
||||
"saveChanges": "Зберегти зміни",
|
||||
"searchForBlock": "Знайти блок",
|
||||
"selectExistingLabel": "Вибрати існуючий {{label}}",
|
||||
"selectFieldsToEdit": "Виберіть поля для редагування",
|
||||
"showAll": "Показати все",
|
||||
"swapUpload": "Замінити завантаження",
|
||||
"textToDisplay": "Текст для відображення",
|
||||
@@ -131,6 +134,9 @@
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "Ви бажаєте видалити {{label}} <1>{{title}}</1>. Ви впевнені?",
|
||||
"aboutToDeleteCount_many": "Ви збираєтеся видалити {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "Ви збираєтеся видалити {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "Ви збираєтеся видалити {{count}} {{label}}",
|
||||
"addBelow": "Добавити нижче",
|
||||
"addFilter": "Добавити фільтр",
|
||||
"adminTheme": "Тема адмінки",
|
||||
@@ -158,6 +164,7 @@
|
||||
"dark": "Темна",
|
||||
"dashboard": "Головна",
|
||||
"delete": "Видалити",
|
||||
"deletedCountSuccessfully": "Успішно видалено {{count}} {{label}}.",
|
||||
"deletedSuccessfully": "Успішно видалено.",
|
||||
"deleting": "Видалення...",
|
||||
"descending": "В порядку спадання",
|
||||
@@ -166,6 +173,9 @@
|
||||
"edit": "Редагувати",
|
||||
"editLabel": "Редагувати {{label}}",
|
||||
"editing": "Редагування",
|
||||
"editingLabel_many": "Редагування {{count}} {{label}}",
|
||||
"editingLabel_one": "Редагування {{count}} {{label}}",
|
||||
"editingLabel_other": "Редагування {{count}} {{label}}",
|
||||
"email": "Email",
|
||||
"emailAddress": "Email адреса",
|
||||
"enterAValue": "Введіть значення",
|
||||
@@ -204,7 +214,9 @@
|
||||
"save": "Зберегти",
|
||||
"saving": "Збереження...",
|
||||
"searchBy": "Шукати по {{label}}",
|
||||
"selectAll": "Вибрати всі {{count}} {{label}}",
|
||||
"selectValue": "Вибрати значення",
|
||||
"selectedCount": "Вибрано {{count}} {{label}}",
|
||||
"sorryNotFound": "Вибачте - немає нічого, що відповідало б Вашому запиту.",
|
||||
"sort": "Сортувати",
|
||||
"stayOnThisPage": "Залишитись на цій сторінці",
|
||||
@@ -218,6 +230,7 @@
|
||||
"unsavedChangesDuplicate": "Ви маєте не збережені зміни. Чи бажаєте ви продовжити дублювання?",
|
||||
"untitled": "Без назви",
|
||||
"updatedAt": "Змінено",
|
||||
"updatedCountSuccessfully": "Успішно оновлено {{count}} {{label}}.",
|
||||
"updatedSuccessfully": "Успішно відредаговано.",
|
||||
"updating": "оновлення",
|
||||
"uploading": "завантаження",
|
||||
@@ -226,20 +239,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": "Розмір файлу",
|
||||
@@ -248,7 +262,6 @@
|
||||
"moreInfo": "Більше інформації",
|
||||
"selectCollectionToBrowse": "Виберіть колекцію для перегляду",
|
||||
"selectFile": "Виберіть файл",
|
||||
"dragAndDrop": "Перемістіть файл",
|
||||
"sizes": "Розміри",
|
||||
"width": "Ширина"
|
||||
},
|
||||
@@ -272,15 +285,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": "Підтвердити відновлення версії",
|
||||
@@ -292,6 +308,7 @@
|
||||
"noRowsFound": "Не знайдено {{label}}",
|
||||
"preview": "Попередній перегляд",
|
||||
"problemRestoringVersion": "Виникла проблема з відновленням цієї версії",
|
||||
"publish": "Опублікувати",
|
||||
"publishChanges": "Опублікувати зміни",
|
||||
"published": "Опубліковано",
|
||||
"restoreThisVersion": "Відновити цю версію",
|
||||
@@ -302,8 +319,8 @@
|
||||
"saveDraft": "Зберегти чернетку",
|
||||
"selectLocales": "Виберіть переклад для відображення",
|
||||
"selectVersionToCompare": "Виберіть версію для порівняння",
|
||||
"showingVersionsFor": "Показані версії для:",
|
||||
"showLocales": "Показати переклади:",
|
||||
"showingVersionsFor": "Показані версії для:",
|
||||
"status": "Статус",
|
||||
"type": "Тип",
|
||||
"unpublish": "Відмінити публікацію",
|
||||
|
||||
@@ -60,8 +60,8 @@
|
||||
"accountAlreadyActivated": "Lỗi - Tài khoản này đã được kích hoạt.",
|
||||
"autosaving": "Lỗi - Đã xảy ra vấn đề khi tự động sao lưu bản tài liệu này.",
|
||||
"correctInvalidFields": "Lỗi - Xin hãy sửa lại những fields không hợp lệ.",
|
||||
"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.",
|
||||
"deletingFile": "Lỗi - Đã xảy ra vấn đề khi xóa file 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_many": "Lỗi - Những fields sau không hợp lệ:",
|
||||
"followingFieldsInvalid_one": "Lỗi - Field sau không hợp lệ:",
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "Lỗi - Đã xảy ra vấn để khi tải lên file sau.",
|
||||
"tokenInvalidOrExpired": "Lỗi - Token không hợp lệ hoặc đã hết hạn.",
|
||||
"unPublishingDocument": "Lỗi - Đã xảy ra vấn để khi ẩn bản tài liệu.",
|
||||
"unableToDeleteCount": "Không thể xóa {{count}} trong số {{total}} {{label}}.",
|
||||
"unableToUpdateCount": "Không thể cập nhật {{count}} trên {{total}} {{label}}.",
|
||||
"unauthorized": "Lỗi - Bạn cần phải đăng nhập trước khi gửi request sau.",
|
||||
"unknown": "Lỗi - Không xác định (unknown error).",
|
||||
"unspecific": "Lỗi - Đã xảy ra (unspecific error).",
|
||||
@@ -90,47 +92,59 @@
|
||||
"verificationTokenInvalid": "Lỗi - Token dùng để xác thực không hợp lệ."
|
||||
},
|
||||
"fields": {
|
||||
"block": "block",
|
||||
"blocks": "blocks",
|
||||
"addLabel": "Thêm: {{label}}",
|
||||
"addLink": "Thêm liên kết",
|
||||
"addNew": "Thêm mới",
|
||||
"addNewLabel": "Thêm mới: {{label}}",
|
||||
"addRelationship": "Thêm mối quan hệ (relationship)",
|
||||
"addUpload": "Thêm tải lên (upload)",
|
||||
"block": "block",
|
||||
"blockType": "Block Type",
|
||||
"blocks": "blocks",
|
||||
"chooseBetweenCustomTextOrDocument": "Chọn giữa nhập URL văn bản tùy chỉnh hoặc liên kết đến tài liệu khác.",
|
||||
"chooseDocumentToLink": "Chọn một tài liệu để liên kết đến",
|
||||
"chooseFromExisting": "Chọn từ vật phẩm có sẵn",
|
||||
"chooseLabel": "Chọn: {{label}}",
|
||||
"collapseAll": "Ẩn toàn bộ",
|
||||
"customURL": "URL tùy chỉnh",
|
||||
"editLabelData": "Chỉnh sửa nội dung của: {{label}}",
|
||||
"editLink": "Chỉnh sửa liên kết",
|
||||
"editRelationship": "Chỉnh sửa mối quan hệ",
|
||||
"enterURL": "Nhập một URL",
|
||||
"internalLink": "Liên kết nội bộ",
|
||||
"itemsAndMore": "{{items}} và {{count}} món nữa",
|
||||
"labelRelationship": "Mối quan hệ của {{label}} (Relationship)",
|
||||
"latitude": "Vĩ độ",
|
||||
"linkType": "Loại liên kết",
|
||||
"linkedTo": "Được nối với <0>{{label}}</0>",
|
||||
"longitude": "Kinh độ",
|
||||
"newLabel": "Tạo {{label}} mới",
|
||||
"openInNewTab": "Mở ra trong trang mới",
|
||||
"passwordsDoNotMatch": "Mật khẩu không trùng.",
|
||||
"relatedDocument": "bản tài liệu liên quan",
|
||||
"relationTo": "Có quan hệ với",
|
||||
"removeReelationship": "Xóa mối quan hệ",
|
||||
"removeUpload": "Xóa bản tải lên",
|
||||
"saveChanges": "Luu thay đổi",
|
||||
"searchForBlock": "Tìm block",
|
||||
"selectExistingLabel": "Chọn một {{label}} có sẵn",
|
||||
"selectFieldsToEdit": "Chọn các trường để chỉnh sửa",
|
||||
"showAll": "Hiển thị toàn bộ",
|
||||
"swapRelationship": "Hoán đổi quan hệ",
|
||||
"swapUpload": "Đổi bản tải lên",
|
||||
"textToDisplay": "Văn bản để hiển thị",
|
||||
"toggleBlock": "Bật/tắt block",
|
||||
"uploadNewLabel": "Tải lên bản mới: {{label}}"
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "Chuẩn bị xóa {{label}} <1>{{title}}</1>. Bạn có muốn tiếp tục không?",
|
||||
"aboutToDeleteCount_many": "Bạn sắp xóa {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "Bạn sắp xóa {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "Bạn sắp xóa {{count}} {{label}}",
|
||||
"addBelow": "Thêm bên dưới",
|
||||
"addFilter": "Thêm bộ lọc",
|
||||
"adminTheme": "Phông nền của trang Admin",
|
||||
"and": "Và",
|
||||
"ascending": "Sắp xếp theo thứ tự tăng dần",
|
||||
"automatic": "Tự động",
|
||||
"backToDashboard": "Quay lại bảng điều khiển",
|
||||
"cancel": "Ngừng thao tác",
|
||||
@@ -153,6 +167,7 @@
|
||||
"dark": "Nền tối",
|
||||
"dashboard": "Bảng điều khiển",
|
||||
"delete": "Xóa",
|
||||
"deletedCountSuccessfully": "Đã xóa thành công {{count}} {{label}}.",
|
||||
"deletedSuccessfully": "Đã xoá thành công.",
|
||||
"deleting": "Đang xóa...",
|
||||
"descending": "Xếp theo thứ tự giảm dần",
|
||||
@@ -161,6 +176,9 @@
|
||||
"edit": "Chỉnh sửa",
|
||||
"editLabel": "Chỉnh sửa: {{label}}",
|
||||
"editing": "Đang chỉnh sửa",
|
||||
"editingLabel_many": "Đang chỉnh sửa {{count}} {{label}}",
|
||||
"editingLabel_one": "Đang chỉnh sửa {{count}} {{label}}",
|
||||
"editingLabel_other": "Đang chỉnh sửa {{count}} {{label}}",
|
||||
"email": "Email",
|
||||
"emailAddress": "Địa chỉ Email",
|
||||
"enterAValue": "Nhập một giá trị",
|
||||
@@ -199,7 +217,9 @@
|
||||
"save": "Luu",
|
||||
"saving": "Đang lưu...",
|
||||
"searchBy": "Tìm với {{label}}",
|
||||
"selectAll": "Chọn tất cả {{count}} {{label}}",
|
||||
"selectValue": "Chọn một giá trị",
|
||||
"selectedCount": "Đã chọn {{count}} {{nhãn}}",
|
||||
"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",
|
||||
"stayOnThisPage": "Ở lại trang này",
|
||||
@@ -213,6 +233,7 @@
|
||||
"unsavedChangesDuplicate": "Bạn chưa lưu các thay đổi. Bạn có muốn tiếp tục tạo bản sao?",
|
||||
"untitled": "Không tiêu đề",
|
||||
"updatedAt": "Được cập nhật vào lúc",
|
||||
"updatedCountSuccessfully": "Đã cập nhật thành công {{count}} {{label}}.",
|
||||
"updatedSuccessfully": "Cập nhật thành công.",
|
||||
"updating": "Đang cập nhật",
|
||||
"uploading": "Đang tải lên",
|
||||
@@ -221,20 +242,21 @@
|
||||
"welcome": "Xin chào"
|
||||
},
|
||||
"operators": {
|
||||
"contains": "chứa",
|
||||
"equals": "bằng",
|
||||
"isNotEqualTo": "không bằng",
|
||||
"isIn": "đang ở",
|
||||
"isNotIn": "không có trong",
|
||||
"exists": "tồn tại",
|
||||
"isGreaterThan": "lớn hơn",
|
||||
"isGreaterThanOrEqualTo": "lớn hơn hoặc bằng",
|
||||
"isIn": "đang ở",
|
||||
"isLessThan": "nhỏ hơn",
|
||||
"isLessThanOrEqualTo": "nhỏ hơn hoặc bằng",
|
||||
"isGreaterThanOrEqualTo": "lớn hơn hoặc bằng",
|
||||
"near": "gần",
|
||||
"isLike": "giống như",
|
||||
"contains": "chứa"
|
||||
"isNotEqualTo": "không bằng",
|
||||
"isNotIn": "không có trong",
|
||||
"near": "gần"
|
||||
},
|
||||
"upload": {
|
||||
"dragAndDrop": "Kéo và thả một tập tin",
|
||||
"dragAndDropHere": "hoặc kéo và thả file vào đây",
|
||||
"fileName": "Tên file",
|
||||
"fileSize": "Dung lượng file",
|
||||
@@ -243,7 +265,6 @@
|
||||
"moreInfo": "Hiển thị nhiều hơn",
|
||||
"selectCollectionToBrowse": "Chọn một Collection để tìm",
|
||||
"selectFile": "Chọn một file",
|
||||
"dragAndDrop": "Kéo và thả một tập tin",
|
||||
"sizes": "Các độ phân giải",
|
||||
"width": "Chiều rộng"
|
||||
},
|
||||
@@ -267,15 +288,18 @@
|
||||
"validUploadID": "'Field này không chứa ID tải lên hợp lệ.'"
|
||||
},
|
||||
"version": {
|
||||
"aboutToPublishSelection": "Bạn sắp xuất bản tất cả {{nhãn}} trong lựa chọn. Bạn có chắc không?",
|
||||
"aboutToRestore": "Bạn chuẩn bị khôi phục lại {{label}} về trạng thái mà bản tài liệu này sở hữu lúc {{versionDate}}.",
|
||||
"aboutToRestoreGlobal": "Bạn chuẩn bị khôi phục lại bản toàn thể (global) của {{label}} về trạng thái mà bản tài liệu này sở hữu lúc {{versionDate}}.",
|
||||
"aboutToRevertToPublished": "Bạn chuẩn bị khiến bản nháp này quay về trạng thái khi được xuất bản. Bạn có muốn tiếp tục không?",
|
||||
"aboutToUnpublish": "Bạn chuẩn bị ẩn bản tài liệu này. Bạn chắc chứ?",
|
||||
"aboutToUnpublishSelection": "Bạn sắp hủy xuất bản tất cả {{nhãn}} trong lựa chọn. Bạn có chắc không?",
|
||||
"autosave": "Tự động lưu dữ liệu",
|
||||
"autosavedSuccessfully": "Đã tự động lưu thành công.",
|
||||
"autosavedVersion": "Các phiên bản từ việc tự động lưu dữ liệu",
|
||||
"changed": "Đã đổi",
|
||||
"compareVersion": "So sánh phiên bản này với:",
|
||||
"confirmPublish": "xác nhận xuất bản",
|
||||
"confirmRevertToSaved": "Xác nhận, quay về trạng thái đã lưu",
|
||||
"confirmUnpublish": "Xác nhận, ẩn tài liệu",
|
||||
"confirmVersionRestoration": "Xác nhận, khôi phục về phiên bản sau",
|
||||
@@ -287,6 +311,7 @@
|
||||
"noRowsFound": "Không tìm thấy: {{label}}",
|
||||
"preview": "Bản xem trước",
|
||||
"problemRestoringVersion": "Đã xảy ra vấn đề khi khôi phục phiên bản này",
|
||||
"publish": "Công bố",
|
||||
"publishChanges": "Xuất bản tài liệu",
|
||||
"published": "Đã xuất bản",
|
||||
"restoreThisVersion": "Khôi phục về phiên bản này",
|
||||
@@ -298,6 +323,7 @@
|
||||
"selectLocales": "Chọn mã khu vực để hiện thị",
|
||||
"selectVersionToCompare": "Chọn phiên bản để so sánh",
|
||||
"showLocales": "Hiển thị mã khu vực:",
|
||||
"showingVersionsFor": "Hiển thị các phiên bản cho:",
|
||||
"status": "Trạng thái",
|
||||
"type": "Loại",
|
||||
"unpublish": "Ẩn tài liệu",
|
||||
@@ -306,6 +332,7 @@
|
||||
"versionCount_many": "{{count}} phiên bản được tìm thấy",
|
||||
"versionCount_none": "Không có phiên bản nào được tìm thấy",
|
||||
"versionCount_one": "{{count}} phiên bản được tìm thấy",
|
||||
"versionCount_other": "Đã tìm thấy {{count}} phiên bản",
|
||||
"versionCreatedOn": "Phiên bản {{version}} được tạo vào lúc:",
|
||||
"versionID": "ID của phiên bản",
|
||||
"versions": "Những phiên bản",
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
"problemUploadingFile": "上传文件时出现了问题。",
|
||||
"tokenInvalidOrExpired": "令牌无效或已过期。",
|
||||
"unPublishingDocument": "取消发布此文件时出现了问题。",
|
||||
"unableToDeleteCount": "无法从 {{total}} {{label}} 中删除 {{count}}。",
|
||||
"unableToUpdateCount": "无法更新 {{count}} 个,共 {{total}} 个 {{label}}。",
|
||||
"unauthorized": "未经授权,您必须登录才能提出这个请求。",
|
||||
"unknown": "发生了一个未知的错误。",
|
||||
"unspecific": "发生了一个错误。",
|
||||
@@ -126,6 +128,7 @@
|
||||
"saveChanges": "保存更改",
|
||||
"searchForBlock": "搜索一个区块",
|
||||
"selectExistingLabel": "选择现有的{{label}}",
|
||||
"selectFieldsToEdit": "选择要编辑的字段",
|
||||
"showAll": "显示全部",
|
||||
"swapRelationship": "交换关系",
|
||||
"swapUpload": "交换上传",
|
||||
@@ -135,6 +138,9 @@
|
||||
},
|
||||
"general": {
|
||||
"aboutToDelete": "您即将删除{{label}} <1>{{title}}</1>。您确定要继续吗?",
|
||||
"aboutToDeleteCount_many": "您即将删除 {{count}} {{label}}",
|
||||
"aboutToDeleteCount_one": "您即将删除 {{count}} {{label}}",
|
||||
"aboutToDeleteCount_other": "您即将删除 {{count}} {{label}}",
|
||||
"addBelow": "添加到下面",
|
||||
"addFilter": "添加过滤器",
|
||||
"adminTheme": "管理页面主题",
|
||||
@@ -162,6 +168,7 @@
|
||||
"dark": "深色",
|
||||
"dashboard": "仪表板",
|
||||
"delete": "删除",
|
||||
"deletedCountSuccessfully": "已成功删除 {{count}} {{label}}。",
|
||||
"deletedSuccessfully": "已成功删除。",
|
||||
"deleting": "删除中...",
|
||||
"descending": "降序",
|
||||
@@ -170,6 +177,9 @@
|
||||
"edit": "编辑",
|
||||
"editLabel": "编辑{{label}}",
|
||||
"editing": "编辑中",
|
||||
"editingLabel_many": "编辑 {{count}} {{label}}",
|
||||
"editingLabel_one": "编辑 {{count}} {{label}}",
|
||||
"editingLabel_other": "编辑 {{count}} {{label}}",
|
||||
"email": "电子邮件",
|
||||
"emailAddress": "电子邮件地址",
|
||||
"enterAValue": "输入一个值",
|
||||
@@ -208,7 +218,9 @@
|
||||
"save": "保存",
|
||||
"saving": "保存中...",
|
||||
"searchBy": "搜索{{label}}",
|
||||
"selectAll": "选择所有 {{count}} {{label}}",
|
||||
"selectValue": "选择一个值",
|
||||
"selectedCount": "已选择 {{count}} {{label}}",
|
||||
"sorryNotFound": "对不起,没有与您的请求相对应的东西。",
|
||||
"sort": "排序",
|
||||
"stayOnThisPage": "停留在此页面",
|
||||
@@ -222,26 +234,28 @@
|
||||
"unsavedChangesDuplicate": "您有未保存的修改。您确定要继续重复吗?",
|
||||
"untitled": "无标题",
|
||||
"updatedAt": "更新于",
|
||||
"updatedCountSuccessfully": "已成功更新 {{count}} {{label}}。",
|
||||
"updatedSuccessfully": "更新成功。",
|
||||
"user": "用户",
|
||||
"users": "用户",
|
||||
"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": "文件大小",
|
||||
@@ -250,7 +264,6 @@
|
||||
"moreInfo": "更多信息",
|
||||
"selectCollectionToBrowse": "选择一个要浏览的集合",
|
||||
"selectFile": "选择一个文件",
|
||||
"dragAndDrop": "拖放一个文件",
|
||||
"sizes": "尺寸",
|
||||
"width": "宽度"
|
||||
},
|
||||
@@ -274,15 +287,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": "确认版本恢复",
|
||||
@@ -294,6 +310,7 @@
|
||||
"noRowsFound": "没有发现{{label}}",
|
||||
"preview": "预览",
|
||||
"problemRestoringVersion": "恢复这个版本时发生了问题",
|
||||
"publish": "发布",
|
||||
"publishChanges": "发布修改",
|
||||
"published": "已发布",
|
||||
"restoreThisVersion": "恢复此版本",
|
||||
@@ -304,8 +321,8 @@
|
||||
"saveDraft": "保存草稿",
|
||||
"selectLocales": "选择要显示的语言",
|
||||
"selectVersionToCompare": "选择要比较的版本",
|
||||
"showingVersionsFor": "显示版本为:",
|
||||
"showLocales": "显示语言:",
|
||||
"showingVersionsFor": "显示版本为:",
|
||||
"status": "状态",
|
||||
"type": "类型",
|
||||
"unpublish": "取消发布",
|
||||
|
||||
56
src/uploads/deleteAssociatedFiles.ts
Normal file
56
src/uploads/deleteAssociatedFiles.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import type { TFunction } from 'i18next';
|
||||
import fileExists from './fileExists';
|
||||
import { ErrorDeletingFile } from '../errors';
|
||||
import type { FileData, FileToSave } from './types';
|
||||
import type { SanitizedConfig } from '../config/types';
|
||||
import type { SanitizedCollectionConfig } from '../collections/config/types';
|
||||
|
||||
type Args = {
|
||||
config: SanitizedConfig
|
||||
collectionConfig: SanitizedCollectionConfig
|
||||
files?: FileToSave[]
|
||||
doc: Record<string, unknown>
|
||||
t: TFunction
|
||||
overrideDelete: boolean
|
||||
}
|
||||
|
||||
export const deleteAssociatedFiles: (args: Args) => Promise<void> = async ({
|
||||
config,
|
||||
collectionConfig,
|
||||
files = [],
|
||||
doc,
|
||||
t,
|
||||
overrideDelete,
|
||||
}) => {
|
||||
if (!collectionConfig.upload) return;
|
||||
if (overrideDelete || files.length > 0) {
|
||||
const { staticDir } = collectionConfig.upload;
|
||||
const staticPath = path.resolve(config.paths.configDir, staticDir);
|
||||
|
||||
const fileToDelete = `${staticPath}/${doc.filename}`;
|
||||
|
||||
if (await fileExists(fileToDelete)) {
|
||||
fs.unlink(fileToDelete, (err) => {
|
||||
if (err) {
|
||||
throw new ErrorDeletingFile(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (doc.sizes) {
|
||||
Object.values(doc.sizes)
|
||||
.forEach(async (size: FileData) => {
|
||||
const sizeToDelete = `${staticPath}/${size.filename}`;
|
||||
if (await fileExists(sizeToDelete)) {
|
||||
fs.unlink(sizeToDelete, (err) => {
|
||||
if (err) {
|
||||
throw new ErrorDeletingFile(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -74,6 +74,7 @@ const getBaseUploadFields = ({ config, collection }: Options): Field[] => {
|
||||
admin: {
|
||||
readOnly: true,
|
||||
hidden: true,
|
||||
disableBulkEdit: true,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
33
src/uploads/unlinkTempFiles.ts
Normal file
33
src/uploads/unlinkTempFiles.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import fs from 'fs';
|
||||
import { promisify } from 'util';
|
||||
import { mapAsync } from '../utilities/mapAsync';
|
||||
import type { PayloadRequest } from '../express/types';
|
||||
import type { SanitizedConfig } from '../config/types';
|
||||
import type { SanitizedCollectionConfig } from '../collections/config/types';
|
||||
|
||||
const unlinkFile = promisify(fs.unlink);
|
||||
|
||||
type Args = {
|
||||
req: PayloadRequest
|
||||
config: SanitizedConfig
|
||||
collectionConfig: SanitizedCollectionConfig
|
||||
}
|
||||
/**
|
||||
* Remove temp files if enabled, as express-fileupload does not do this automatically
|
||||
*/
|
||||
export const unlinkTempFiles: (args: Args) => Promise<void> = async ({
|
||||
req,
|
||||
config,
|
||||
collectionConfig,
|
||||
}) => {
|
||||
if (config.upload?.useTempFiles && collectionConfig.upload) {
|
||||
const { files } = req;
|
||||
const fileArray = Array.isArray(files) ? files : [files];
|
||||
await mapAsync(fileArray, async ({ file }) => {
|
||||
// Still need this check because this will not be populated if using local API
|
||||
if (file.tempFilePath) {
|
||||
await unlinkFile(file.tempFilePath);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -22,6 +22,7 @@ const baseVersionFields: Field[] = [
|
||||
options: statuses,
|
||||
defaultValue: 'draft',
|
||||
admin: {
|
||||
disableBulkEdit: true,
|
||||
components: {
|
||||
Field: () => null,
|
||||
},
|
||||
|
||||
@@ -18,7 +18,7 @@ type Args = {
|
||||
accessResult: AccessResult
|
||||
collection: Collection
|
||||
locale: string
|
||||
paginationOptions: PaginateOptions
|
||||
paginationOptions?: PaginateOptions
|
||||
payload: Payload
|
||||
where: Where
|
||||
}
|
||||
@@ -69,25 +69,32 @@ export const queryDrafts = async <T extends TypeWithID>({
|
||||
allowDiskUse: true,
|
||||
});
|
||||
|
||||
const aggregatePaginateOptions = {
|
||||
...paginationOptions,
|
||||
useFacet: payload.mongoOptions?.useFacet,
|
||||
sort: Object.entries(paginationOptions.sort).reduce((sort, [incomingSortKey, order]) => {
|
||||
let key = incomingSortKey;
|
||||
let result;
|
||||
|
||||
if (!['createdAt', 'updatedAt', '_id'].includes(incomingSortKey)) {
|
||||
key = `version.${incomingSortKey}`
|
||||
}
|
||||
if (paginationOptions) {
|
||||
const aggregatePaginateOptions = {
|
||||
...paginationOptions,
|
||||
useFacet: payload.mongoOptions?.useFacet,
|
||||
sort: Object.entries(paginationOptions.sort)
|
||||
.reduce((sort, [incomingSortKey, order]) => {
|
||||
let key = incomingSortKey;
|
||||
|
||||
return {
|
||||
...sort,
|
||||
[key]: order === 'asc' ? 1 : -1,
|
||||
};
|
||||
}, {})
|
||||
if (!['createdAt', 'updatedAt', '_id'].includes(incomingSortKey)) {
|
||||
key = `version.${incomingSortKey}`;
|
||||
}
|
||||
|
||||
return {
|
||||
...sort,
|
||||
[key]: order === 'asc' ? 1 : -1,
|
||||
};
|
||||
}, {}),
|
||||
};
|
||||
|
||||
result = await VersionModel.aggregatePaginate(aggregate, aggregatePaginateOptions);
|
||||
} else {
|
||||
result = aggregate.exec();
|
||||
}
|
||||
|
||||
const result = await VersionModel.aggregatePaginate(aggregate, aggregatePaginateOptions);
|
||||
|
||||
return {
|
||||
...result,
|
||||
docs: result.docs.map((doc) => ({
|
||||
|
||||
Reference in New Issue
Block a user