@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+352 -31
+32 -20
resources/celerity/map.php
··· 12 12 'core.pkg.css' => 'a4a2417c', 13 13 'core.pkg.js' => '4355a8d3', 14 14 'differential.pkg.css' => '607c84be', 15 - 'differential.pkg.js' => 'e40c5192', 15 + 'differential.pkg.js' => '688775a9', 16 16 'diffusion.pkg.css' => '42c75c37', 17 17 'diffusion.pkg.js' => 'a98c0bf7', 18 18 'maniphest.pkg.css' => '35995d6d', ··· 378 378 'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => 'a2ab19be', 379 379 'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '1e413dc9', 380 380 'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '0116d3e8', 381 - 'rsrc/js/application/diff/DiffChangeset.js' => '5a4e4a3b', 382 - 'rsrc/js/application/diff/DiffChangesetList.js' => '3ac694dd', 381 + 'rsrc/js/application/diff/DiffChangeset.js' => 'd1eda7b4', 382 + 'rsrc/js/application/diff/DiffChangesetList.js' => '469beba0', 383 383 'rsrc/js/application/diff/DiffInline.js' => '16e97ebc', 384 + 'rsrc/js/application/diff/DiffPathView.js' => 'e5166692', 385 + 'rsrc/js/application/diff/DiffTreeView.js' => '4055adeb', 384 386 'rsrc/js/application/diff/behavior-preview-link.js' => 'f51e9c17', 385 387 'rsrc/js/application/differential/behavior-diff-radios.js' => '925fe8cd', 386 388 'rsrc/js/application/differential/behavior-populate.js' => 'b86ef6c2', ··· 778 780 'phabricator-darklog' => '3b869402', 779 781 'phabricator-darkmessage' => '26cd4b73', 780 782 'phabricator-dashboard-css' => '5a205b9d', 781 - 'phabricator-diff-changeset' => '5a4e4a3b', 782 - 'phabricator-diff-changeset-list' => '3ac694dd', 783 + 'phabricator-diff-changeset' => 'd1eda7b4', 784 + 'phabricator-diff-changeset-list' => '469beba0', 783 785 'phabricator-diff-inline' => '16e97ebc', 786 + 'phabricator-diff-path-view' => 'e5166692', 787 + 'phabricator-diff-tree-view' => '4055adeb', 784 788 'phabricator-drag-and-drop-file-upload' => '4370900d', 785 789 'phabricator-draggable-list' => '0169e425', 786 790 'phabricator-fatal-config-template-css' => '20babf50', ··· 1240 1244 'trigger-rule', 1241 1245 'trigger-rule-type', 1242 1246 ), 1243 - '3ac694dd' => array( 1244 - 'javelin-install', 1245 - 'phuix-button-view', 1246 - ), 1247 1247 '3ae89b20' => array( 1248 1248 'phui-workcard-view-css', 1249 1249 ), ··· 1266 1266 'phabricator-phtize', 1267 1267 'phabricator-drag-and-drop-file-upload', 1268 1268 'phabricator-draggable-list', 1269 + ), 1270 + '4055adeb' => array( 1271 + 'javelin-dom', 1269 1272 ), 1270 1273 '407ee861' => array( 1271 1274 'javelin-behavior', ··· 1315 1318 'javelin-router', 1316 1319 'javelin-util', 1317 1320 'phabricator-busy', 1321 + ), 1322 + '469beba0' => array( 1323 + 'javelin-install', 1324 + 'phuix-button-view', 1325 + 'phabricator-diff-tree-view', 1318 1326 ), 1319 1327 '47a0728b' => array( 1320 1328 'javelin-behavior', ··· 1466 1474 'javelin-dom', 1467 1475 'javelin-history', 1468 1476 ), 1469 - '5a4e4a3b' => array( 1470 - 'javelin-dom', 1471 - 'javelin-util', 1472 - 'javelin-stratcom', 1473 - 'javelin-install', 1474 - 'javelin-workflow', 1475 - 'javelin-router', 1476 - 'javelin-behavior-device', 1477 - 'javelin-vector', 1478 - 'phabricator-diff-inline', 1479 - ), 1480 1477 '5a6f6a06' => array( 1481 1478 'javelin-behavior', 1482 1479 'javelin-quicksand', ··· 2099 2096 'javelin-workflow', 2100 2097 'javelin-util', 2101 2098 ), 2099 + 'd1eda7b4' => array( 2100 + 'javelin-dom', 2101 + 'javelin-util', 2102 + 'javelin-stratcom', 2103 + 'javelin-install', 2104 + 'javelin-workflow', 2105 + 'javelin-router', 2106 + 'javelin-behavior-device', 2107 + 'javelin-vector', 2108 + 'phabricator-diff-inline', 2109 + 'phabricator-diff-path-view', 2110 + ), 2102 2111 'd3799cb4' => array( 2103 2112 'javelin-install', 2104 2113 ), ··· 2124 2133 'javelin-stratcom', 2125 2134 'javelin-dom', 2126 2135 'phuix-dropdown-menu', 2136 + ), 2137 + 'e5166692' => array( 2138 + 'javelin-dom', 2127 2139 ), 2128 2140 'e5bdb730' => array( 2129 2141 'javelin-behavior',
+4 -1
src/applications/differential/view/DifferentialChangesetDetailView.php
··· 178 178 $changeset_state = null; 179 179 } 180 180 181 + $path_parts = trim($display_filename, '/'); 182 + $path_parts = explode('/', $path_parts); 183 + 181 184 return javelin_tag( 182 185 'div', 183 186 array( ··· 189 192 'ref' => $this->getRenderingRef(), 190 193 'autoload' => $this->getAutoload(), 191 194 'displayPath' => hsprintf('%s', $display_parts), 192 - 'path' => $display_filename, 193 195 'icon' => $display_icon, 194 196 'treeNodeID' => 'tree-node-'.$changeset->getAnchorName(), 197 + 'pathParts' => $path_parts, 195 198 196 199 'editorURI' => $this->getEditorURI(), 197 200 'editorConfigureURI' => $this->getEditorConfigureURI(),
+18 -1
webroot/rsrc/js/application/diff/DiffChangeset.js
··· 9 9 * javelin-behavior-device 10 10 * javelin-vector 11 11 * phabricator-diff-inline 12 + * phabricator-diff-path-view 12 13 * @javelin 13 14 */ 14 - 15 15 16 16 JX.install('DiffChangeset', { 17 17 ··· 29 29 this._rightID = data.right; 30 30 31 31 this._displayPath = JX.$H(data.displayPath); 32 + this._pathParts = data.pathParts; 32 33 this._icon = data.icon; 33 34 34 35 this._editorURI = data.editorURI; ··· 70 71 71 72 _editorURI: null, 72 73 _editorConfigureURI: null, 74 + _pathView: null, 73 75 74 76 getEditorURI: function() { 75 77 return this._editorURI; ··· 891 893 _onundo: function(e) { 892 894 e.kill(); 893 895 this.toggleVisibility(); 896 + }, 897 + 898 + getPathView: function() { 899 + if (!this._pathView) { 900 + this._pathView = new JX.DiffPathView() 901 + .setChangeset(this) 902 + .setPath(this._pathParts); 903 + } 904 + 905 + return this._pathView; 906 + }, 907 + 908 + select: function(scroll) { 909 + this.getChangesetList().selectChangeset(this, scroll); 910 + return this; 894 911 } 895 912 }, 896 913
+56 -9
webroot/rsrc/js/application/diff/DiffChangesetList.js
··· 2 2 * @provides phabricator-diff-changeset-list 3 3 * @requires javelin-install 4 4 * phuix-button-view 5 + * phabricator-diff-tree-view 5 6 * @javelin 6 7 */ 7 8 ··· 638 639 cursor: cursor, 639 640 items: items 640 641 }; 642 + }, 643 + 644 + selectChangeset: function(changeset, scroll) { 645 + var items = this._getSelectableItems(); 646 + 647 + var cursor = null; 648 + for (var ii = 0; ii < items.length; ii++) { 649 + var item = items[ii]; 650 + if (changeset === item.target) { 651 + cursor = ii; 652 + break; 653 + } 654 + } 655 + 656 + if (cursor !== null) { 657 + this._setSelectionState(items[cursor], true); 658 + } 659 + 660 + return this; 641 661 }, 642 662 643 663 _setSelectionState: function(item, scroll) { ··· 1467 1487 1468 1488 var node = this._getBannerNode(); 1469 1489 var changeset = this._getVisibleChangeset(); 1490 + var tree = this._getTreeView(); 1491 + var formation = this.getFormationView(); 1470 1492 1471 1493 if (!changeset) { 1472 1494 this._bannerChangeset = null; 1473 1495 JX.DOM.remove(node); 1496 + tree.setSelectedPath(null); 1497 + 1498 + if (formation) { 1499 + formation.repaint(); 1500 + } 1501 + 1474 1502 return; 1475 1503 } 1476 1504 ··· 1481 1509 } 1482 1510 this._bannerChangeset = changeset; 1483 1511 1512 + var paths = tree.getPaths(); 1513 + for (var ii = 0; ii < paths.length; ii++) { 1514 + var path = paths[ii]; 1515 + if (path.getChangeset() === changeset) { 1516 + tree.setSelectedPath(path); 1517 + } 1518 + } 1519 + 1484 1520 var inlines = this._getInlinesByType(); 1485 1521 1486 1522 var unsaved = inlines.unsaved; ··· 1586 1622 JX.DOM.setContent(node, [buttons_view, path_view]); 1587 1623 1588 1624 document.body.appendChild(node); 1625 + 1626 + if (formation) { 1627 + formation.repaint(); 1628 + } 1589 1629 }, 1590 1630 1591 1631 _getInlinesByType: function() { ··· 1958 1998 return null; 1959 1999 }, 1960 2000 2001 + _getTreeView: function() { 2002 + if (!this._treeView) { 2003 + var tree = new JX.DiffTreeView(); 2004 + 2005 + for (var ii = 0; ii < this._changesets.length; ii++) { 2006 + var changeset = this._changesets[ii]; 2007 + tree.addPath(changeset.getPathView()); 2008 + } 2009 + 2010 + this._treeView = tree; 2011 + } 2012 + return this._treeView; 2013 + }, 2014 + 1961 2015 _redrawFiletree : function() { 1962 2016 var formation = this.getFormationView(); 1963 2017 ··· 1970 2024 1971 2025 var flank_body = flank.getBodyNode(); 1972 2026 1973 - var items = []; 1974 - for (var ii = 0; ii < this._changesets.length; ii++) { 1975 - var changeset = this._changesets[ii]; 1976 - 1977 - var node = JX.$N('div', {}, changeset.getDisplayPath()); 1978 - items.push(node); 1979 - } 1980 - 1981 - JX.DOM.setContent(flank_body, items); 2027 + var tree = this._getTreeView(); 2028 + JX.DOM.setContent(flank_body, tree.getNode()); 1982 2029 } 1983 2030 1984 2031 }
+83
webroot/rsrc/js/application/diff/DiffPathView.js
··· 1 + /** 2 + * @provides phabricator-diff-path-view 3 + * @requires javelin-dom 4 + * @javelin 5 + */ 6 + 7 + JX.install('DiffPathView', { 8 + 9 + construct: function() { 10 + }, 11 + 12 + properties: { 13 + changeset: null 14 + }, 15 + 16 + members: { 17 + _node: null, 18 + _path: null, 19 + _depth: 0, 20 + _selected: false, 21 + 22 + getNode: function() { 23 + if (!this._node) { 24 + this._node = JX.$N('li'); 25 + 26 + var onclick = JX.bind(this, this._onclick); 27 + JX.DOM.listen(this._node, 'click', null, onclick); 28 + } 29 + return this._node; 30 + }, 31 + 32 + setPath: function(path) { 33 + this._path = path; 34 + this._redraw(); 35 + return this; 36 + }, 37 + 38 + getPath: function() { 39 + return this._path; 40 + }, 41 + 42 + setDepth: function(depth) { 43 + this._depth = depth; 44 + this._redraw(); 45 + return this; 46 + }, 47 + 48 + setIsSelected: function(selected) { 49 + this._selected = selected; 50 + this._redraw(); 51 + return this; 52 + }, 53 + 54 + _onclick: function(e) { 55 + if (!e.isNormalClick()) { 56 + return; 57 + } 58 + 59 + var changeset = this.getChangeset(); 60 + if (changeset) { 61 + changeset.select(true); 62 + } 63 + 64 + e.kill(); 65 + }, 66 + 67 + _redraw: function() { 68 + var node = this.getNode(); 69 + 70 + node.style.paddingLeft = (8 * this._depth) + 'px'; 71 + 72 + var display = this._path[this._path.length - 1]; 73 + 74 + if (this._selected) { 75 + display = ['*', display]; 76 + } 77 + 78 + JX.DOM.setContent(node, display); 79 + } 80 + 81 + } 82 + 83 + });
+159
webroot/rsrc/js/application/diff/DiffTreeView.js
··· 1 + /** 2 + * @provides phabricator-diff-tree-view 3 + * @requires javelin-dom 4 + * @javelin 5 + */ 6 + 7 + JX.install('DiffTreeView', { 8 + 9 + construct: function() { 10 + this._keys = []; 11 + this._tree = this._newTreeNode(null, [], 0); 12 + this._nodes = {}; 13 + this._paths = []; 14 + }, 15 + 16 + members: { 17 + _node: null, 18 + _keys: null, 19 + _tree: null, 20 + _nodes: null, 21 + _dirty: false, 22 + _paths: null, 23 + _selectedPath: null, 24 + 25 + getNode: function() { 26 + if (!this._node) { 27 + this._node = JX.$N('ul'); 28 + } 29 + 30 + if (this._dirty) { 31 + this.redraw(); 32 + } 33 + 34 + return this._node; 35 + }, 36 + 37 + addPath: function(path) { 38 + this._paths.push(path); 39 + 40 + var tree = this._getTree(this._tree, path.getPath(), 0); 41 + tree.pathObject = path; 42 + 43 + this._dirty = true; 44 + 45 + return this; 46 + }, 47 + 48 + getPaths: function() { 49 + return this._paths; 50 + }, 51 + 52 + setSelectedPath: function(path) { 53 + if (this._selectedPath) { 54 + this._selectedPath.setIsSelected(false); 55 + this._selectedPath = null; 56 + } 57 + 58 + if (path) { 59 + path.setIsSelected(true); 60 + } 61 + 62 + this._selectedPath = path; 63 + 64 + return this; 65 + }, 66 + 67 + redraw: function() { 68 + if (!this._dirty) { 69 + return; 70 + } 71 + this._dirty = false; 72 + 73 + var ii; 74 + 75 + // For nodes which don't have a path object yet, build one. 76 + var tree; 77 + var trees = []; 78 + for (ii = 0; ii < this._keys.length; ii++) { 79 + var key = this._keys[ii]; 80 + tree = this._nodes[key]; 81 + var path = tree.pathObject; 82 + 83 + if (!path) { 84 + path = new JX.DiffPathView() 85 + .setPath(tree.parts); 86 + tree.pathObject = path; 87 + } 88 + 89 + trees.push(tree); 90 + } 91 + 92 + for (ii = 0; ii < trees.length; ii++) { 93 + tree = trees[ii]; 94 + 95 + if (!tree.parent) { 96 + tree.depth = 0; 97 + } else { 98 + tree.depth = tree.parent.depth + 1; 99 + } 100 + 101 + tree.pathObject.setDepth((tree.depth - 1)); 102 + } 103 + 104 + var nodes = []; 105 + for (ii = 0; ii < trees.length; ii++) { 106 + tree = trees[ii]; 107 + nodes.push(tree.pathObject.getNode()); 108 + } 109 + 110 + JX.DOM.setContent(this.getNode(), nodes); 111 + }, 112 + 113 + _getTree: function(root, path, ii) { 114 + if (ii >= path.length) { 115 + return root; 116 + } 117 + 118 + var part = path[ii]; 119 + 120 + if (!root.children.hasOwnProperty(part)) { 121 + root.children[part] = this._newTreeNode(root, path, ii); 122 + root.childCount++; 123 + } 124 + 125 + return this._getTree(root.children[part], path, ii + 1); 126 + }, 127 + 128 + _newTreeNode: function(parent, path, ii) { 129 + var key; 130 + var parts; 131 + if (path.length) { 132 + parts = path.slice(0, ii + 1); 133 + key = parts.join('/'); 134 + this._keys.push(key); 135 + } else { 136 + parts = []; 137 + key = null; 138 + } 139 + 140 + var node = { 141 + parent: parent, 142 + nodeKey: key, 143 + parts: parts, 144 + children: {}, 145 + pathObject: null, 146 + childCount: 0, 147 + depth: 0 148 + }; 149 + 150 + if (key !== null) { 151 + this._nodes[key] = node; 152 + } 153 + 154 + return node; 155 + } 156 + 157 + } 158 + 159 + });