Skip to content

Commit 5434a60

Browse files
author
Thomas Draier
authored
BACKLOG-19919: Use descendants and recursion filter for useTreeEntries (#217)
* BACKLOG-19919: Use descendants and recursion filter for useTreeEntries * Fixed test
1 parent 10995c2 commit 5434a60

File tree

3 files changed

+44
-61
lines changed

3 files changed

+44
-61
lines changed

packages/data-helper/src/fragments/fragments.utils.js

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {PredefinedFragments} from '../fragments';
55

66
function findParametersInDocument(doc) {
77
if (doc && doc.definitions) {
8-
return _.flatMap(doc.definitions, def => findParametersInSelectionSet(def.selectionSet));
8+
return doc.definitions.flatMap(def => findParametersInSelectionSet(def.selectionSet));
99
}
1010

1111
return [];
@@ -31,7 +31,7 @@ function replaceFragmentsInDocument(doc, fragments) {
3131
let clonedQuery = null;
3232
if (doc && doc.definitions) {
3333
clonedQuery = _.cloneDeep(doc);
34-
_.each(clonedQuery.definitions, def => replaceFragmentsInSelectionSet(def.selectionSet, fragments, def, clonedQuery));
34+
clonedQuery.definitions.forEach(def => replaceFragmentsInSelectionSet(def.selectionSet, fragments, def, clonedQuery));
3535
clonedQuery.definitions[0].name.value = key;
3636
}
3737

@@ -42,10 +42,10 @@ function replaceFragmentsInDocument(doc, fragments) {
4242

4343
function findParametersInSelectionSet(selectionSet) {
4444
if (selectionSet && selectionSet.selections) {
45-
return _.flatMap(selectionSet.selections, sel =>
46-
_.without(_.concat(
47-
_.flatMap(_.filter(sel.arguments, arg => (arg.value.kind === 'Variable')), arg => arg.value.name.value),
48-
findParametersInSelectionSet(sel.selectionSet)), undefined)
45+
return selectionSet.selections.flatMap(sel =>
46+
sel.arguments.filter(arg => (arg.value.kind === 'Variable')).flatMap(arg => arg.value.name.value)
47+
.concat(findParametersInSelectionSet(sel.selectionSet))
48+
.filter(f => typeof f !== 'undefined')
4949
);
5050
}
5151

@@ -54,9 +54,8 @@ function findParametersInSelectionSet(selectionSet) {
5454

5555
function findFragmentsInSelectionSet(selectionSet) {
5656
if (selectionSet && selectionSet.selections) {
57-
return _.concat(
58-
_.map(_.filter(selectionSet.selections, sel => sel.kind === 'FragmentSpread'), sel => sel.name.value),
59-
_.flatMap(selectionSet.selections, sel => findFragmentsInSelectionSet(sel.selectionSet)));
57+
return selectionSet.selections.filter(sel => sel.kind === 'FragmentSpread').map(sel => sel.name.value)
58+
.concat(selectionSet.selections.flatMap(sel => findFragmentsInSelectionSet(sel.selectionSet)));
6059
}
6160

6261
return [];
@@ -67,39 +66,38 @@ function replaceFragmentsInSelectionSet(selectionSet, fragments, def, document)
6766
let newFragmentsSpreads = [];
6867
let removedFragmentSpreads = [];
6968
// Look for all existing fragment spreads in selection set
70-
_.each(_.filter(selectionSet.selections, sel => sel.kind === 'FragmentSpread'), sel => {
69+
selectionSet.selections.filter(sel => sel.kind === 'FragmentSpread').forEach(sel => {
7170
// Handle only named fragments
7271
if (sel.name.value) {
7372
// Check if spread exists in current doc - if not, we replace or remove it
74-
let existing = _.find(document.definitions, definition => definition.kind === 'FragmentDefinition' && definition.name.value === sel.name.value);
73+
let existing = document.definitions.find(definition => definition.kind === 'FragmentDefinition' && definition.name.value === sel.name.value);
7574

7675
if (!existing) {
7776
// First remove the spread, as it has no match in document
7877
removedFragmentSpreads.push(sel);
7978

8079
// Check if a replacement is provided for this pseudo-fragment, then insert spreads and definitions
8180
if (fragments) {
82-
fragments = _.map(fragments, frag => (typeof frag === 'string') ? PredefinedFragments[frag] : frag);
81+
fragments = fragments.map(frag => (typeof frag === 'string') ? PredefinedFragments[frag] : frag);
8382

84-
let applyableFragments = _.filter(fragments, frag => frag.applyFor === sel.name.value);
83+
const applyableFragments = fragments.filter(frag => frag.applyFor === sel.name.value);
8584

86-
let allFragmentsDefinitions = _.flatMap(applyableFragments, fragment => fragment.gql.definitions);
87-
_.each(allFragmentsDefinitions, frag => {
88-
let newSpread = _.cloneDeep(sel);
85+
applyableFragments.flatMap(fragment => fragment.gql.definitions).forEach(frag => {
86+
const newSpread = _.cloneDeep(sel);
8987
newSpread.name.value = frag.name.value;
9088
newFragmentsSpreads.push(newSpread);
9189

9290
// Add the new fragment definition in document if it has not already been added
93-
let existing = _.find(document.definitions, definition => definition.kind === 'FragmentDefinition' && definition.name.value === frag.name.value);
91+
let existing = document.definitions.find(definition => definition.kind === 'FragmentDefinition' && definition.name.value === frag.name.value);
9492
if (!existing) {
9593
document.definitions.push(frag);
9694
}
9795
});
9896

9997
// Adds the associated variables to the query
100-
let allVariables = _.reduce(applyableFragments, (result, n) => _.assign(result, n.variables), {});
101-
_.each(allVariables, (value, name) => {
102-
let existing = _.find(def.variableDefinitions, def => def.variable.name.value === name);
98+
let allVariables = applyableFragments.reduce((result, n) => ({...result, ...n.variables}), {});
99+
Object.entries(allVariables).forEach(([name, value]) => {
100+
let existing = def.variableDefinitions.find(def => def.variable.name.value === name);
103101
if (!existing) {
104102
let type = parseType(value, {noLocation: true});
105103
def.variableDefinitions.push({
@@ -121,13 +119,13 @@ function replaceFragmentsInSelectionSet(selectionSet, fragments, def, document)
121119
});
122120

123121
// Removed replaced spreads
124-
selectionSet.selections = _.filter(selectionSet.selections, sel => removedFragmentSpreads.indexOf(sel) === -1);
122+
selectionSet.selections = selectionSet.selections.filter(sel => removedFragmentSpreads.indexOf(sel) === -1);
125123

126124
// Add all new spreads
127125
selectionSet.selections.push(...newFragmentsSpreads);
128126

129127
// Recursively call on sub-selections set
130-
_.each(selectionSet.selections, sel => replaceFragmentsInSelectionSet(sel.selectionSet, fragments, def, document));
128+
selectionSet.selections.forEach(sel => replaceFragmentsInSelectionSet(sel.selectionSet, fragments, def, document));
131129
}
132130
}
133131

packages/data-helper/src/hooks/useTreeEntries/useTreeEntries.gql-queries.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
// TODO BACKLOG-12393 - refactor Legacy Picker into hook without lodash
21
import gql from 'graphql-tag';
32
import {nodeCacheRequiredFields} from '../../fragments/PredefinedFragments';
43

54
export const TREE_QUERY = gql`
6-
query PickerQuery($rootPaths:[String!]!, $selectable:[String]!, $openable:[String]!, $openPaths:[String!]!, $types:[String]!, $sortBy: InputFieldSorterInput) {
5+
query PickerQuery($rootPaths:[String!]!, $selectable:[String]!, $openable:[String]!, $openPaths:[String!]!, $types:[String]!, $recursionTypesFilter: InputNodeTypesInput, $sortBy: InputFieldSorterInput, $fieldGrouping: InputFieldGroupingInput) {
76
jcr {
87
rootNodes:nodesByPath(paths: $rootPaths) {
98
name
10-
children(typesFilter:{types:$types}, limit:1) {
9+
children: descendants(typesFilter:{types: $types}, recursionTypesFilter: $recursionTypesFilter, limit:1) {
1110
pageInfo {
1211
nodesCount
1312
}
@@ -19,10 +18,10 @@ export const TREE_QUERY = gql`
1918
},
2019
openNodes:nodesByPath(paths: $openPaths) {
2120
... NodeCacheRequiredFields
22-
children(typesFilter:{types:$types}, fieldSorter: $sortBy) {
21+
children:descendants(typesFilter:{types: $types}, recursionTypesFilter: $recursionTypesFilter, fieldSorter: $sortBy, fieldGrouping: $fieldGrouping) {
2322
nodes {
2423
name
25-
children(typesFilter:{types:$types}, limit:1) {
24+
children: descendants(typesFilter:{types: $types}, recursionTypesFilter: $recursionTypesFilter, limit:1) {
2625
pageInfo {
2726
nodesCount
2827
}

packages/data-helper/src/hooks/useTreeEntries/useTreeEntries.js

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import {useRef} from 'react';
22
import {useQuery} from 'react-apollo';
33
import {replaceFragmentsInDocument} from '../../fragments/fragments.utils';
44
import {TREE_QUERY} from './useTreeEntries.gql-queries';
5-
import * as _ from 'lodash';
65

76
export const useTreeEntries = ({
87
fragments,
@@ -11,32 +10,33 @@ export const useTreeEntries = ({
1110
selectedPaths,
1211
openableTypes,
1312
selectableTypes,
13+
recursionTypesFilter,
1414
queryVariables,
1515
hideRoot,
1616
sortBy
1717
}, queryOptions) => {
1818
let query = useRef(replaceFragmentsInDocument(TREE_QUERY, fragments));
1919

2020
const getTreeEntries = (data, selectedPaths, openPaths) => {
21-
let treeEntries = [];
22-
let nodesById = {};
23-
let jcr = data ? data.jcr : {};
21+
const treeEntries = [];
22+
const nodesById = {};
23+
const jcr = data ? data.jcr : {};
2424

25-
let addNode = function (node, depth, index) {
25+
const addNode = function (node, depth, index) {
2626
let selected = false;
2727
if (node.selectable) {
28-
selected = _.indexOf(selectedPaths, node.path) !== -1;
28+
selected = selectedPaths.indexOf(node.path) !== -1;
2929
}
3030

3131
let treeEntry = {
3232
name: node.name,
3333
path: node.path,
34-
open: node.openable && _.indexOf(openPaths, node.path) !== -1,
34+
open: node.openable && openPaths.indexOf(node.path) !== -1,
3535
selected: selected,
3636
openable: node.openable,
3737
selectable: node.selectable,
3838
depth: depth,
39-
prefix: _.repeat(' ', depth * 3),
39+
prefix: ' '.repeat(depth * 3),
4040
node: node,
4141
hidden: false,
4242
hasChildren: node.children.pageInfo.nodesCount > 0
@@ -48,18 +48,18 @@ export const useTreeEntries = ({
4848

4949
if (jcr) {
5050
if (jcr.rootNodes) {
51-
_.forEach(jcr.rootNodes, rootNode => {
51+
jcr.rootNodes.forEach(rootNode => {
5252
let root = addNode(rootNode, 0, 0);
5353
root.hidden = hideRoot;
5454
});
5555
}
5656

5757
if (jcr.openNodes) {
58-
_.sortBy(jcr.openNodes, ['path']).forEach(node => {
59-
let parent = nodesById[node.uuid];
58+
[...jcr.openNodes].sort((a, b) => a.path.localeCompare(b.path)).forEach(node => {
59+
const parent = nodesById[node.uuid];
6060
if (parent) {
61-
let parentIndex = _.indexOf(treeEntries, parent);
62-
_.forEachRight(node.children.nodes, child => {
61+
const parentIndex = treeEntries.indexOf(parent);
62+
[...node.children.nodes].reverse().forEach(child => {
6363
addNode(child, parent.depth + 1, parentIndex + 1);
6464
});
6565
}
@@ -68,36 +68,22 @@ export const useTreeEntries = ({
6868
}
6969

7070
// Nodes loaded, fill selection list
71-
let selectedNodes = _.filter(treeEntries, node => {
72-
return node.selected;
73-
}).map(node => {
74-
return node.node;
75-
});
71+
selectedPaths = treeEntries.filter(node => node.selected).map(node => node.node.path);
7672

77-
selectedPaths = _.map(selectedNodes, 'path');
78-
treeEntries = _.filter(treeEntries, treeNode => {
79-
return !treeNode.hidden;
80-
});
81-
82-
return treeEntries;
73+
return treeEntries.filter(treeNode => !treeNode.hidden);
8374
};
8475

8576
let vars = {
8677
rootPaths: rootPaths,
87-
types: _.union(openableTypes, selectableTypes),
78+
types: Array.from(new Set([...(openableTypes || []), ...(selectableTypes || [])])),
79+
recursionTypesFilter: recursionTypesFilter || {types: 'nt:base', multi: 'NONE'},
8880
selectable: selectableTypes,
8981
openable: openableTypes,
90-
openPaths: openPaths
82+
openPaths: openPaths,
83+
sortBy,
84+
...queryVariables
9185
};
9286

93-
if (sortBy) { // Add the sortBy if it is not null or undefined
94-
vars.sortBy = sortBy;
95-
}
96-
97-
if (queryVariables) {
98-
_.assign(vars, queryVariables);
99-
}
100-
10187
const {data, ...others} = useQuery(query.current, {...queryOptions, variables: vars});
10288
return {treeEntries: getTreeEntries(data, selectedPaths, openPaths), ...others};
10389
};

0 commit comments

Comments
 (0)