fix: deprecate inconsistent config param case (#4172)
This commit is contained in:
51
packages/netlify-cms-core/index.d.ts
vendored
51
packages/netlify-cms-core/index.d.ts
vendored
@ -61,8 +61,21 @@ declare module 'netlify-cms-core' {
|
||||
|
||||
/** If widget === "datetime" */
|
||||
format?: string;
|
||||
date_format?: boolean | string;
|
||||
time_format?: boolean | string;
|
||||
picker_utc?: boolean;
|
||||
|
||||
/**
|
||||
* @deprecated Use date_format instead
|
||||
*/
|
||||
dateFormat?: boolean | string;
|
||||
/**
|
||||
* @deprecated Use time_format instead
|
||||
*/
|
||||
timeFormat?: boolean | string;
|
||||
/**
|
||||
* @deprecated Use picker_utc instead
|
||||
*/
|
||||
pickerUtc?: boolean;
|
||||
|
||||
/** If widget === "file" || widget === "image" */
|
||||
@ -89,12 +102,22 @@ declare module 'netlify-cms-core' {
|
||||
/** If widget === "markdown" */
|
||||
minimal?: boolean;
|
||||
buttons?: CmsMarkdownWidgetButton[];
|
||||
editor_components?: string[];
|
||||
|
||||
/**
|
||||
* @deprecated Use editor_components instead
|
||||
*/
|
||||
editorComponents?: string[];
|
||||
|
||||
/** If widget === "number" */
|
||||
valueType?: 'int' | 'float' | string;
|
||||
value_type?: 'int' | 'float' | string;
|
||||
step?: number;
|
||||
|
||||
/**
|
||||
* @deprecated Use valueType instead
|
||||
*/
|
||||
valueType?: 'int' | 'float' | string;
|
||||
|
||||
/** If widget === "number" || widget === "select" */
|
||||
min?: number;
|
||||
max?: number;
|
||||
@ -104,10 +127,27 @@ declare module 'netlify-cms-core' {
|
||||
|
||||
/** If widget === "relation" */
|
||||
collection?: string;
|
||||
valueField?: string;
|
||||
searchFields?: string[];
|
||||
value_field?: string;
|
||||
search_fields?: string[];
|
||||
file?: string;
|
||||
display_fields?: string[];
|
||||
options_length?: number;
|
||||
|
||||
/**
|
||||
* @deprecated Use value_field instead
|
||||
*/
|
||||
valueField?: string;
|
||||
/**
|
||||
* @deprecated Use search_fields instead
|
||||
*/
|
||||
searchFields?: string[];
|
||||
/**
|
||||
* @deprecated Use display_fields instead
|
||||
*/
|
||||
displayFields?: string[];
|
||||
/**
|
||||
* @deprecated Use options_length instead
|
||||
*/
|
||||
optionsLength?: number;
|
||||
|
||||
/** If widget === "select" */
|
||||
@ -155,6 +195,11 @@ declare module 'netlify-cms-core' {
|
||||
path?: string;
|
||||
media_folder?: string;
|
||||
public_folder?: string;
|
||||
sortable_fields?: string[];
|
||||
|
||||
/**
|
||||
* @deprecated Use sortable_fields instead
|
||||
*/
|
||||
sortableFields?: string[];
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,15 @@
|
||||
import { fromJS } from 'immutable';
|
||||
import { stripIndent } from 'common-tags';
|
||||
import { parseConfig, applyDefaults, detectProxyServer, handleLocalBackend } from '../config';
|
||||
import {
|
||||
parseConfig,
|
||||
normalizeConfig,
|
||||
applyDefaults,
|
||||
detectProxyServer,
|
||||
handleLocalBackend,
|
||||
} from '../config';
|
||||
|
||||
jest.spyOn(console, 'log').mockImplementation(() => {});
|
||||
jest.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
jest.mock('coreSrc/backend', () => {
|
||||
return {
|
||||
resolveBackend: jest.fn(() => ({ isGitBackend: jest.fn(() => true) })),
|
||||
@ -413,6 +420,119 @@ describe('config', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('should convert camel case to snake case', () => {
|
||||
expect(
|
||||
applyDefaults(
|
||||
normalizeConfig(
|
||||
fromJS({
|
||||
collections: [
|
||||
{
|
||||
sortableFields: ['title'],
|
||||
folder: 'src',
|
||||
identifier_field: 'datetime',
|
||||
fields: [
|
||||
{
|
||||
name: 'datetime',
|
||||
widget: 'datetime',
|
||||
dateFormat: 'YYYY/MM/DD',
|
||||
timeFormat: 'HH:mm',
|
||||
pickerUtc: true,
|
||||
},
|
||||
{
|
||||
widget: 'number',
|
||||
valueType: 'float',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sortableFields: [],
|
||||
files: [
|
||||
{
|
||||
name: 'file',
|
||||
file: 'src/file.json',
|
||||
fields: [
|
||||
{
|
||||
widget: 'markdown',
|
||||
editorComponents: ['code'],
|
||||
},
|
||||
{
|
||||
widget: 'relation',
|
||||
valueField: 'title',
|
||||
searchFields: ['title'],
|
||||
displayFields: ['title'],
|
||||
optionsLength: 5,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
).toJS(),
|
||||
).toEqual({
|
||||
public_folder: '/',
|
||||
publish_mode: 'simple',
|
||||
slug: { clean_accents: false, encoding: 'unicode', sanitize_replacement: '-' },
|
||||
collections: [
|
||||
{
|
||||
sortable_fields: ['title'],
|
||||
folder: 'src',
|
||||
identifier_field: 'datetime',
|
||||
fields: [
|
||||
{
|
||||
name: 'datetime',
|
||||
widget: 'datetime',
|
||||
date_format: 'YYYY/MM/DD',
|
||||
dateFormat: 'YYYY/MM/DD',
|
||||
time_format: 'HH:mm',
|
||||
timeFormat: 'HH:mm',
|
||||
picker_utc: true,
|
||||
pickerUtc: true,
|
||||
},
|
||||
{
|
||||
widget: 'number',
|
||||
value_type: 'float',
|
||||
valueType: 'float',
|
||||
},
|
||||
],
|
||||
meta: {},
|
||||
publish: true,
|
||||
view_filters: [],
|
||||
},
|
||||
{
|
||||
sortable_fields: [],
|
||||
files: [
|
||||
{
|
||||
name: 'file',
|
||||
file: 'src/file.json',
|
||||
fields: [
|
||||
{
|
||||
widget: 'markdown',
|
||||
editor_components: ['code'],
|
||||
editorComponents: ['code'],
|
||||
},
|
||||
{
|
||||
widget: 'relation',
|
||||
value_field: 'title',
|
||||
valueField: 'title',
|
||||
search_fields: ['title'],
|
||||
searchFields: ['title'],
|
||||
display_fields: ['title'],
|
||||
displayFields: ['title'],
|
||||
options_length: 5,
|
||||
optionsLength: 5,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
publish: true,
|
||||
view_filters: [],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('detectProxyServer', () => {
|
||||
|
@ -31,10 +31,79 @@ const setDefaultPublicFolder = map => {
|
||||
return map;
|
||||
};
|
||||
|
||||
const setSnakeCaseConfig = field => {
|
||||
// Mapping between existing camelCase and its snake_case counterpart
|
||||
const widgetKeyMap = {
|
||||
dateFormat: 'date_format',
|
||||
timeFormat: 'time_format',
|
||||
pickerUtc: 'picker_utc',
|
||||
editorComponents: 'editor_components',
|
||||
valueType: 'value_type',
|
||||
valueField: 'value_field',
|
||||
searchFields: 'search_fields',
|
||||
displayFields: 'display_fields',
|
||||
optionsLength: 'options_length',
|
||||
};
|
||||
|
||||
Object.entries(widgetKeyMap).forEach(([camel, snake]) => {
|
||||
if (field.has(camel)) {
|
||||
field = field.set(snake, field.get(camel));
|
||||
console.warn(
|
||||
`Field ${field.get(
|
||||
'name',
|
||||
)} is using a deprecated configuration '${camel}'. Please use '${snake}'`,
|
||||
);
|
||||
}
|
||||
});
|
||||
return field;
|
||||
};
|
||||
|
||||
const defaults = {
|
||||
publish_mode: publishModes.SIMPLE,
|
||||
};
|
||||
|
||||
export function normalizeConfig(config) {
|
||||
return Map(config).withMutations(map => {
|
||||
map.set(
|
||||
'collections',
|
||||
map.get('collections').map(collection => {
|
||||
const folder = collection.get('folder');
|
||||
if (folder) {
|
||||
collection = collection.set(
|
||||
'fields',
|
||||
traverseFields(collection.get('fields'), setSnakeCaseConfig),
|
||||
);
|
||||
}
|
||||
|
||||
const files = collection.get('files');
|
||||
if (files) {
|
||||
collection = collection.set(
|
||||
'files',
|
||||
files.map(file => {
|
||||
file = file.set('fields', traverseFields(file.get('fields'), setSnakeCaseConfig));
|
||||
return file;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (collection.has('sortableFields')) {
|
||||
collection = collection
|
||||
.set('sortable_fields', collection.get('sortableFields'))
|
||||
.delete('sortableFields');
|
||||
|
||||
console.warn(
|
||||
`Collection ${collection.get(
|
||||
'name',
|
||||
)} is using a deprecated configuration 'sortableFields'. Please use 'sortable_fields'`,
|
||||
);
|
||||
}
|
||||
|
||||
return collection;
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function applyDefaults(config) {
|
||||
return Map(defaults)
|
||||
.mergeDeep(config)
|
||||
@ -118,10 +187,10 @@ export function applyDefaults(config) {
|
||||
);
|
||||
}
|
||||
|
||||
if (!collection.has('sortableFields')) {
|
||||
if (!collection.has('sortable_fields')) {
|
||||
const backend = resolveBackend(config);
|
||||
const defaultSortable = selectDefaultSortableFields(collection, backend);
|
||||
collection = collection.set('sortableFields', fromJS(defaultSortable));
|
||||
collection = collection.set('sortable_fields', fromJS(defaultSortable));
|
||||
}
|
||||
|
||||
if (!collection.has('view_filters')) {
|
||||
@ -283,7 +352,7 @@ export function loadConfig() {
|
||||
|
||||
mergedConfig = await handleLocalBackend(mergedConfig);
|
||||
|
||||
const config = applyDefaults(mergedConfig);
|
||||
const config = applyDefaults(normalizeConfig(mergedConfig));
|
||||
|
||||
dispatch(configDidLoad(config));
|
||||
dispatch(authenticateUser());
|
||||
|
@ -21,7 +21,7 @@ const renderWithRedux = (component, { store } = {}) => {
|
||||
};
|
||||
|
||||
describe('Collection', () => {
|
||||
const collection = fromJS({ name: 'pages', sortableFields: [], view_filters: [] });
|
||||
const collection = fromJS({ name: 'pages', sortable_fields: [], view_filters: [] });
|
||||
const props = {
|
||||
collections: fromJS([collection]).toOrderedMap(),
|
||||
collection,
|
||||
|
@ -14,8 +14,8 @@ exports[`Collection should render connected component 1`] = `
|
||||
class="emotion-2 emotion-3"
|
||||
>
|
||||
<mock-sidebar
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [] }"
|
||||
collections="OrderedMap { 0: Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [] } }"
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [] }"
|
||||
collections="OrderedMap { 0: Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [] } }"
|
||||
filterterm=""
|
||||
searchterm=""
|
||||
/>
|
||||
@ -23,7 +23,7 @@ exports[`Collection should render connected component 1`] = `
|
||||
class="emotion-0 emotion-1"
|
||||
>
|
||||
<mock-collection-top
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [] }"
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [] }"
|
||||
newentryurl=""
|
||||
/>
|
||||
<mock-collection-controls
|
||||
@ -32,7 +32,7 @@ exports[`Collection should render connected component 1`] = `
|
||||
viewfilters=""
|
||||
/>
|
||||
<mock-entries-collection
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [] }"
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [] }"
|
||||
filterterm=""
|
||||
/>
|
||||
</main>
|
||||
@ -54,19 +54,19 @@ exports[`Collection should render with collection with create url 1`] = `
|
||||
class="emotion-2 emotion-3"
|
||||
>
|
||||
<mock-sidebar
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
collections="OrderedMap { 0: Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [] } }"
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
collections="OrderedMap { 0: Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [] } }"
|
||||
/>
|
||||
<main
|
||||
class="emotion-0 emotion-1"
|
||||
>
|
||||
<mock-collection-top
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
newentryurl="/collections/pages/new"
|
||||
/>
|
||||
<mock-collection-controls />
|
||||
<mock-entries-collection
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
/>
|
||||
</main>
|
||||
</div>
|
||||
@ -87,20 +87,20 @@ exports[`Collection should render with collection with create url and path 1`] =
|
||||
class="emotion-2 emotion-3"
|
||||
>
|
||||
<mock-sidebar
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
collections="OrderedMap { 0: Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [] } }"
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
collections="OrderedMap { 0: Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [] } }"
|
||||
filterterm="dir1/dir2"
|
||||
/>
|
||||
<main
|
||||
class="emotion-0 emotion-1"
|
||||
>
|
||||
<mock-collection-top
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
newentryurl="/collections/pages/new?path=dir1/dir2"
|
||||
/>
|
||||
<mock-collection-controls />
|
||||
<mock-entries-collection
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
filterterm="dir1/dir2"
|
||||
/>
|
||||
</main>
|
||||
@ -122,19 +122,19 @@ exports[`Collection should render with collection without create url 1`] = `
|
||||
class="emotion-2 emotion-3"
|
||||
>
|
||||
<mock-sidebar
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": false }"
|
||||
collections="OrderedMap { 0: Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [] } }"
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [], \\"create\\": false }"
|
||||
collections="OrderedMap { 0: Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [] } }"
|
||||
/>
|
||||
<main
|
||||
class="emotion-0 emotion-1"
|
||||
>
|
||||
<mock-collection-top
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": false }"
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [], \\"create\\": false }"
|
||||
newentryurl=""
|
||||
/>
|
||||
<mock-collection-controls />
|
||||
<mock-entries-collection
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": false }"
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortable_fields\\": List [], \\"view_filters\\": List [], \\"create\\": false }"
|
||||
/>
|
||||
</main>
|
||||
</div>
|
||||
|
@ -183,24 +183,38 @@ describe('config', () => {
|
||||
}).not.toThrowError();
|
||||
});
|
||||
|
||||
it('should throw if collections sortableFields is not a boolean or a string array', () => {
|
||||
it('should throw if collections sortable_fields is not a boolean or a string array', () => {
|
||||
expect(() => {
|
||||
validateConfig(merge({}, validConfig, { collections: [{ sortableFields: 'title' }] }));
|
||||
}).toThrowError("'collections[0].sortableFields' should be array");
|
||||
validateConfig(merge({}, validConfig, { collections: [{ sortable_fields: 'title' }] }));
|
||||
}).toThrowError("'collections[0].sortable_fields' should be array");
|
||||
});
|
||||
|
||||
it('should allow sortableFields to be a string array', () => {
|
||||
it('should allow sortable_fields to be a string array', () => {
|
||||
expect(() => {
|
||||
validateConfig(merge({}, validConfig, { collections: [{ sortableFields: ['title'] }] }));
|
||||
validateConfig(merge({}, validConfig, { collections: [{ sortable_fields: ['title'] }] }));
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should allow sortableFields to be a an empty array', () => {
|
||||
it('should allow sortable_fields to be a an empty array', () => {
|
||||
expect(() => {
|
||||
validateConfig(merge({}, validConfig, { collections: [{ sortable_fields: [] }] }));
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should allow sortableFields instead of sortable_fields', () => {
|
||||
expect(() => {
|
||||
validateConfig(merge({}, validConfig, { collections: [{ sortableFields: [] }] }));
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should throw if both sortable_fields and sortableFields exist', () => {
|
||||
expect(() => {
|
||||
validateConfig(
|
||||
merge({}, validConfig, { collections: [{ sortable_fields: [], sortableFields: [] }] }),
|
||||
);
|
||||
}).toThrowError("'collections[0]' should NOT be valid");
|
||||
});
|
||||
|
||||
it('should throw if collection names are not unique', () => {
|
||||
expect(() => {
|
||||
validateConfig(
|
||||
@ -285,14 +299,14 @@ describe('config', () => {
|
||||
name: 'relation',
|
||||
schema: {
|
||||
properties: {
|
||||
searchFields: { type: 'array', items: { type: 'string' } },
|
||||
displayFields: { type: 'array', items: { type: 'string' } },
|
||||
search_fields: { type: 'array', items: { type: 'string' } },
|
||||
display_fields: { type: 'array', items: { type: 'string' } },
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
it('should throw if nested relation displayFields and searchFields are not arrays', () => {
|
||||
it('should throw if nested relation display_fields and search_fields are not arrays', () => {
|
||||
expect(() => {
|
||||
validateConfig(
|
||||
merge({}, validConfig, {
|
||||
@ -310,8 +324,8 @@ describe('config', () => {
|
||||
name: 'relation',
|
||||
label: 'relation',
|
||||
widget: 'relation',
|
||||
displayFields: 'title',
|
||||
searchFields: 'title',
|
||||
display_fields: 'title',
|
||||
search_fields: 'title',
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -320,10 +334,10 @@ describe('config', () => {
|
||||
],
|
||||
}),
|
||||
);
|
||||
}).toThrowError("'searchFields' should be array\n'displayFields' should be array");
|
||||
}).toThrowError("'search_fields' should be array\n'display_fields' should be array");
|
||||
});
|
||||
|
||||
it('should not throw if nested relation displayFields and searchFields are arrays', () => {
|
||||
it('should not throw if nested relation display_fields and search_fields are arrays', () => {
|
||||
expect(() => {
|
||||
validateConfig(
|
||||
merge({}, validConfig, {
|
||||
@ -341,8 +355,8 @@ describe('config', () => {
|
||||
name: 'relation',
|
||||
label: 'relation',
|
||||
widget: 'relation',
|
||||
displayFields: ['title'],
|
||||
searchFields: ['title'],
|
||||
display_fields: ['title'],
|
||||
search_fields: ['title'],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -181,6 +181,12 @@ const getConfigSchema = () => ({
|
||||
},
|
||||
},
|
||||
fields: fieldsConfig(),
|
||||
sortable_fields: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
sortableFields: {
|
||||
type: 'array',
|
||||
items: {
|
||||
@ -215,6 +221,9 @@ const getConfigSchema = () => ({
|
||||
},
|
||||
required: ['name', 'label'],
|
||||
oneOf: [{ required: ['files'] }, { required: ['folder', 'fields'] }],
|
||||
not: {
|
||||
required: ['sortable_fields', 'sortableFields'],
|
||||
},
|
||||
if: { required: ['extension'] },
|
||||
then: {
|
||||
// Cannot infer format from extension.
|
||||
|
@ -245,6 +245,7 @@ export const traverseFields = (
|
||||
if (done()) {
|
||||
return fields;
|
||||
}
|
||||
|
||||
fields = fields
|
||||
.map(f => {
|
||||
const field = updater(f as EntryField);
|
||||
@ -395,7 +396,7 @@ export const selectDefaultSortableFields = (collection: Collection, backend: Bac
|
||||
|
||||
export const selectSortableFields = (collection: Collection, t: (key: string) => string) => {
|
||||
const fields = collection
|
||||
.get('sortableFields')
|
||||
.get('sortable_fields')
|
||||
.toArray()
|
||||
.map(key => {
|
||||
if (key === COMMIT_DATE) {
|
||||
|
@ -183,7 +183,7 @@ type CollectionObject = {
|
||||
slug?: string;
|
||||
label_singular?: string;
|
||||
label: string;
|
||||
sortableFields: List<string>;
|
||||
sortable_fields: List<string>;
|
||||
view_filters: List<StaticallyTypedRecord<ViewFilter>>;
|
||||
nested?: Nested;
|
||||
meta?: Meta;
|
||||
|
Reference in New Issue
Block a user