Skip to content
This repository has been archived by the owner on Feb 6, 2023. It is now read-only.

Commit

Permalink
Allow insertion at a specific point for updateParentChild
Browse files Browse the repository at this point in the history
Summary:
We need more flexibility for this method, so that the untab method can correctly add a child to the middle of the children array.

* insert at position 0 (first child)
* insert at len(children) position (last child)
* insert somewhere in the middle

Reviewed By: flarnie

Differential Revision: D9653244

fbshipit-source-id: 7d2bc44a9116d512838c8bbd5fe89a5ae20d5de7
  • Loading branch information
niveditc authored and facebook-github-bot committed Sep 5, 2018
1 parent 4a5ad07 commit 6b83312
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 61 deletions.
90 changes: 42 additions & 48 deletions src/model/modifier/exploration/DraftTreeOperations.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ const Immutable = require('immutable');
const invariant = require('invariant');

type SiblingInsertPosition = 'previous' | 'next';
type ChildInsertPosition = 'first' | 'last';

const verifyTree = (tree: BlockMap): void => {
if (__DEV__) {
Expand All @@ -32,67 +31,62 @@ const verifyTree = (tree: BlockMap): void => {
};

/**
* This is a utility method for setting B as a first/last child of A, ensuring
* This is a utility method for setting B as a child of A, ensuring
* that parent <-> child operations are correctly mirrored
*
* The child is inserted at 'position' index in the list
*
* The block map returned by this method may not be a valid tree (siblings are
* unaffected)
*/
const updateParentChild = (
blockMap: BlockMap,
parentKey: string,
childKey: string,
position: ChildInsertPosition,
position: number,
): BlockMap => {
const parent = blockMap.get(parentKey);
const child = blockMap.get(childKey);
invariant(
parent != null && child != null,
'parent & child should exist in the block map',
);
const existingChildren = parent.getChildKeys();
const newBlocks = {};
const existingChildren = parent.getChildKeys();
invariant(
existingChildren != null &&
position >= 0 &&
position <= existingChildren.count(),
'position is not valid for the number of children',
);

// add as parent's child
newBlocks[parentKey] = parent.merge({
children:
position === 'first'
? existingChildren.unshift(childKey)
: existingChildren.push(childKey),
children: existingChildren.splice(position, 0, childKey),
});
// add as child's parent
if (existingChildren.count() !== 0) {
// link child as sibling to the existing children
switch (position) {
case 'first':
const nextSiblingKey = existingChildren.first();
newBlocks[childKey] = child.merge({
parent: parentKey,
nextSibling: nextSiblingKey,
prevSibling: null,
});
newBlocks[nextSiblingKey] = blockMap.get(nextSiblingKey).merge({
prevSibling: childKey,
});
break;
case 'last':
const prevSiblingKey = existingChildren.last();
newBlocks[childKey] = child.merge({
parent: parentKey,
prevSibling: prevSiblingKey,
nextSibling: null,
});
newBlocks[prevSiblingKey] = blockMap.get(prevSiblingKey).merge({
nextSibling: childKey,
});
break;
}
} else {
newBlocks[childKey] = child.merge({
parent: parentKey,
prevSibling: null,
nextSibling: null,

let nextSiblingKey = null;
let prevSiblingKey = null;
// link new child as next sibling to the correct existing child
if (position > 0) {
prevSiblingKey = existingChildren.get(position - 1);
newBlocks[prevSiblingKey] = blockMap.get(prevSiblingKey).merge({
nextSibling: childKey,
});
}
// link new child as previous sibling to the correct existing child
if (position < existingChildren.count()) {
nextSiblingKey = existingChildren.get(position);
newBlocks[nextSiblingKey] = blockMap.get(nextSiblingKey).merge({
prevSibling: childKey,
});
}
// add parent & siblings to the child
newBlocks[childKey] = child.merge({
parent: parentKey,
prevSibling: prevSiblingKey,
nextSibling: nextSiblingKey,
});
return blockMap.merge(newBlocks);
};

Expand Down Expand Up @@ -181,12 +175,7 @@ const createNewParent = (blockMap: BlockMap, key: string): BlockMap => {
.concat(Immutable.OrderedMap([[newParent.getKey(), newParent]]))
.concat(blockMap.skipUntil(block => block.getKey() === key));
// set parent <-> child connection
newBlockMap = updateParentChild(
newBlockMap,
newParent.getKey(),
key,
'first',
);
newBlockMap = updateParentChild(newBlockMap, newParent.getKey(), key, 0);
// set siblings & parent for the new parent key to child's siblings & parent
const prevSibling = block.getPrevSiblingKey();
const nextSibling = block.getNextSiblingKey();
Expand Down Expand Up @@ -239,7 +228,7 @@ const updateAsSiblingsChild = (
let newBlockMap = blockMap;
switch (position) {
case 'next':
newBlockMap = updateParentChild(newBlockMap, newParentKey, key, 'first');
newBlockMap = updateParentChild(newBlockMap, newParentKey, key, 0);
const prevSibling = block.getPrevSiblingKey();
if (prevSibling != null) {
newBlockMap = updateSibling(newBlockMap, prevSibling, newParentKey);
Expand All @@ -266,7 +255,12 @@ const updateAsSiblingsChild = (
);
break;
case 'previous':
newBlockMap = updateParentChild(newBlockMap, newParentKey, key, 'last');
newBlockMap = updateParentChild(
newBlockMap,
newParentKey,
key,
newParent.getChildKeys().count(),
);
const nextSibling = block.getNextSiblingKey();
if (nextSibling != null) {
newBlockMap = updateSibling(newBlockMap, newParentKey, nextSibling);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ const blockMap1 = Immutable.OrderedMap({
}),
});

test('test adding a last child to parent', () => {
test('test adding a child to parent at position 0 (first)', () => {
let newBlockMap = DraftTreeOperations.updateParentChild(
blockMap1,
'X',
'D',
'last',
0,
);
newBlockMap = newBlockMap.merge({
X: newBlockMap.get('X').merge({
Expand All @@ -79,12 +79,27 @@ test('test adding a last child to parent', () => {
expect(newBlockMap).toMatchSnapshot();
});

test('test adding a first child to parent', () => {
test('test adding a child to parent at position 1', () => {
let newBlockMap = DraftTreeOperations.updateParentChild(
blockMap1,
'X',
'D',
'first',
1,
);
newBlockMap = newBlockMap.merge({
X: newBlockMap.get('X').merge({
nextSibling: null,
}),
});
expect(newBlockMap).toMatchSnapshot();
});

test('test adding a child to parent at last position', () => {
let newBlockMap = DraftTreeOperations.updateParentChild(
blockMap1,
'X',
'D',
2,
);
newBlockMap = newBlockMap.merge({
X: newBlockMap.get('X').merge({
Expand Down Expand Up @@ -162,7 +177,7 @@ test('test adding an only child to parent', () => {
blockMap2,
'X',
'C',
'first',
0,
);
newBlockMap = newBlockMap.merge({
B: newBlockMap.get('B').merge({
Expand Down
Loading

0 comments on commit 6b83312

Please sign in to comment.