decap-cms-core 3.10.0 → 3.10.1

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.
Files changed (27) hide show
  1. package/dist/decap-cms-core.js +8 -8
  2. package/dist/decap-cms-core.js.map +1 -1
  3. package/dist/esm/bootstrap.js +2 -2
  4. package/dist/esm/components/App/StatusBar.js +1 -1
  5. package/dist/esm/components/Collection/CollectionControls.js +3 -2
  6. package/dist/esm/components/Collection/ViewStyleControl.js +6 -3
  7. package/dist/esm/components/Editor/EditorControlPane/EditorControl.js +8 -5
  8. package/dist/esm/components/Editor/EditorNotesPane/AddNoteForm.js +5 -5
  9. package/dist/esm/components/Editor/EditorNotesPane/EditorNotesPane.js +75 -15
  10. package/dist/esm/components/Editor/EditorNotesPane/NoteItem.js +21 -24
  11. package/dist/esm/components/Editor/EditorNotesPane/NotesList.js +4 -4
  12. package/dist/esm/components/MediaLibrary/MediaLibraryHeader.js +5 -3
  13. package/dist/esm/components/MediaLibrary/MediaLibraryTop.js +5 -4
  14. package/dist/esm/components/UI/ErrorBoundary.js +2 -2
  15. package/dist/esm/components/UI/SettingsDropdown.js +9 -7
  16. package/package.json +2 -2
  17. package/src/components/Collection/CollectionControls.js +1 -1
  18. package/src/components/Collection/ViewStyleControl.js +3 -1
  19. package/src/components/Editor/EditorControlPane/EditorControl.js +1 -0
  20. package/src/components/MediaLibrary/MediaLibraryHeader.js +2 -2
  21. package/src/components/MediaLibrary/MediaLibraryTop.js +1 -0
  22. package/src/components/UI/SettingsDropdown.js +1 -1
  23. package/dist/esm/components/Collection/Entries/Pagination.js +0 -132
  24. package/dist/esm/lib/entryCache.js +0 -145
  25. package/dist/esm/lib/entryHelpers.js +0 -102
  26. package/dist/esm/lib/immutableHelpers.js +0 -21
  27. package/dist/esm/lib/pagination.js +0 -68
@@ -1,145 +0,0 @@
1
- /**
2
- * Entry Cache Module
3
- *
4
- * Provides localStorage-based caching for collection entries to improve performance
5
- * when navigating between pages, sorting, or filtering.
6
- *
7
- * Cache Strategy:
8
- * - Store fetched entries with timestamps
9
- * - Invalidate on entry changes (persist, delete)
10
- * - Time-based expiration (default: 5 minutes)
11
- * - Collection-specific cache keys
12
- */
13
-
14
- import localForage from 'decap-cms-lib-util/src/localForage';
15
- const CACHE_PREFIX = 'decap_entry_cache_';
16
- const CACHE_EXPIRATION_MS = 5 * 60 * 1000; // 5 minutes
17
-
18
- /**
19
- * Generate cache key for a collection
20
- */
21
- function getCacheKey(collectionName) {
22
- return `${CACHE_PREFIX}${collectionName}`;
23
- }
24
-
25
- /**
26
- * Check if cached data is still valid
27
- */
28
- function isCacheValid(cacheEntry) {
29
- if (!cacheEntry) {
30
- return false;
31
- }
32
- const now = Date.now();
33
- const age = now - cacheEntry.timestamp;
34
- return age < CACHE_EXPIRATION_MS;
35
- }
36
-
37
- /**
38
- * Get cached entries for a collection
39
- *
40
- * @param collectionName - Name of the collection
41
- * @returns Cached entries or null if cache miss/expired
42
- */
43
- export async function getCachedEntries(collectionName) {
44
- try {
45
- const cacheKey = getCacheKey(collectionName);
46
- const cached = await localForage.getItem(cacheKey);
47
- if (cached && isCacheValid(cached)) {
48
- console.log(`[EntryCache] Cache HIT for collection: ${collectionName}`);
49
- return cached.entries;
50
- }
51
- console.log(`[EntryCache] Cache MISS for collection: ${collectionName}`);
52
- return null;
53
- } catch (error) {
54
- console.warn('[EntryCache] Error reading cache:', error);
55
- return null;
56
- }
57
- }
58
-
59
- /**
60
- * Store entries in cache
61
- *
62
- * @param collectionName - Name of the collection
63
- * @param entries - Entries to cache
64
- */
65
- export async function setCachedEntries(collectionName, entries) {
66
- try {
67
- const cacheKey = getCacheKey(collectionName);
68
- const cacheEntry = {
69
- entries,
70
- timestamp: Date.now(),
71
- collectionName,
72
- version: 1
73
- };
74
- await localForage.setItem(cacheKey, cacheEntry);
75
- console.log(`[EntryCache] Cached ${entries.length} entries for collection: ${collectionName}`);
76
- } catch (error) {
77
- console.warn('[EntryCache] Error writing cache:', error);
78
- }
79
- }
80
-
81
- /**
82
- * Invalidate cache for a specific collection
83
- *
84
- * Should be called when:
85
- * - Entry is created
86
- * - Entry is updated
87
- * - Entry is deleted
88
- *
89
- * @param collectionName - Name of the collection to invalidate
90
- */
91
- export async function invalidateCollectionCache(collectionName) {
92
- try {
93
- const cacheKey = getCacheKey(collectionName);
94
- await localForage.removeItem(cacheKey);
95
- console.log(`[EntryCache] Invalidated cache for collection: ${collectionName}`);
96
- } catch (error) {
97
- console.warn('[EntryCache] Error invalidating cache:', error);
98
- }
99
- }
100
-
101
- /**
102
- * Clear all entry caches
103
- *
104
- * Useful for logout or manual cache clearing
105
- */
106
- export async function clearAllEntryCaches() {
107
- try {
108
- const keys = await localForage.keys();
109
- const cacheKeys = keys.filter(key => key.startsWith(CACHE_PREFIX));
110
- await Promise.all(cacheKeys.map(key => localForage.removeItem(key)));
111
- console.log(`[EntryCache] Cleared ${cacheKeys.length} collection caches`);
112
- } catch (error) {
113
- console.warn('[EntryCache] Error clearing all caches:', error);
114
- }
115
- }
116
-
117
- /**
118
- * Get cache statistics for debugging
119
- */
120
- export async function getCacheStats() {
121
- try {
122
- const keys = await localForage.keys();
123
- const cacheKeys = keys.filter(key => key.startsWith(CACHE_PREFIX));
124
- const cacheEntries = await Promise.all(cacheKeys.map(async key => {
125
- const entry = await localForage.getItem(key);
126
- return entry;
127
- }));
128
- const validCaches = cacheEntries.filter(entry => entry !== null);
129
- const timestamps = validCaches.map(c => c.timestamp);
130
- return {
131
- collections: validCaches.map(c => c.collectionName),
132
- totalEntries: validCaches.reduce((sum, c) => sum + c.entries.length, 0),
133
- oldestCache: timestamps.length > 0 ? Math.min(...timestamps) : null,
134
- newestCache: timestamps.length > 0 ? Math.max(...timestamps) : null
135
- };
136
- } catch (error) {
137
- console.warn('[EntryCache] Error getting cache stats:', error);
138
- return {
139
- collections: [],
140
- totalEntries: 0,
141
- oldestCache: null,
142
- newestCache: null
143
- };
144
- }
145
- }
@@ -1,102 +0,0 @@
1
- /**
2
- * Utility functions for working with entries, filters, sorts, and groups
3
- */
4
-
5
- /**
6
- * Check if any filters are active in the Redux state
7
- */
8
- export function hasActiveFilters(activeFilters) {
9
- if (!activeFilters) return false;
10
-
11
- // Check if it's an Immutable collection with a 'some' method
12
- if (typeof activeFilters === 'object' &&
13
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
- typeof activeFilters.some === 'function') {
15
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
- return activeFilters.some(f => f.get('active') === true);
17
- }
18
- return false;
19
- }
20
-
21
- /**
22
- * Check if any groups are active in the Redux state
23
- */
24
- export function hasActiveGroups(activeGroups) {
25
- if (!activeGroups) return false;
26
-
27
- // Check if it's an Immutable collection with a 'some' method
28
- if (typeof activeGroups === 'object' &&
29
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
- typeof activeGroups.some === 'function') {
31
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
- return activeGroups.some(g => g.get('active') === true);
33
- }
34
- return false;
35
- }
36
-
37
- /**
38
- * Check if any sorts are active in the Redux state
39
- */
40
- export function hasActiveSorts(activeSorts) {
41
- if (!activeSorts) return false;
42
-
43
- // Check if it's an Immutable collection with a 'size' property
44
- if (typeof activeSorts === 'object' &&
45
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
- typeof activeSorts.size === 'number') {
47
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
- return activeSorts.size > 0;
49
- }
50
- return false;
51
- }
52
-
53
- /**
54
- * Get value from a nested field path (e.g., "data.title" or "data.nested.field")
55
- */
56
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
- export function getFieldValue(obj, fieldPath) {
58
- const pathParts = fieldPath.split('.');
59
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
- let value = obj;
61
- for (const part of pathParts) {
62
- value = value?.[part];
63
- }
64
- return value;
65
- }
66
-
67
- /**
68
- * Extract active filters from Immutable collection into plain array
69
- */
70
-
71
- export function extractActiveFilters(activeFilters) {
72
- const filters = [];
73
- if (!activeFilters) return filters;
74
-
75
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
76
- if (typeof activeFilters.forEach === 'function') {
77
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
- activeFilters.forEach(f => {
79
- if (f.get('active') === true) {
80
- filters.push({
81
- pattern: f.get('pattern'),
82
- field: f.get('field')
83
- });
84
- }
85
- });
86
- }
87
- return filters;
88
- }
89
-
90
- /**
91
- * Apply filters to an entry
92
- */
93
- export function matchesFilters(entry, filters) {
94
- return filters.every(({
95
- pattern,
96
- field
97
- }) => {
98
- const data = ('data' in entry ? entry.data : entry) || {};
99
- const value = getFieldValue(data, field);
100
- return value !== undefined && new RegExp(String(pattern)).test(String(value));
101
- });
102
- }
@@ -1,21 +0,0 @@
1
- import { Map } from 'immutable';
2
- /**
3
- * Type guard to check if an object is an Immutable.js Map
4
- */
5
- export function isImmutableMap(obj) {
6
- return Map.isMap(obj);
7
- }
8
-
9
- /**
10
- * Helper to safely get a value from either an Immutable Map or plain object
11
- */
12
- export function getValue(obj, key) {
13
- if (!obj) return undefined;
14
- if (isImmutableMap(obj)) {
15
- return obj.get(key);
16
- }
17
- if (typeof obj === 'object' && obj !== null) {
18
- return obj[key];
19
- }
20
- return undefined;
21
- }
@@ -1,68 +0,0 @@
1
- /**
2
- * Pagination Utilities
3
- *
4
- * This module provides helpers for determining if pagination is enabled for a collection,
5
- * and for retrieving the effective pagination configuration (page size, enabled flag).
6
- *
7
- * Principles:
8
- * - Pagination can be enabled/disabled per collection or globally via config.
9
- * - If sorting, filtering, or grouping is active, pagination is handled client-side (all entries loaded).
10
- * - If none are active, server-side pagination is used (only a page of entries loaded at a time).
11
- * - The effective page size is determined by collection config, then global config, then a default.
12
- *
13
- * Usage:
14
- * - Use isPaginationEnabled(collection, config) to check if pagination should be active.
15
- * - Use getPaginationConfig(collection, config) to get the effective page size and enabled flag.
16
- */
17
- import { getValue, isImmutableMap } from './immutableHelpers';
18
- const DEFAULT_PER_PAGE = 100;
19
- export function isPaginationEnabled(collection, globalConfig) {
20
- const pagination = isImmutableMap(collection) ? collection.get('pagination') : collection.pagination;
21
- if (typeof pagination !== 'undefined') {
22
- if (typeof pagination === 'boolean') return pagination;
23
- if (pagination && typeof pagination === 'object') {
24
- const enabled = getValue(pagination, 'enabled');
25
- return enabled !== false;
26
- }
27
- return false;
28
- }
29
- if (globalConfig?.pagination) {
30
- if (typeof globalConfig.pagination === 'boolean') return globalConfig.pagination;
31
- if (typeof globalConfig.pagination === 'object') {
32
- const enabled = getValue(globalConfig.pagination, 'enabled');
33
- return enabled !== false;
34
- }
35
- }
36
- return false;
37
- }
38
- export function getPaginationConfig(collection, globalConfig) {
39
- const defaults = {
40
- enabled: false,
41
- per_page: DEFAULT_PER_PAGE
42
- };
43
- if (globalConfig?.pagination) {
44
- if (typeof globalConfig.pagination === 'boolean') {
45
- defaults.enabled = globalConfig.pagination;
46
- } else if (typeof globalConfig.pagination === 'object') {
47
- const enabled = getValue(globalConfig.pagination, 'enabled');
48
- defaults.enabled = enabled !== false;
49
- const perPage = getValue(globalConfig.pagination, 'per_page');
50
- defaults.per_page = typeof perPage === 'number' ? perPage : defaults.per_page;
51
- }
52
- }
53
- const pagination = isImmutableMap(collection) ? collection.get('pagination') : collection.pagination;
54
- if (pagination === true) {
55
- return {
56
- enabled: true,
57
- per_page: defaults.per_page
58
- };
59
- } else if (typeof pagination === 'object' && pagination !== null) {
60
- const perPage = getValue(pagination, 'per_page');
61
- const enabled = getValue(pagination, 'enabled');
62
- return {
63
- enabled: enabled !== false,
64
- per_page: typeof perPage === 'number' ? perPage : defaults.per_page
65
- };
66
- }
67
- return defaults;
68
- }