mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 06:42:42 +01:00
Generate file trees from changesets in the new flank UI
Summary: Ref T13516. Generate a tree structure based on the page changesets. Still missing styles and a whole lot of behavior. Test Plan: {F7373967} Maniphest Tasks: T13516 Differential Revision: https://secure.phabricator.com/D21152
This commit is contained in:
parent
646280972b
commit
8cd1f9a309
6 changed files with 352 additions and 31 deletions
|
@ -12,7 +12,7 @@ return array(
|
|||
'core.pkg.css' => 'a4a2417c',
|
||||
'core.pkg.js' => '4355a8d3',
|
||||
'differential.pkg.css' => '607c84be',
|
||||
'differential.pkg.js' => 'e40c5192',
|
||||
'differential.pkg.js' => '688775a9',
|
||||
'diffusion.pkg.css' => '42c75c37',
|
||||
'diffusion.pkg.js' => 'a98c0bf7',
|
||||
'maniphest.pkg.css' => '35995d6d',
|
||||
|
@ -378,9 +378,11 @@ return array(
|
|||
'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => 'a2ab19be',
|
||||
'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '1e413dc9',
|
||||
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '0116d3e8',
|
||||
'rsrc/js/application/diff/DiffChangeset.js' => '5a4e4a3b',
|
||||
'rsrc/js/application/diff/DiffChangesetList.js' => '3ac694dd',
|
||||
'rsrc/js/application/diff/DiffChangeset.js' => 'd1eda7b4',
|
||||
'rsrc/js/application/diff/DiffChangesetList.js' => '469beba0',
|
||||
'rsrc/js/application/diff/DiffInline.js' => '16e97ebc',
|
||||
'rsrc/js/application/diff/DiffPathView.js' => 'e5166692',
|
||||
'rsrc/js/application/diff/DiffTreeView.js' => '4055adeb',
|
||||
'rsrc/js/application/diff/behavior-preview-link.js' => 'f51e9c17',
|
||||
'rsrc/js/application/differential/behavior-diff-radios.js' => '925fe8cd',
|
||||
'rsrc/js/application/differential/behavior-populate.js' => 'b86ef6c2',
|
||||
|
@ -778,9 +780,11 @@ return array(
|
|||
'phabricator-darklog' => '3b869402',
|
||||
'phabricator-darkmessage' => '26cd4b73',
|
||||
'phabricator-dashboard-css' => '5a205b9d',
|
||||
'phabricator-diff-changeset' => '5a4e4a3b',
|
||||
'phabricator-diff-changeset-list' => '3ac694dd',
|
||||
'phabricator-diff-changeset' => 'd1eda7b4',
|
||||
'phabricator-diff-changeset-list' => '469beba0',
|
||||
'phabricator-diff-inline' => '16e97ebc',
|
||||
'phabricator-diff-path-view' => 'e5166692',
|
||||
'phabricator-diff-tree-view' => '4055adeb',
|
||||
'phabricator-drag-and-drop-file-upload' => '4370900d',
|
||||
'phabricator-draggable-list' => '0169e425',
|
||||
'phabricator-fatal-config-template-css' => '20babf50',
|
||||
|
@ -1240,10 +1244,6 @@ return array(
|
|||
'trigger-rule',
|
||||
'trigger-rule-type',
|
||||
),
|
||||
'3ac694dd' => array(
|
||||
'javelin-install',
|
||||
'phuix-button-view',
|
||||
),
|
||||
'3ae89b20' => array(
|
||||
'phui-workcard-view-css',
|
||||
),
|
||||
|
@ -1267,6 +1267,9 @@ return array(
|
|||
'phabricator-drag-and-drop-file-upload',
|
||||
'phabricator-draggable-list',
|
||||
),
|
||||
'4055adeb' => array(
|
||||
'javelin-dom',
|
||||
),
|
||||
'407ee861' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-uri',
|
||||
|
@ -1316,6 +1319,11 @@ return array(
|
|||
'javelin-util',
|
||||
'phabricator-busy',
|
||||
),
|
||||
'469beba0' => array(
|
||||
'javelin-install',
|
||||
'phuix-button-view',
|
||||
'phabricator-diff-tree-view',
|
||||
),
|
||||
'47a0728b' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-dom',
|
||||
|
@ -1466,17 +1474,6 @@ return array(
|
|||
'javelin-dom',
|
||||
'javelin-history',
|
||||
),
|
||||
'5a4e4a3b' => array(
|
||||
'javelin-dom',
|
||||
'javelin-util',
|
||||
'javelin-stratcom',
|
||||
'javelin-install',
|
||||
'javelin-workflow',
|
||||
'javelin-router',
|
||||
'javelin-behavior-device',
|
||||
'javelin-vector',
|
||||
'phabricator-diff-inline',
|
||||
),
|
||||
'5a6f6a06' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-quicksand',
|
||||
|
@ -2099,6 +2096,18 @@ return array(
|
|||
'javelin-workflow',
|
||||
'javelin-util',
|
||||
),
|
||||
'd1eda7b4' => array(
|
||||
'javelin-dom',
|
||||
'javelin-util',
|
||||
'javelin-stratcom',
|
||||
'javelin-install',
|
||||
'javelin-workflow',
|
||||
'javelin-router',
|
||||
'javelin-behavior-device',
|
||||
'javelin-vector',
|
||||
'phabricator-diff-inline',
|
||||
'phabricator-diff-path-view',
|
||||
),
|
||||
'd3799cb4' => array(
|
||||
'javelin-install',
|
||||
),
|
||||
|
@ -2125,6 +2134,9 @@ return array(
|
|||
'javelin-dom',
|
||||
'phuix-dropdown-menu',
|
||||
),
|
||||
'e5166692' => array(
|
||||
'javelin-dom',
|
||||
),
|
||||
'e5bdb730' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-stratcom',
|
||||
|
|
|
@ -178,6 +178,9 @@ final class DifferentialChangesetDetailView extends AphrontView {
|
|||
$changeset_state = null;
|
||||
}
|
||||
|
||||
$path_parts = trim($display_filename, '/');
|
||||
$path_parts = explode('/', $path_parts);
|
||||
|
||||
return javelin_tag(
|
||||
'div',
|
||||
array(
|
||||
|
@ -189,9 +192,9 @@ final class DifferentialChangesetDetailView extends AphrontView {
|
|||
'ref' => $this->getRenderingRef(),
|
||||
'autoload' => $this->getAutoload(),
|
||||
'displayPath' => hsprintf('%s', $display_parts),
|
||||
'path' => $display_filename,
|
||||
'icon' => $display_icon,
|
||||
'treeNodeID' => 'tree-node-'.$changeset->getAnchorName(),
|
||||
'pathParts' => $path_parts,
|
||||
|
||||
'editorURI' => $this->getEditorURI(),
|
||||
'editorConfigureURI' => $this->getEditorConfigureURI(),
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
* javelin-behavior-device
|
||||
* javelin-vector
|
||||
* phabricator-diff-inline
|
||||
* phabricator-diff-path-view
|
||||
* @javelin
|
||||
*/
|
||||
|
||||
|
||||
JX.install('DiffChangeset', {
|
||||
|
||||
construct : function(node) {
|
||||
|
@ -29,6 +29,7 @@ JX.install('DiffChangeset', {
|
|||
this._rightID = data.right;
|
||||
|
||||
this._displayPath = JX.$H(data.displayPath);
|
||||
this._pathParts = data.pathParts;
|
||||
this._icon = data.icon;
|
||||
|
||||
this._editorURI = data.editorURI;
|
||||
|
@ -70,6 +71,7 @@ JX.install('DiffChangeset', {
|
|||
|
||||
_editorURI: null,
|
||||
_editorConfigureURI: null,
|
||||
_pathView: null,
|
||||
|
||||
getEditorURI: function() {
|
||||
return this._editorURI;
|
||||
|
@ -891,6 +893,21 @@ JX.install('DiffChangeset', {
|
|||
_onundo: function(e) {
|
||||
e.kill();
|
||||
this.toggleVisibility();
|
||||
},
|
||||
|
||||
getPathView: function() {
|
||||
if (!this._pathView) {
|
||||
this._pathView = new JX.DiffPathView()
|
||||
.setChangeset(this)
|
||||
.setPath(this._pathParts);
|
||||
}
|
||||
|
||||
return this._pathView;
|
||||
},
|
||||
|
||||
select: function(scroll) {
|
||||
this.getChangesetList().selectChangeset(this, scroll);
|
||||
return this;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* @provides phabricator-diff-changeset-list
|
||||
* @requires javelin-install
|
||||
* phuix-button-view
|
||||
* phabricator-diff-tree-view
|
||||
* @javelin
|
||||
*/
|
||||
|
||||
|
@ -640,6 +641,25 @@ JX.install('DiffChangesetList', {
|
|||
};
|
||||
},
|
||||
|
||||
selectChangeset: function(changeset, scroll) {
|
||||
var items = this._getSelectableItems();
|
||||
|
||||
var cursor = null;
|
||||
for (var ii = 0; ii < items.length; ii++) {
|
||||
var item = items[ii];
|
||||
if (changeset === item.target) {
|
||||
cursor = ii;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cursor !== null) {
|
||||
this._setSelectionState(items[cursor], true);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_setSelectionState: function(item, scroll) {
|
||||
this._cursorItem = item;
|
||||
this._redrawSelection(scroll);
|
||||
|
@ -1467,10 +1487,18 @@ JX.install('DiffChangesetList', {
|
|||
|
||||
var node = this._getBannerNode();
|
||||
var changeset = this._getVisibleChangeset();
|
||||
var tree = this._getTreeView();
|
||||
var formation = this.getFormationView();
|
||||
|
||||
if (!changeset) {
|
||||
this._bannerChangeset = null;
|
||||
JX.DOM.remove(node);
|
||||
tree.setSelectedPath(null);
|
||||
|
||||
if (formation) {
|
||||
formation.repaint();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1481,6 +1509,14 @@ JX.install('DiffChangesetList', {
|
|||
}
|
||||
this._bannerChangeset = changeset;
|
||||
|
||||
var paths = tree.getPaths();
|
||||
for (var ii = 0; ii < paths.length; ii++) {
|
||||
var path = paths[ii];
|
||||
if (path.getChangeset() === changeset) {
|
||||
tree.setSelectedPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
var inlines = this._getInlinesByType();
|
||||
|
||||
var unsaved = inlines.unsaved;
|
||||
|
@ -1586,6 +1622,10 @@ JX.install('DiffChangesetList', {
|
|||
JX.DOM.setContent(node, [buttons_view, path_view]);
|
||||
|
||||
document.body.appendChild(node);
|
||||
|
||||
if (formation) {
|
||||
formation.repaint();
|
||||
}
|
||||
},
|
||||
|
||||
_getInlinesByType: function() {
|
||||
|
@ -1958,6 +1998,20 @@ JX.install('DiffChangesetList', {
|
|||
return null;
|
||||
},
|
||||
|
||||
_getTreeView: function() {
|
||||
if (!this._treeView) {
|
||||
var tree = new JX.DiffTreeView();
|
||||
|
||||
for (var ii = 0; ii < this._changesets.length; ii++) {
|
||||
var changeset = this._changesets[ii];
|
||||
tree.addPath(changeset.getPathView());
|
||||
}
|
||||
|
||||
this._treeView = tree;
|
||||
}
|
||||
return this._treeView;
|
||||
},
|
||||
|
||||
_redrawFiletree : function() {
|
||||
var formation = this.getFormationView();
|
||||
|
||||
|
@ -1970,15 +2024,8 @@ JX.install('DiffChangesetList', {
|
|||
|
||||
var flank_body = flank.getBodyNode();
|
||||
|
||||
var items = [];
|
||||
for (var ii = 0; ii < this._changesets.length; ii++) {
|
||||
var changeset = this._changesets[ii];
|
||||
|
||||
var node = JX.$N('div', {}, changeset.getDisplayPath());
|
||||
items.push(node);
|
||||
}
|
||||
|
||||
JX.DOM.setContent(flank_body, items);
|
||||
var tree = this._getTreeView();
|
||||
JX.DOM.setContent(flank_body, tree.getNode());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
83
webroot/rsrc/js/application/diff/DiffPathView.js
Normal file
83
webroot/rsrc/js/application/diff/DiffPathView.js
Normal file
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* @provides phabricator-diff-path-view
|
||||
* @requires javelin-dom
|
||||
* @javelin
|
||||
*/
|
||||
|
||||
JX.install('DiffPathView', {
|
||||
|
||||
construct: function() {
|
||||
},
|
||||
|
||||
properties: {
|
||||
changeset: null
|
||||
},
|
||||
|
||||
members: {
|
||||
_node: null,
|
||||
_path: null,
|
||||
_depth: 0,
|
||||
_selected: false,
|
||||
|
||||
getNode: function() {
|
||||
if (!this._node) {
|
||||
this._node = JX.$N('li');
|
||||
|
||||
var onclick = JX.bind(this, this._onclick);
|
||||
JX.DOM.listen(this._node, 'click', null, onclick);
|
||||
}
|
||||
return this._node;
|
||||
},
|
||||
|
||||
setPath: function(path) {
|
||||
this._path = path;
|
||||
this._redraw();
|
||||
return this;
|
||||
},
|
||||
|
||||
getPath: function() {
|
||||
return this._path;
|
||||
},
|
||||
|
||||
setDepth: function(depth) {
|
||||
this._depth = depth;
|
||||
this._redraw();
|
||||
return this;
|
||||
},
|
||||
|
||||
setIsSelected: function(selected) {
|
||||
this._selected = selected;
|
||||
this._redraw();
|
||||
return this;
|
||||
},
|
||||
|
||||
_onclick: function(e) {
|
||||
if (!e.isNormalClick()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var changeset = this.getChangeset();
|
||||
if (changeset) {
|
||||
changeset.select(true);
|
||||
}
|
||||
|
||||
e.kill();
|
||||
},
|
||||
|
||||
_redraw: function() {
|
||||
var node = this.getNode();
|
||||
|
||||
node.style.paddingLeft = (8 * this._depth) + 'px';
|
||||
|
||||
var display = this._path[this._path.length - 1];
|
||||
|
||||
if (this._selected) {
|
||||
display = ['*', display];
|
||||
}
|
||||
|
||||
JX.DOM.setContent(node, display);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
159
webroot/rsrc/js/application/diff/DiffTreeView.js
Normal file
159
webroot/rsrc/js/application/diff/DiffTreeView.js
Normal file
|
@ -0,0 +1,159 @@
|
|||
/**
|
||||
* @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,
|
||||
|
||||
getNode: function() {
|
||||
if (!this._node) {
|
||||
this._node = JX.$N('ul');
|
||||
}
|
||||
|
||||
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;
|
||||
},
|
||||
|
||||
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 trees = [];
|
||||
for (ii = 0; ii < this._keys.length; ii++) {
|
||||
var key = this._keys[ii];
|
||||
tree = this._nodes[key];
|
||||
var path = tree.pathObject;
|
||||
|
||||
if (!path) {
|
||||
path = new JX.DiffPathView()
|
||||
.setPath(tree.parts);
|
||||
tree.pathObject = path;
|
||||
}
|
||||
|
||||
trees.push(tree);
|
||||
}
|
||||
|
||||
for (ii = 0; ii < trees.length; ii++) {
|
||||
tree = trees[ii];
|
||||
|
||||
if (!tree.parent) {
|
||||
tree.depth = 0;
|
||||
} else {
|
||||
tree.depth = tree.parent.depth + 1;
|
||||
}
|
||||
|
||||
tree.pathObject.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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
Loading…
Reference in a new issue