feat: nested collections (#680)

This commit is contained in:
Daniel Lautzenheiser
2023-04-04 15:12:32 -04:00
committed by GitHub
parent 22a1b8d9c0
commit d0ecae310c
54 changed files with 2671 additions and 295 deletions

View File

@ -28,6 +28,7 @@ describe('entryDraft', () => {
},
value: 'newValue',
i18n: undefined,
isMeta: false,
},
});
@ -38,6 +39,28 @@ describe('entryDraft', () => {
});
});
it('should update meta path with value', () => {
const state = entryDraftReducer(startState, {
type: DRAFT_CHANGE_FIELD,
payload: {
path: 'path1.path2',
field: {
widget: 'string',
name: 'stringInput',
},
value: 'newValue',
i18n: undefined,
isMeta: true,
},
});
expect(state.entry?.meta).toEqual({
path1: {
path2: 'newValue',
},
});
});
it('should update path with value for singleton list', () => {
let state = entryDraftReducer(startState, {
type: DRAFT_CHANGE_FIELD,
@ -49,6 +72,7 @@ describe('entryDraft', () => {
},
value: ['newValue1', 'newValue2', 'newValue3'],
i18n: undefined,
isMeta: false,
},
});
@ -66,6 +90,7 @@ describe('entryDraft', () => {
},
value: 'newValue2Updated',
i18n: undefined,
isMeta: false,
},
});
@ -91,6 +116,7 @@ describe('entryDraft', () => {
defaultLocale: 'en',
currentLocale: 'en',
},
isMeta: false,
},
});
@ -138,6 +164,7 @@ describe('entryDraft', () => {
field,
value: ['newValue1', 'newValue2', 'newValue3'],
i18n,
isMeta: false,
},
});
@ -165,6 +192,7 @@ describe('entryDraft', () => {
field,
value: 'newValue2Updated',
i18n,
isMeta: false,
},
});

View File

@ -1,9 +1,9 @@
import { CONFIG_SUCCESS } from '../constants';
import type { ConfigAction } from '../actions/config';
import type { Collection, Collections } from '../interface';
import type { BaseField, Collection, Collections, UnknownField } from '../interface';
export type CollectionsState = Collections;
export type CollectionsState<EF extends BaseField = UnknownField> = Collections<EF>;
const defaultState: CollectionsState = {};

View File

@ -1,10 +1,10 @@
import { CONFIG_FAILURE, CONFIG_REQUEST, CONFIG_SUCCESS } from '../constants';
import type { ConfigAction } from '../actions/config';
import type { Config } from '../interface';
import type { BaseField, Config, UnknownField } from '../interface';
export interface ConfigState {
config?: Config;
export interface ConfigState<EF extends BaseField = UnknownField> {
config?: Config<EF>;
isFetching: boolean;
error?: string;
}

View File

@ -1,4 +1,3 @@
import get from 'lodash/get';
import isEqual from 'lodash/isEqual';
import { v4 as uuid } from 'uuid';
@ -154,8 +153,10 @@ function entryDraftReducer(
return state;
}
const { path, field, value, i18n } = action.payload;
const dataPath = (i18n && getDataPath(i18n.currentLocale, i18n.defaultLocale)) || ['data'];
const { path, field, value, i18n, isMeta } = action.payload;
const dataPath = isMeta
? ['meta']
: (i18n && getDataPath(i18n.currentLocale, i18n.defaultLocale)) || ['data'];
newState = {
...newState,
@ -166,11 +167,20 @@ function entryDraftReducer(
newState = duplicateI18nFields(newState, field, i18n.locales, i18n.defaultLocale, path);
}
const newData = get(newState.entry, dataPath) ?? {};
let hasChanged =
!isEqual(newState.entry?.meta, newState.original?.meta) ||
!isEqual(newState.entry?.data, newState.original?.data);
const i18nData = newState.entry?.i18n ?? {};
for (const locale in i18nData) {
hasChanged =
hasChanged ||
!isEqual(newState.entry?.i18n?.[locale]?.data, newState.original?.i18n?.[locale]?.data);
}
return {
...newState,
hasChanged: !newState.original || !isEqual(newData, get(newState.original, dataPath)),
hasChanged: !newState.original || hasChanged,
};
}

View File

@ -1,10 +1,13 @@
/* eslint-disable import/prefer-default-export */
import type { BaseField, UnknownField } from '@staticcms/core/interface';
import type { RootState } from '@staticcms/core/store';
export const selectCollections = (state: RootState) => {
export const selectCollections = <EF extends BaseField = UnknownField>(state: RootState<EF>) => {
return state.collections;
};
export const selectCollection = (collectionName: string | undefined) => (state: RootState) => {
return Object.values(state.collections).find(collection => collection.name === collectionName);
};
export const selectCollection =
<EF extends BaseField = UnknownField>(collectionName: string | undefined) =>
(state: RootState<EF>) => {
return Object.values(state.collections).find(collection => collection.name === collectionName);
};