Merge pull request #15818 from strapi/feat/relations-diffing-fe

This commit is contained in:
Josh 2023-02-15 10:55:45 +00:00 committed by GitHub
commit 14d5597a8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 619 additions and 71 deletions

View File

@ -75,7 +75,7 @@ module.exports = {
'<rootDir>/fileTransformer.js',
},
transformIgnorePatterns: [
'node_modules/(?!(react-dnd|dnd-core|react-dnd-html5-backend|@strapi/design-system|@strapi/icons)/)',
'node_modules/(?!(react-dnd|dnd-core|react-dnd-html5-backend|@strapi/design-system|@strapi/icons|fractional-indexing)/)',
],
testMatch: ['/**/tests/**/?(*.)+(spec|test).[jt]s?(x)'],
testEnvironmentOptions: {

View File

@ -8,6 +8,7 @@ import uniqBy from 'lodash/uniqBy';
import merge from 'lodash/merge';
import castArray from 'lodash/castArray';
import isNil from 'lodash/isNil';
import { generateNKeysBetween } from 'fractional-indexing';
import {
findLeafByPathAndReplace,
@ -155,17 +156,33 @@ const reducer = (state, action) =>
const initialDataRelations = get(state, initialDataPath);
const modifiedDataRelations = get(state, modifiedDataPath);
/**
* Check if the values we're loading are already in initial
* data if they are then we don't need to load them at all
*/
const valuesToLoad = value.filter((relation) => {
return !initialDataRelations.some((initialDataRelation) => {
return initialDataRelation.id === relation.id;
});
});
set(draftState, initialDataPath, uniqBy([...valuesToLoad, ...initialDataRelations], 'id'));
const keys = generateNKeysBetween(
null,
modifiedDataRelations[0]?.__temp_key__,
valuesToLoad.length
);
/**
* Check if the values we're loading are already in initial
* data if they are then we don't need to load them at all
*/
const valuesWithKeys = valuesToLoad.map((relation, index) => ({
...relation,
__temp_key__: keys[index],
}));
set(
draftState,
initialDataPath,
uniqBy([...valuesWithKeys, ...initialDataRelations], 'id')
);
/**
* We need to set the value also on modifiedData, because initialData
@ -175,7 +192,7 @@ const reducer = (state, action) =>
set(
draftState,
modifiedDataPath,
uniqBy([...valuesToLoad, ...modifiedDataRelations], 'id')
uniqBy([...valuesWithKeys, ...modifiedDataRelations], 'id')
);
break;
@ -192,7 +209,9 @@ const reducer = (state, action) =>
set(draftState, path, [value]);
} else {
const modifiedDataRelations = get(state, path);
const newRelations = [...modifiedDataRelations, value];
const [key] = generateNKeysBetween(modifiedDataRelations.at(-1)?.__temp_key__, null, 1);
const newRelations = [...modifiedDataRelations, { ...value, __temp_key__: key }];
set(draftState, path, newRelations);
}
@ -219,8 +238,19 @@ const reducer = (state, action) =>
const newRelations = [...modifiedDataRelations];
newRelations.splice(oldIndex, 1);
newRelations.splice(newIndex, 0, currentItem);
if (action.type === 'REORDER_RELATION') {
const [newKey] = generateNKeysBetween(
modifiedDataRelations[newIndex - 1]?.__temp_key__,
modifiedDataRelations[newIndex]?.__temp_key__,
1
);
newRelations.splice(oldIndex, 1);
newRelations.splice(newIndex, 0, { ...currentItem, __temp_key__: newKey });
} else {
newRelations.splice(oldIndex, 1);
newRelations.splice(newIndex, 0, currentItem);
}
set(draftState, path, newRelations);

View File

@ -869,7 +869,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer',
componentsDataStructure: {},
initialData: {},
modifiedData: {
relation: [{ id: 1 }],
relation: [{ id: 1, __temp_key__: 'a0' }],
},
};
@ -882,6 +882,74 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer',
expect(reducer(state, action)).toEqual(expected);
});
it('should set a temp key every time a relation is connected', () => {
const state = {
...initialState,
initialData: {
relation: [
{ id: 1, __temp_key__: 'a0' },
{ id: 2, __temp_key__: 'a1' },
],
},
modifiedData: {
relation: [
{ id: 1, __temp_key__: 'a0' },
{ id: 2, __temp_key__: 'a1' },
],
},
};
const nextState = reducer(state, {
type: 'CONNECT_RELATION',
keys: ['relation'],
value: { id: 3 },
});
expect(nextState).toStrictEqual({
...initialState,
componentsDataStructure: {},
initialData: {
relation: [
{ id: 1, __temp_key__: 'a0' },
{ id: 2, __temp_key__: 'a1' },
],
},
modifiedData: {
relation: [
{ id: 1, __temp_key__: 'a0' },
{ id: 2, __temp_key__: 'a1' },
{ id: 3, __temp_key__: 'a2' },
],
},
});
expect(
reducer(nextState, {
type: 'CONNECT_RELATION',
keys: ['relation'],
value: { id: 4 },
})
).toStrictEqual({
...initialState,
componentsDataStructure: {},
initialData: {
relation: [
{ id: 1, __temp_key__: 'a0' },
{ id: 2, __temp_key__: 'a1' },
],
},
modifiedData: {
relation: [
{ id: 1, __temp_key__: 'a0' },
{ id: 2, __temp_key__: 'a1' },
{ id: 3, __temp_key__: 'a2' },
{ id: 4, __temp_key__: 'a3' },
],
},
});
});
it('should overwrite existing data, when toOneRelation is set to true', () => {
const state = {
...initialState,
@ -953,10 +1021,10 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer',
expect(nextState).toStrictEqual({
...initialState,
initialData: {
relation: [{ id: 1 }],
relation: [{ id: 1, __temp_key__: 'a0' }],
},
modifiedData: {
relation: [{ id: 1 }],
relation: [{ id: 1, __temp_key__: 'a0' }],
},
});
@ -970,10 +1038,16 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer',
).toStrictEqual({
...initialState,
initialData: {
relation: [{ id: 2 }, { id: 1 }],
relation: [
{ id: 2, __temp_key__: 'Zz' },
{ id: 1, __temp_key__: 'a0' },
],
},
modifiedData: {
relation: [{ id: 2 }, { id: 1 }],
relation: [
{ id: 2, __temp_key__: 'Zz' },
{ id: 1, __temp_key__: 'a0' },
],
},
});
});
@ -1002,10 +1076,10 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer',
expect(nextState).toStrictEqual({
...initialState,
initialData: {
relation: [{ id: 1 }],
relation: [{ id: 1, __temp_key__: 'a0' }],
},
modifiedData: {
relation: [{ id: 1 }],
relation: [{ id: 1, __temp_key__: 'a0' }],
},
});
@ -1019,10 +1093,103 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer',
).toStrictEqual({
...initialState,
initialData: {
relation: [{ id: 1 }],
relation: [{ id: 1, __temp_key__: 'a0' }],
},
modifiedData: {
relation: [{ id: 1 }],
relation: [{ id: 1, __temp_key__: 'a0' }],
},
});
});
it('should add a temp key for all the relations added', () => {
const state = {
...initialState,
initialData: {
relation: [],
},
modifiedData: {
relation: [],
},
};
const initialDataPath = ['initialData', 'relation'];
const modifiedDataPath = ['modifiedData', 'relation'];
let nextState = reducer(state, {
type: 'LOAD_RELATION',
initialDataPath,
modifiedDataPath,
value: [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }],
});
expect(nextState).toStrictEqual({
...initialState,
initialData: {
relation: [
{ id: 1, __temp_key__: 'a0' },
{ id: 2, __temp_key__: 'a1' },
{ id: 3, __temp_key__: 'a2' },
{ id: 4, __temp_key__: 'a3' },
{ id: 5, __temp_key__: 'a4' },
],
},
modifiedData: {
relation: [
{ id: 1, __temp_key__: 'a0' },
{ id: 2, __temp_key__: 'a1' },
{ id: 3, __temp_key__: 'a2' },
{ id: 4, __temp_key__: 'a3' },
{ id: 5, __temp_key__: 'a4' },
],
},
});
});
it('should add a temp key working backwards on every new load because of how relations are shown in the UI', () => {
const state = {
...initialState,
initialData: {
relation: [],
},
modifiedData: {
relation: [],
},
};
const initialDataPath = ['initialData', 'relation'];
const modifiedDataPath = ['modifiedData', 'relation'];
let nextState = reducer(state, {
type: 'LOAD_RELATION',
initialDataPath,
modifiedDataPath,
value: [{ id: 1 }, { id: 2 }],
});
expect(
reducer(nextState, {
type: 'LOAD_RELATION',
initialDataPath,
modifiedDataPath,
value: [{ id: 3 }, { id: 4 }],
})
).toStrictEqual({
...initialState,
initialData: {
relation: [
{ id: 3, __temp_key__: 'Zy' },
{ id: 4, __temp_key__: 'Zz' },
{ id: 1, __temp_key__: 'a0' },
{ id: 2, __temp_key__: 'a1' },
],
},
modifiedData: {
relation: [
{ id: 3, __temp_key__: 'Zy' },
{ id: 4, __temp_key__: 'Zz' },
{ id: 1, __temp_key__: 'a0' },
{ id: 2, __temp_key__: 'a1' },
],
},
});
});
@ -2397,10 +2564,10 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer',
field1: {
field2: {
relation: [
{ name: 'first' },
{ name: 'second' },
{ name: 'third' },
{ name: 'fourth' },
{ name: 'first', __temp_key__: 'a0' },
{ name: 'second', __temp_key__: 'a1' },
{ name: 'third', __temp_key__: 'a2' },
{ name: 'fourth', __temp_key__: 'a3' },
],
},
},
@ -2421,10 +2588,10 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer',
field1: {
field2: {
relation: [
{ name: 'first' },
{ name: 'fourth' },
{ name: 'second' },
{ name: 'third' },
{ name: 'first', __temp_key__: 'a0' },
{ name: 'fourth', __temp_key__: 'a0V' },
{ name: 'second', __temp_key__: 'a1' },
{ name: 'third', __temp_key__: 'a2' },
],
},
},
@ -2433,6 +2600,89 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer',
expect(reducer(state, action)).toEqual(expected);
});
it('should move many components many times and have the correct temp keys', () => {
const state = {
...initialState,
modifiedData: {
relation: [
{ name: 'first', __temp_key__: 'a0' },
{ name: 'second', __temp_key__: 'a1' },
{ name: 'third', __temp_key__: 'a2' },
{ name: 'fourth', __temp_key__: 'a3' },
],
},
};
const generateAction = (newIndex, oldIndex) => ({
type: 'REORDER_RELATION',
newIndex,
oldIndex,
keys: ['relation'],
});
const generateExpected = (relation = []) => ({
...initialState,
modifiedData: {
relation,
},
});
const nextState1 = reducer(state, generateAction(1, 3));
expect(nextState1).toEqual(
generateExpected([
{ name: 'first', __temp_key__: 'a0' },
{ name: 'fourth', __temp_key__: 'a0V' },
{ name: 'second', __temp_key__: 'a1' },
{ name: 'third', __temp_key__: 'a2' },
])
);
const nextState2 = reducer(nextState1, generateAction(1, 2));
expect(nextState2).toEqual(
generateExpected([
{ name: 'first', __temp_key__: 'a0' },
{ name: 'second', __temp_key__: 'a0G' },
{ name: 'fourth', __temp_key__: 'a0V' },
{ name: 'third', __temp_key__: 'a2' },
])
);
const nextState3 = reducer(nextState2, generateAction(0, 3));
expect(nextState3).toEqual(
generateExpected([
{ name: 'third', __temp_key__: 'Zz' },
{ name: 'first', __temp_key__: 'a0' },
{ name: 'second', __temp_key__: 'a0G' },
{ name: 'fourth', __temp_key__: 'a0V' },
])
);
const nextState4 = reducer(nextState3, generateAction(3, 1));
expect(nextState4).toEqual(
generateExpected([
{ name: 'third', __temp_key__: 'Zz' },
{ name: 'second', __temp_key__: 'a0G' },
{ name: 'fourth', __temp_key__: 'a0V' },
{ name: 'first', __temp_key__: 'a0O' },
])
);
const nextState5 = reducer(nextState4, generateAction(1, 2));
expect(nextState5).toEqual(
generateExpected([
{ name: 'third', __temp_key__: 'Zz' },
{ name: 'fourth', __temp_key__: 'a0' },
{ name: 'second', __temp_key__: 'a0G' },
{ name: 'first', __temp_key__: 'a0O' },
])
);
});
});
describe('SET_DEFAULT_DATA_STRUCTURES', () => {

View File

@ -95,28 +95,22 @@ const cleanData = ({ browserState, serverState }, currentSchema, componentsSchem
*/
let actualOldValue = get(rootServerState, trueInitialDataPath, []);
const valuesWithPositions = value.map((relation, index, allRelations) => {
const nextRelation = allRelations[index + 1];
if (nextRelation) {
return { ...relation, position: { before: nextRelation.id } };
}
return { ...relation, position: { end: true } };
});
/**
* Instead of the full relation object, we only want to send its ID
* connectedRelations are the items that are in the browserState
* array but not in the serverState
*/
const connectedRelations = valuesWithPositions.reduce((acc, relation, currentIndex) => {
const indexOfRelationOnServer = actualOldValue.findIndex(
const connectedRelations = value.reduce((acc, relation, currentIndex, array) => {
const relationOnServer = actualOldValue.find(
(oldRelation) => oldRelation.id === relation.id
);
if (indexOfRelationOnServer === -1 || indexOfRelationOnServer !== currentIndex) {
return [...acc, { id: relation.id, position: relation.position }];
const relationInFront = array[currentIndex + 1];
if (!relationOnServer || relationOnServer.__temp_key__ !== relation.__temp_key__) {
const position = relationInFront ? { before: relationInFront.id } : { end: true };
return [...acc, { id: relation.id, position }];
}
return acc;
@ -127,7 +121,7 @@ const cleanData = ({ browserState, serverState }, currentSchema, componentsSchem
* are no longer in the browserState
*/
const disconnectedRelations = actualOldValue.reduce((acc, relation) => {
if (!valuesWithPositions.find((newRelation) => newRelation.id === relation.id)) {
if (!value.find((newRelation) => newRelation.id === relation.id)) {
return [...acc, { id: relation.id }];
}

View File

@ -407,10 +407,10 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
const result = cleanData(
{
browserState: {
relation: [{ id: 1, something: true }],
relation: [{ id: 1, __temp_key__: 'a1', something: true }],
},
serverState: {
relation: [{ id: 2, something: true }],
relation: [{ id: 2, __temp_key__: 'a0', something: true }],
},
},
schema,
@ -429,7 +429,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
const result = cleanData(
{
browserState: {
relation: [{ id: 1, something: true }],
relation: [{ id: 1, __temp_key__: 'a0', something: true }],
},
serverState: {
relation: [],
@ -454,7 +454,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
relation: [],
},
serverState: {
relation: [{ id: 1, something: true }],
relation: [{ id: 1, __temp_key__: 'a0', something: true }],
},
},
schema,
@ -477,13 +477,13 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
{
id: 1,
relation_component: {
relation: [{ id: 1 }],
relation: [{ id: 1, __temp_key__: 'a0' }],
},
},
{
id: 2,
relation_component: {
relation: [{ id: 2 }],
relation: [{ id: 2, __temp_key__: 'a0' }],
},
},
],
@ -541,7 +541,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
{
id: 2,
relation_component: {
relation: [{ id: 2 }],
relation: [{ id: 2, __temp_key__: 'a0' }],
},
},
],
@ -551,13 +551,13 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
{
id: 1,
relation_component: {
relation: [{ id: 1 }],
relation: [{ id: 1, __temp_key__: 'a0' }],
},
},
{
id: 2,
relation_component: {
relation: [{ id: 2 }],
relation: [{ id: 2, __temp_key__: 'a0' }],
},
},
],
@ -599,13 +599,13 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
{
__component: 'basic.relation',
id: 1,
relation: [{ id: 1 }],
relation: [{ id: 1, __temp_key__: 'a0' }],
},
{
__component: 'basic.nested-relation',
id: 2,
relation_component: {
relation: [{ id: 2 }],
relation: [{ id: 2, __temp_key__: 'a0' }],
},
},
{
@ -615,7 +615,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
{
__component: 'basic.relation',
id: 1,
relation: [{ id: 3 }],
relation: [{ id: 3, __temp_key__: 'a0' }],
},
],
},
@ -715,7 +715,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
{
__component: 'basic.relation',
id: 1,
relation: [{ id: 3 }],
relation: [{ id: 3, __temp_key__: 'a0' }],
},
{
__component: 'basic.relation',
@ -731,13 +731,13 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
{
__component: 'basic.relation',
id: 1,
relation: [{ id: 1 }],
relation: [{ id: 1, __temp_key__: 'a0' }],
},
{
__component: 'basic.nested-relation',
id: 2,
relation_component: {
relation: [{ id: 2 }],
relation: [{ id: 2, __temp_key__: 'a0' }],
},
},
{
@ -747,12 +747,12 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
{
__component: 'basic.relation',
id: 1,
relation: [{ id: 3 }],
relation: [{ id: 3, __temp_key__: 'a0' }],
},
{
__component: 'basic.relation',
id: 2,
relation: [{ id: 4 }],
relation: [{ id: 4, __temp_key__: 'a0' }],
},
],
},
@ -813,10 +813,16 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
const result = cleanData(
{
browserState: {
relation: [{ id: 1 }, { id: 2 }],
relation: [
{ id: 1, __temp_key__: 'Zz' },
{ id: 2, __temp_key__: 'a0' },
],
},
serverState: {
relation: [{ id: 2 }, { id: 1 }],
relation: [
{ id: 2, __temp_key__: 'a0' },
{ id: 1, __temp_key__: 'a1' },
],
},
},
schema,
@ -825,10 +831,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
expect(result).toStrictEqual({
relation: {
connect: [
{ id: 2, position: { end: true } },
{ id: 1, position: { before: 2 } },
],
connect: [{ id: 1, position: { before: 2 } }],
disconnect: [],
},
});
@ -838,10 +841,17 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
const result = cleanData(
{
browserState: {
relation: [{ id: 3 }, { id: 1 }, { id: 2 }],
relation: [
{ id: 3, __temp_key__: 'Zz' },
{ id: 1, __temp_key__: 'a0' },
{ id: 2, __temp_key__: 'a1' },
],
},
serverState: {
relation: [{ id: 1 }, { id: 2 }],
relation: [
{ id: 1, __temp_key__: 'a0' },
{ id: 2, __temp_key__: 'a1' },
],
},
},
schema,
@ -851,8 +861,6 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
expect(result).toStrictEqual({
relation: {
connect: [
{ id: 2, position: { end: true } },
{ id: 1, position: { before: 2 } },
{
id: 3,
position: { before: 1 },
@ -867,10 +875,18 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
const result = cleanData(
{
browserState: {
relation: [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }],
relation: [
{ id: 1, __temp_key__: 'a0' },
{ id: 2, __temp_key__: 'a1' },
{ id: 3, __temp_key__: 'a2' },
{ id: 4, __temp_key__: 'a3' },
],
},
serverState: {
relation: [{ id: 1 }, { id: 2 }],
relation: [
{ id: 1, __temp_key__: 'a0' },
{ id: 2, __temp_key__: 'a1' },
],
},
},
schema,
@ -893,5 +909,255 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData'
},
});
});
test('given a complicated list of reorderd relations it should only contain the items that moved', () => {
const result = cleanData(
{
browserState: {
relation: [
{
id: 3,
__temp_key__: 'Zw',
},
{
id: 2,
__temp_key__: 'Zx',
},
{
id: 4,
__temp_key__: 'Zwl',
},
{
id: 1,
__temp_key__: 'ZwV',
},
{
id: 5,
__temp_key__: 'Zy',
},
{
id: 7,
__temp_key__: 'Zz',
},
{
id: 10,
__temp_key__: 'ZzV',
},
{
id: 6,
__temp_key__: 'a0',
},
{
id: 9,
__temp_key__: 'a0G',
},
{
id: 8,
__temp_key__: 'a0V',
},
],
},
serverState: {
relation: [
{
id: 1,
__temp_key__: 'Zv',
},
{
id: 3,
__temp_key__: 'Zw',
},
{
id: 2,
__temp_key__: 'Zx',
},
{
id: 5,
__temp_key__: 'Zy',
},
{
id: 4,
__temp_key__: 'Zz',
},
{
id: 6,
__temp_key__: 'a0',
},
{
id: 7,
__temp_key__: 'a1',
},
{
id: 8,
__temp_key__: 'a2',
},
{
id: 9,
__temp_key__: 'a3',
},
{
id: 10,
__temp_key__: 'a4',
},
],
},
},
schema,
componentsSchema
);
expect(result).toStrictEqual({
relation: {
connect: [
{
id: 8,
position: {
end: true,
},
},
{
id: 9,
position: {
before: 8,
},
},
{
id: 10,
position: {
before: 6,
},
},
{
id: 7,
position: {
before: 10,
},
},
{
id: 1,
position: {
before: 5,
},
},
{
id: 4,
position: {
before: 1,
},
},
],
disconnect: [],
},
});
});
test('given a long list of relations and i move the first to the last, only that item should be in the payload', () => {
const result = cleanData(
{
browserState: {
relation: [
{
id: 10,
__temp_key__: 'Zu',
},
{
id: 1,
__temp_key__: 'Zv',
},
{
id: 3,
__temp_key__: 'Zw',
},
{
id: 2,
__temp_key__: 'Zx',
},
{
id: 5,
__temp_key__: 'Zy',
},
{
id: 4,
__temp_key__: 'Zz',
},
{
id: 6,
__temp_key__: 'a0',
},
{
id: 7,
__temp_key__: 'a1',
},
{
id: 8,
__temp_key__: 'a2',
},
{
id: 9,
__temp_key__: 'a3',
},
],
},
serverState: {
relation: [
{
id: 1,
__temp_key__: 'Zv',
},
{
id: 3,
__temp_key__: 'Zw',
},
{
id: 2,
__temp_key__: 'Zx',
},
{
id: 5,
__temp_key__: 'Zy',
},
{
id: 4,
__temp_key__: 'Zz',
},
{
id: 6,
__temp_key__: 'a0',
},
{
id: 7,
__temp_key__: 'a1',
},
{
id: 8,
__temp_key__: 'a2',
},
{
id: 9,
__temp_key__: 'a3',
},
{
id: 10,
__temp_key__: 'a4',
},
],
},
},
schema,
componentsSchema
);
expect(result).toStrictEqual({
relation: {
connect: [
{
id: 10,
position: { before: 1 },
},
],
disconnect: [],
},
});
});
});
});

View File

@ -73,6 +73,7 @@
"find-root": "1.1.0",
"fork-ts-checker-webpack-plugin": "7.2.1",
"formik": "^2.2.6",
"fractional-indexing": "3.2.0",
"fs-extra": "10.0.0",
"highlight.js": "^10.4.1",
"history": "^4.9.0",

View File

@ -12013,6 +12013,11 @@ forwarded@0.2.0:
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
fractional-indexing@3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/fractional-indexing/-/fractional-indexing-3.2.0.tgz#1193e63d54ff4e0cbe0c79a9ed6cfbab25d91628"
integrity sha512-PcOxmqwYCW7O2ovKRU8OoQQj2yqTfEB/yeTYk4gPid6dN5ODRfU1hXd9tTVZzax/0NkO7AxpHykvZnT1aYp/BQ==
fragment-cache@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
@ -17862,6 +17867,8 @@ path-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/path-case/-/path-case-2.1.1.tgz#94b8037c372d3fe2906e465bb45e25d226e8eea5"
integrity sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU=
dependencies:
no-case "^2.2.0"
path-dirname@^1.0.0:
version "1.0.2"