decap-cms-core 3.8.1 → 3.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/decap-cms-core.js +23 -23
- package/dist/decap-cms-core.js.LICENSE.txt +10 -0
- package/dist/decap-cms-core.js.map +1 -1
- package/dist/esm/actions/config.js +19 -0
- package/dist/esm/actions/entries.js +10 -1
- package/dist/esm/bootstrap.js +2 -2
- package/dist/esm/components/App/StatusBar.js +41 -0
- package/dist/esm/components/Collection/Entries/Pagination.js +132 -0
- package/dist/esm/components/Editor/EditorNotesPane/AddNoteForm.js +111 -0
- package/dist/esm/components/Editor/EditorNotesPane/EditorNotesPane.js +138 -0
- package/dist/esm/components/Editor/EditorNotesPane/NoteItem.js +247 -0
- package/dist/esm/components/Editor/EditorNotesPane/NotesList.js +54 -0
- package/dist/esm/components/UI/ErrorBoundary.js +6 -9
- package/dist/esm/constants/configSchema.js +41 -23
- package/dist/esm/lib/entryCache.js +145 -0
- package/dist/esm/lib/entryHelpers.js +102 -0
- package/dist/esm/lib/formatters.js +2 -1
- package/dist/esm/lib/immutableHelpers.js +21 -0
- package/dist/esm/lib/indexFileHelper.js +36 -0
- package/dist/esm/lib/pagination.js +68 -0
- package/dist/esm/reducers/collections.js +54 -5
- package/dist/esm/reducers/entries.js +9 -4
- package/index.d.ts +10 -2
- package/package.json +2 -3
- package/src/actions/__tests__/config.spec.js +4 -4
- package/src/actions/config.ts +22 -0
- package/src/actions/entries.ts +11 -1
- package/src/components/UI/ErrorBoundary.js +1 -2
- package/src/constants/__tests__/configSchema.spec.js +84 -0
- package/src/constants/configSchema.js +34 -1
- package/src/lib/__tests__/formatters.spec.js +30 -2
- package/src/lib/formatters.ts +6 -1
- package/src/reducers/__tests__/collections.spec.js +39 -0
- package/src/reducers/__tests__/entries.spec.js +3 -3
- package/src/reducers/collections.ts +52 -5
- package/src/reducers/entries.ts +13 -5
- package/src/types/redux.ts +11 -3
|
@@ -412,23 +412,46 @@ export function selectDefaultSortableFields(
|
|
|
412
412
|
defaultSortable = [COMMIT_DATE, ...defaultSortable];
|
|
413
413
|
}
|
|
414
414
|
|
|
415
|
-
|
|
415
|
+
// Return as objects with field property
|
|
416
|
+
return defaultSortable.map(field => ({ field })) as {
|
|
417
|
+
field: string;
|
|
418
|
+
label?: string;
|
|
419
|
+
default_sort?: boolean | 'asc' | 'desc';
|
|
420
|
+
}[];
|
|
416
421
|
}
|
|
417
422
|
|
|
418
423
|
export function selectSortableFields(collection: Collection, t: (key: string) => string) {
|
|
419
424
|
const fields = collection
|
|
420
425
|
.get('sortable_fields')
|
|
421
426
|
.toArray()
|
|
422
|
-
.map(
|
|
427
|
+
.map(sortableField => {
|
|
428
|
+
// Extract the field name and custom label from the sortable field object
|
|
429
|
+
const key = sortableField.get('field');
|
|
430
|
+
const customLabel = sortableField.get('label');
|
|
431
|
+
|
|
423
432
|
if (key === COMMIT_DATE) {
|
|
424
|
-
|
|
433
|
+
const label = customLabel || t('collection.defaultFields.updatedOn.label');
|
|
434
|
+
return { key, field: { name: key, label } };
|
|
425
435
|
}
|
|
426
436
|
const field = selectField(collection, key);
|
|
427
437
|
if (key === COMMIT_AUTHOR && !field) {
|
|
428
|
-
|
|
438
|
+
const label = customLabel || t('collection.defaultFields.author.label');
|
|
439
|
+
return { key, field: { name: key, label } };
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
let fieldObj: Record<string, unknown> | undefined = field?.toJS();
|
|
443
|
+
|
|
444
|
+
// If custom label is provided, override the field's label
|
|
445
|
+
if (fieldObj && customLabel) {
|
|
446
|
+
fieldObj = { ...fieldObj, label: customLabel };
|
|
429
447
|
}
|
|
430
448
|
|
|
431
|
-
|
|
449
|
+
// If no label exists at all, use the field name
|
|
450
|
+
if (fieldObj && !fieldObj.label) {
|
|
451
|
+
fieldObj = { ...fieldObj, label: (fieldObj.name as string) || key };
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
return { key, field: fieldObj };
|
|
432
455
|
})
|
|
433
456
|
.filter(item => !!item.field)
|
|
434
457
|
.map(item => ({ ...item.field, key: item.key }));
|
|
@@ -436,6 +459,30 @@ export function selectSortableFields(collection: Collection, t: (key: string) =>
|
|
|
436
459
|
return fields;
|
|
437
460
|
}
|
|
438
461
|
|
|
462
|
+
export function selectDefaultSortField(collection: Collection) {
|
|
463
|
+
const sortableFields = collection.get('sortable_fields').toArray();
|
|
464
|
+
const defaultField = sortableFields.find(field => field.get('default_sort') !== undefined);
|
|
465
|
+
|
|
466
|
+
if (!defaultField) {
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const fieldName = defaultField.get('field');
|
|
471
|
+
const defaultSortValue = defaultField.get('default_sort');
|
|
472
|
+
|
|
473
|
+
// Determine direction based on default_sort value
|
|
474
|
+
let direction;
|
|
475
|
+
if (defaultSortValue === true || defaultSortValue === 'asc') {
|
|
476
|
+
direction = 'asc';
|
|
477
|
+
} else if (defaultSortValue === 'desc') {
|
|
478
|
+
direction = 'desc';
|
|
479
|
+
} else {
|
|
480
|
+
direction = 'asc'; // fallback
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
return { field: fieldName, direction };
|
|
484
|
+
}
|
|
485
|
+
|
|
439
486
|
export function selectSortDataPath(collection: Collection, key: string) {
|
|
440
487
|
if (key === COMMIT_DATE) {
|
|
441
488
|
return 'updatedOn';
|
package/src/reducers/entries.ts
CHANGED
|
@@ -78,6 +78,14 @@ let slug: string;
|
|
|
78
78
|
|
|
79
79
|
const storageSortKey = 'decap-cms.entries.sort';
|
|
80
80
|
const viewStyleKey = 'decap-cms.entries.viewStyle';
|
|
81
|
+
|
|
82
|
+
function normalizeDoubleSlashes(path: string) {
|
|
83
|
+
if (!path) {
|
|
84
|
+
return path;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return path.replace(/([^:]\/)\/+/g, '$1');
|
|
88
|
+
}
|
|
81
89
|
type StorageSortObject = SortObject & { index: number };
|
|
82
90
|
type StorageSort = { [collection: string]: { [key: string]: StorageSortObject } };
|
|
83
91
|
|
|
@@ -532,8 +540,6 @@ export function selectIsFetching(state: Entries, collection: string) {
|
|
|
532
540
|
return state.getIn(['pages', collection, 'isFetching'], false);
|
|
533
541
|
}
|
|
534
542
|
|
|
535
|
-
const DRAFT_MEDIA_FILES = 'DRAFT_MEDIA_FILES';
|
|
536
|
-
|
|
537
543
|
function getFileField(collectionFiles: CollectionFiles, slug: string | undefined) {
|
|
538
544
|
const file = collectionFiles.find(f => f?.get('name') === slug);
|
|
539
545
|
return file;
|
|
@@ -752,7 +758,7 @@ export function selectMediaFolder(
|
|
|
752
758
|
const entryPath = entryMap?.get('path');
|
|
753
759
|
mediaFolder = entryPath
|
|
754
760
|
? join(dirname(entryPath), folder)
|
|
755
|
-
:
|
|
761
|
+
: (collection!.get('folder') as string);
|
|
756
762
|
}
|
|
757
763
|
}
|
|
758
764
|
|
|
@@ -787,12 +793,14 @@ export function selectMediaFilePublicPath(
|
|
|
787
793
|
}
|
|
788
794
|
|
|
789
795
|
const name = 'public_folder';
|
|
790
|
-
let publicFolder = config[name]
|
|
796
|
+
let publicFolder = normalizeDoubleSlashes(config[name]!);
|
|
791
797
|
|
|
792
798
|
const customFolder = hasCustomFolder(name, collection, entryMap?.get('slug'), field);
|
|
793
799
|
|
|
794
800
|
if (customFolder) {
|
|
795
|
-
publicFolder =
|
|
801
|
+
publicFolder = normalizeDoubleSlashes(
|
|
802
|
+
evaluateFolder(name, config, collection!, entryMap, field),
|
|
803
|
+
);
|
|
796
804
|
}
|
|
797
805
|
|
|
798
806
|
if (isAbsolutePath(publicFolder)) {
|
package/src/types/redux.ts
CHANGED
|
@@ -148,6 +148,8 @@ export interface CmsFieldList {
|
|
|
148
148
|
default?: unknown;
|
|
149
149
|
|
|
150
150
|
allow_add?: boolean;
|
|
151
|
+
allow_remove?: boolean;
|
|
152
|
+
allow_reorder?: boolean;
|
|
151
153
|
collapsed?: boolean;
|
|
152
154
|
summary?: string;
|
|
153
155
|
minimize_collapsed?: boolean;
|
|
@@ -307,6 +309,12 @@ export interface ViewGroup {
|
|
|
307
309
|
id: string;
|
|
308
310
|
}
|
|
309
311
|
|
|
312
|
+
export interface SortableField {
|
|
313
|
+
field: string;
|
|
314
|
+
label?: string;
|
|
315
|
+
default_sort?: boolean | 'asc' | 'desc';
|
|
316
|
+
}
|
|
317
|
+
|
|
310
318
|
export interface CmsCollection {
|
|
311
319
|
name: string;
|
|
312
320
|
label: string;
|
|
@@ -346,7 +354,7 @@ export interface CmsCollection {
|
|
|
346
354
|
path?: string;
|
|
347
355
|
media_folder?: string;
|
|
348
356
|
public_folder?: string;
|
|
349
|
-
sortable_fields?: string[];
|
|
357
|
+
sortable_fields?: (string | SortableField)[];
|
|
350
358
|
view_filters?: ViewFilter[];
|
|
351
359
|
view_groups?: ViewGroup[];
|
|
352
360
|
i18n?: boolean | CmsI18nConfig;
|
|
@@ -354,7 +362,7 @@ export interface CmsCollection {
|
|
|
354
362
|
/**
|
|
355
363
|
* @deprecated Use sortable_fields instead
|
|
356
364
|
*/
|
|
357
|
-
sortableFields?: string[];
|
|
365
|
+
sortableFields?: (string | SortableField)[];
|
|
358
366
|
}
|
|
359
367
|
|
|
360
368
|
export interface CmsBackend {
|
|
@@ -633,7 +641,7 @@ type CollectionObject = {
|
|
|
633
641
|
slug?: string;
|
|
634
642
|
label_singular?: string;
|
|
635
643
|
label: string;
|
|
636
|
-
sortable_fields: List<
|
|
644
|
+
sortable_fields: List<StaticallyTypedRecord<SortableField>>;
|
|
637
645
|
view_filters: List<StaticallyTypedRecord<ViewFilter>>;
|
|
638
646
|
view_groups: List<StaticallyTypedRecord<ViewGroup>>;
|
|
639
647
|
nested?: Nested;
|