1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-09-20 09:18:48 +02:00
phorge-phorge/webroot/rsrc/js/application/diff/DiffTreeView.js
epriestley 9550ae6984 When a directory has a single directory child, collapse them into a single "a/b/" path entry
Summary:
Ref T13516. Instead of rendering trees like this:

  - a/
    - b/
      - c.txt

...render:

  - a/b/
    - c.txt

Test Plan: {F7374205}

Maniphest Tasks: T13516

Differential Revision: https://secure.phabricator.com/D21155
2020-04-22 08:37:03 -07:00

255 lines
5.1 KiB
JavaScript

/**
* @provides phabricator-diff-tree-view
* @requires javelin-dom
* @javelin
*/
JX.install('DiffTreeView', {
construct: function() {
this._keys = [];
this._tree = this._newTreeNode(null, [], 0);
this._nodes = {};
this._paths = [];
},
members: {
_node: null,
_keys: null,
_tree: null,
_nodes: null,
_dirty: false,
_paths: null,
_selectedPath: null,
_focusedPath: null,
getNode: function() {
if (!this._node) {
var attrs = {
className: 'diff-tree-view'
};
this._node = JX.$N('ul', attrs);
}
if (this._dirty) {
this.redraw();
}
return this._node;
},
addPath: function(path) {
this._paths.push(path);
var tree = this._getTree(this._tree, path.getPath(), 0);
tree.pathObject = path;
this._dirty = true;
return this;
},
getPaths: function() {
return this._paths;
},
setSelectedPath: function(path) {
if (this._selectedPath) {
this._selectedPath.setIsSelected(false);
this._selectedPath = null;
}
if (path) {
path.setIsSelected(true);
}
this._selectedPath = path;
return this;
},
setFocusedPath: function(path) {
if (this._focusedPath) {
this._focusedPath.setIsFocused(false);
this._focusedPath = null;
}
if (path) {
path.setIsFocused(true);
}
this._focusedPath = path;
return this;
},
redraw: function() {
if (!this._dirty) {
return;
}
this._dirty = false;
var ii;
// For nodes which don't have a path object yet, build one.
var tree;
var path;
var trees = [];
for (ii = 0; ii < this._keys.length; ii++) {
var key = this._keys[ii];
tree = this._nodes[key];
path = tree.pathObject;
if (!path) {
path = new JX.DiffPathView()
.setPath(tree.parts);
path.getIcon()
.setIcon('fa-folder-open-o');
tree.pathObject = path;
}
trees.push(tree);
}
for (ii = 0; ii < trees.length; ii++) {
tree = trees[ii];
tree.displayRoot = null;
tree.displayPath = null;
tree.displayHide = false;
}
var child;
for (ii = 0; ii < trees.length; ii++) {
tree = trees[ii];
if (tree.childCount !== 1) {
continue;
}
for (var k in tree.children) {
if (tree.children.hasOwnProperty(k)) {
child = tree.children[k];
break;
}
}
if (child.pathObject.getChangeset()) {
continue;
}
child.displayRoot = tree.displayRoot || tree;
}
for (ii = 0; ii < trees.length; ii++) {
tree = trees[ii];
if (!tree.displayRoot) {
continue;
}
if (!tree.displayRoot.displayPath) {
tree.displayRoot.displayPath = [
tree.displayRoot.parts[tree.displayRoot.parts.length - 1]
];
}
tree.displayRoot.displayPath.push(tree.parts[tree.parts.length - 1]);
tree.displayHide = true;
}
for (ii = 0; ii < trees.length; ii++) {
tree = trees[ii];
path = tree.pathObject;
path.setHidden(!!tree.displayHide);
if (tree.displayPath) {
path.setDisplayPath(tree.displayPath.join('/'));
} else {
path.setDisplayPath(null);
}
}
for (ii = 0; ii < trees.length; ii++) {
tree = trees[ii];
if (!tree.parent) {
tree.depth = 0;
} else {
// If this node was collapsed into the parent node, don't increase
// the tree depth.
if (tree.displayHide) {
tree.depth = tree.parent.depth;
} else {
tree.depth = tree.parent.depth + 1;
}
}
path = tree.pathObject;
if (tree.childCount > 0) {
path.setIsDirectory(true);
}
path.setDepth((tree.depth - 1));
}
var nodes = [];
for (ii = 0; ii < trees.length; ii++) {
tree = trees[ii];
nodes.push(tree.pathObject.getNode());
}
JX.DOM.setContent(this.getNode(), nodes);
},
_getTree: function(root, path, ii) {
if (ii >= path.length) {
return root;
}
var part = path[ii];
if (!root.children.hasOwnProperty(part)) {
root.children[part] = this._newTreeNode(root, path, ii);
root.childCount++;
}
return this._getTree(root.children[part], path, ii + 1);
},
_newTreeNode: function(parent, path, ii) {
var key;
var parts;
if (path.length) {
parts = path.slice(0, ii + 1);
key = parts.join('/');
this._keys.push(key);
} else {
parts = [];
key = null;
}
var node = {
parent: parent,
nodeKey: key,
parts: parts,
children: {},
pathObject: null,
childCount: 0,
depth: 0
};
if (key !== null) {
this._nodes[key] = node;
}
return node;
}
}
});