From 5d6dd7df7d7ab45506fcb5e5753c4c70ec506bd1 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 15 Jan 2016 04:25:22 -0800 Subject: [PATCH 01/66] Add a basic remarkup typeahead for users and projects Summary: Ref T3725. This probably has 900,000 bugs. This will need updates for subprojects/milestones. Test Plan: - Tested very gently in Safari, Firefox and Chrome. - Reasonable inputs appear to work. - Clicking, escape, tab, return, arrow keys work OK? Reviewers: chad Reviewed By: chad Maniphest Tasks: T3725 Differential Revision: https://secure.phabricator.com/D15029 --- resources/celerity/map.php | 71 +-- .../typeahead/PhabricatorPeopleDatasource.php | 7 +- .../PhabricatorProjectDatasource.php | 7 +- .../storage/PhabricatorTypeaheadResult.php | 11 + .../control/PhabricatorRemarkupControl.php | 17 + webroot/rsrc/css/core/remarkup.css | 49 ++ webroot/rsrc/css/core/z-index.css | 4 + webroot/rsrc/js/core/Prefab.js | 3 +- .../behavior-phabricator-remarkup-assist.js | 10 + webroot/rsrc/js/phuix/PHUIXAutocomplete.js | 504 ++++++++++++++++++ 10 files changed, 648 insertions(+), 35 deletions(-) create mode 100644 webroot/rsrc/js/phuix/PHUIXAutocomplete.js diff --git a/resources/celerity/map.php b/resources/celerity/map.php index bb30c70582..e64383cd6c 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,8 +7,8 @@ */ return array( 'names' => array( - 'core.pkg.css' => '1eed0b4f', - 'core.pkg.js' => '6ae03393', + 'core.pkg.css' => 'f30d5cbd', + 'core.pkg.js' => '1f5f365a', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', 'differential.pkg.js' => 'f83532f8', @@ -102,9 +102,9 @@ return array( 'rsrc/css/application/tokens/tokens.css' => '3d0f239e', 'rsrc/css/application/uiexample/example.css' => '528b19de', 'rsrc/css/core/core.css' => 'a76cefc9', - 'rsrc/css/core/remarkup.css' => 'b6ad82e4', + 'rsrc/css/core/remarkup.css' => 'b748dc17', 'rsrc/css/core/syntax.css' => '9fd11da8', - 'rsrc/css/core/z-index.css' => '57ddcaa2', + 'rsrc/css/core/z-index.css' => 'a36a45da', 'rsrc/css/diviner/diviner-shared.css' => 'aa3656aa', 'rsrc/css/font/font-aleo.css' => '8bdb2835', 'rsrc/css/font/font-awesome.css' => 'c43323c5', @@ -457,7 +457,7 @@ return array( 'rsrc/js/core/KeyboardShortcutManager.js' => 'c1700f6f', 'rsrc/js/core/MultirowRowManager.js' => 'b5d57730', 'rsrc/js/core/Notification.js' => 'ccf1cbf8', - 'rsrc/js/core/Prefab.js' => '666c80c5', + 'rsrc/js/core/Prefab.js' => 'a15cbd65', 'rsrc/js/core/ShapedRequest.js' => '7cbe244b', 'rsrc/js/core/TextAreaUtils.js' => '9e54692d', 'rsrc/js/core/Title.js' => 'df5e11d2', @@ -487,7 +487,7 @@ return array( 'rsrc/js/core/behavior-object-selector.js' => '49b73b36', 'rsrc/js/core/behavior-oncopy.js' => '2926fff2', 'rsrc/js/core/behavior-phabricator-nav.js' => '56a1ca03', - 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'b60b6d9b', + 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '340c8eff', 'rsrc/js/core/behavior-refresh-csrf.js' => 'ab2f381b', 'rsrc/js/core/behavior-remarkup-preview.js' => '4b700e9e', 'rsrc/js/core/behavior-reorder-applications.js' => '76b9fc3e', @@ -506,6 +506,7 @@ return array( 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', + 'rsrc/js/phuix/PHUIXAutocomplete.js' => 'c5f5e42f', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 'rsrc/js/phuix/PHUIXFormControl.js' => '8fba1997', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', @@ -639,7 +640,7 @@ return array( 'javelin-behavior-phabricator-notification-example' => '8ce821c5', 'javelin-behavior-phabricator-object-selector' => '49b73b36', 'javelin-behavior-phabricator-oncopy' => '2926fff2', - 'javelin-behavior-phabricator-remarkup-assist' => 'b60b6d9b', + 'javelin-behavior-phabricator-remarkup-assist' => '340c8eff', 'javelin-behavior-phabricator-reveal-content' => '60821bc7', 'javelin-behavior-phabricator-search-typeahead' => '0b7a4f6e', 'javelin-behavior-phabricator-show-older-transactions' => 'dbbf48b6', @@ -758,8 +759,8 @@ return array( 'phabricator-notification-menu-css' => 'f31c0bde', 'phabricator-object-selector-css' => '85ee8ce6', 'phabricator-phtize' => 'd254d646', - 'phabricator-prefab' => '666c80c5', - 'phabricator-remarkup-css' => 'b6ad82e4', + 'phabricator-prefab' => 'a15cbd65', + 'phabricator-remarkup-css' => 'b748dc17', 'phabricator-search-results-css' => '7dea472c', 'phabricator-shaped-request' => '7cbe244b', 'phabricator-side-menu-view-css' => '91b7a42c', @@ -780,7 +781,7 @@ return array( 'phabricator-uiexample-reactor-select' => 'a155550f', 'phabricator-uiexample-reactor-sendclass' => '1def2711', 'phabricator-uiexample-reactor-sendproperties' => 'b1f0ccee', - 'phabricator-zindex-css' => '57ddcaa2', + 'phabricator-zindex-css' => 'a36a45da', 'phame-css' => 'dac8fdf2', 'pholio-css' => '95174bdd', 'pholio-edit-css' => '3ad9d1ee', @@ -833,6 +834,7 @@ return array( 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', + 'phuix-autocomplete' => 'c5f5e42f', 'phuix-dropdown-menu' => 'bd4c8dca', 'phuix-form-control-view' => '8fba1997', 'phuix-icon-view' => 'bff6884b', @@ -1050,6 +1052,16 @@ return array( '331b1611' => array( 'javelin-install', ), + '340c8eff' => array( + 'javelin-behavior', + 'javelin-stratcom', + 'javelin-dom', + 'phabricator-phtize', + 'phabricator-textareautils', + 'javelin-workflow', + 'javelin-vector', + 'phuix-autocomplete', + ), '3ab51e2c' => array( 'javelin-behavior', 'javelin-behavior-device', @@ -1293,18 +1305,6 @@ return array( 'javelin-vector', 'differential-inline-comment-editor', ), - '666c80c5' => array( - 'javelin-install', - 'javelin-util', - 'javelin-dom', - 'javelin-typeahead', - 'javelin-tokenizer', - 'javelin-typeahead-preloaded-source', - 'javelin-typeahead-ondemand-source', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-util', - ), '66dd6e9e' => array( 'javelin-behavior', 'javelin-behavior-device', @@ -1587,6 +1587,18 @@ return array( 'javelin-dom', 'javelin-reactor-dom', ), + 'a15cbd65' => array( + 'javelin-install', + 'javelin-util', + 'javelin-dom', + 'javelin-typeahead', + 'javelin-tokenizer', + 'javelin-typeahead-preloaded-source', + 'javelin-typeahead-ondemand-source', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-util', + ), 'a16ec1c6' => array( 'javelin-install', 'javelin-dom', @@ -1742,15 +1754,6 @@ return array( 'javelin-dom', 'javelin-util', ), - 'b60b6d9b' => array( - 'javelin-behavior', - 'javelin-stratcom', - 'javelin-dom', - 'phabricator-phtize', - 'phabricator-textareautils', - 'javelin-workflow', - 'javelin-vector', - ), 'b6993408' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1794,6 +1797,12 @@ return array( 'javelin-dom', 'javelin-vector', ), + 'c5f5e42f' => array( + 'javelin-install', + 'javelin-dom', + 'phuix-icon-view', + 'phabricator-prefab', + ), 'c6f720ff' => array( 'javelin-install', 'javelin-dom', diff --git a/src/applications/people/typeahead/PhabricatorPeopleDatasource.php b/src/applications/people/typeahead/PhabricatorPeopleDatasource.php index cdd68988a9..2cd337cacc 100644 --- a/src/applications/people/typeahead/PhabricatorPeopleDatasource.php +++ b/src/applications/people/typeahead/PhabricatorPeopleDatasource.php @@ -59,12 +59,15 @@ final class PhabricatorPeopleDatasource $closed = pht('Mailing List'); } + $username = $user->getUsername(); + $result = id(new PhabricatorTypeaheadResult()) ->setName($user->getFullName()) - ->setURI('/p/'.$user->getUsername()) + ->setURI('/p/'.$username.'/') ->setPHID($user->getPHID()) - ->setPriorityString($user->getUsername()) + ->setPriorityString($username) ->setPriorityType('user') + ->setAutocomplete('@'.$username) ->setClosed($closed); if ($user->getIsMailingList()) { diff --git a/src/applications/project/typeahead/PhabricatorProjectDatasource.php b/src/applications/project/typeahead/PhabricatorProjectDatasource.php index 64f0604b3f..9a18006e5c 100644 --- a/src/applications/project/typeahead/PhabricatorProjectDatasource.php +++ b/src/applications/project/typeahead/PhabricatorProjectDatasource.php @@ -65,13 +65,18 @@ final class PhabricatorProjectDatasource ->setName($all_strings) ->setDisplayName($proj->getName()) ->setDisplayType(pht('Project')) - ->setURI('/tag/'.$proj->getPrimarySlug().'/') + ->setURI($proj->getURI()) ->setPHID($proj->getPHID()) ->setIcon($proj->getDisplayIconIcon()) ->setColor($proj->getColor()) ->setPriorityType('proj') ->setClosed($closed); + $slug = $proj->getPrimarySlug(); + if (strlen($slug)) { + $proj_result->setAutocomplete('#'.$slug); + } + $proj_result->setImageURI($proj->getProfileImageURI()); $results[] = $proj_result; diff --git a/src/applications/typeahead/storage/PhabricatorTypeaheadResult.php b/src/applications/typeahead/storage/PhabricatorTypeaheadResult.php index 6ef913fc5a..f5c84766b7 100644 --- a/src/applications/typeahead/storage/PhabricatorTypeaheadResult.php +++ b/src/applications/typeahead/storage/PhabricatorTypeaheadResult.php @@ -16,6 +16,7 @@ final class PhabricatorTypeaheadResult extends Phobject { private $closed; private $tokenType; private $unique; + private $autocomplete; public function setIcon($icon) { $this->icon = $icon; @@ -114,6 +115,15 @@ final class PhabricatorTypeaheadResult extends Phobject { return $this->color; } + public function setAutocomplete($autocomplete) { + $this->autocomplete = $autocomplete; + return $this; + } + + public function getAutocomplete() { + return $this->autocomplete; + } + public function getSortKey() { // Put unique results (special parameter functions) ahead of other // results. @@ -142,6 +152,7 @@ final class PhabricatorTypeaheadResult extends Phobject { $this->color, $this->tokenType, $this->unique ? 1 : null, + $this->autocomplete, ); while (end($data) === null) { array_pop($data); diff --git a/src/view/form/control/PhabricatorRemarkupControl.php b/src/view/form/control/PhabricatorRemarkupControl.php index be989d8a5c..11388d257e 100644 --- a/src/view/form/control/PhabricatorRemarkupControl.php +++ b/src/view/form/control/PhabricatorRemarkupControl.php @@ -44,6 +44,9 @@ final class PhabricatorRemarkupControl extends AphrontFormTextAreaControl { $root_id = celerity_generate_unique_node_id(); + $user_datasource = new PhabricatorPeopleDatasource(); + $proj_datasource = new PhabricatorProjectDatasource(); + Javelin::initBehavior( 'phabricator-remarkup-assist', array( @@ -59,6 +62,20 @@ final class PhabricatorRemarkupControl extends AphrontFormTextAreaControl { ), 'disabled' => $this->getDisabled(), 'rootID' => $root_id, + 'autocompleteMap' => (object)array( + 64 => array( // "@" + 'datasourceURI' => $user_datasource->getDatasourceURI(), + 'headerIcon' => 'fa-user', + 'headerText' => pht('Find User:'), + 'hintText' => $user_datasource->getPlaceholderText(), + ), + 35 => array( // "#" + 'datasourceURI' => $proj_datasource->getDatasourceURI(), + 'headerIcon' => 'fa-briefcase', + 'headerText' => pht('Find Project:'), + 'hintText' => $proj_datasource->getPlaceholderText(), + ), + ), )); Javelin::initBehavior('phabricator-tooltips', array()); diff --git a/webroot/rsrc/css/core/remarkup.css b/webroot/rsrc/css/core/remarkup.css index 6c43ba6159..da04fe2b68 100644 --- a/webroot/rsrc/css/core/remarkup.css +++ b/webroot/rsrc/css/core/remarkup.css @@ -561,3 +561,52 @@ var.remarkup-assist-textarea { .device .remarkup-assist-nodevice { display: none; } + +.phuix-autocomplete { + position: absolute; + width: 300px; + box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.300); + background: #ffffff; + border: 1px solid {$blueborder}; +} + +.phuix-autocomplete-head { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + padding: 4px 8px; + background: {$lightgreybackground}; + color: {$greytext}; +} + +.phuix-autocomplete-head .phui-icon-view { + margin-right: 4px; + color: {$greytext}; +} + +.phuix-autocomplete-echo { + margin-left: 4px; + color: {$lightgreytext}; +} + +.phuix-autocomplete-list a.jx-result { + display: block; + padding: 4px 8px; + font-size: {$normalfontsize}; + border-top: 1px solid {$hoverborder}; + color: {$darkgreytext}; +} + +.phuix-autocomplete-list a.jx-result .phui-icon-view { + margin-right: 4px; +} + +.phuix-autocomplete-list a.jx-result:hover { + text-decoration: none; + background: {$hoverblue}; +} + +.phuix-autocomplete-list a.jx-result.focused, +.phuix-autocomplete-list a.jx-result.focused:hover { + background: {$hoverblue}; +} diff --git a/webroot/rsrc/css/core/z-index.css b/webroot/rsrc/css/core/z-index.css index 06513c9d59..3025b5dc5c 100644 --- a/webroot/rsrc/css/core/z-index.css +++ b/webroot/rsrc/css/core/z-index.css @@ -150,6 +150,10 @@ div.jx-typeahead-results { z-index: 20; } +.phuix-autocomplete { + z-index: 21; +} + .phuix-dropdown-menu { z-index: 32; } diff --git a/webroot/rsrc/js/core/Prefab.js b/webroot/rsrc/js/core/Prefab.js index d48b295f0d..5f5c210273 100644 --- a/webroot/rsrc/js/core/Prefab.js +++ b/webroot/rsrc/js/core/Prefab.js @@ -325,7 +325,8 @@ JX.install('Prefab', { sprite: fields[10], color: fields[11], tokenType: fields[12], - unique: fields[13] || false + unique: fields[13] || false, + autocomplete: fields[14] }; }, diff --git a/webroot/rsrc/js/core/behavior-phabricator-remarkup-assist.js b/webroot/rsrc/js/core/behavior-phabricator-remarkup-assist.js index 9dabffeb10..f09070e42e 100644 --- a/webroot/rsrc/js/core/behavior-phabricator-remarkup-assist.js +++ b/webroot/rsrc/js/core/behavior-phabricator-remarkup-assist.js @@ -7,6 +7,7 @@ * phabricator-textareautils * javelin-workflow * javelin-vector + * phuix-autocomplete */ JX.behavior('phabricator-remarkup-assist', function(config) { @@ -293,4 +294,13 @@ JX.behavior('phabricator-remarkup-assist', function(config) { assist(area, data.action, root, e.getNode('remarkup-assist')); }); + var autocomplete = new JX.PHUIXAutocomplete() + .setArea(area); + + for (var k in config.autocompleteMap) { + autocomplete.addAutocomplete(k, config.autocompleteMap[k]); + } + + autocomplete.start(); + }); diff --git a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js new file mode 100644 index 0000000000..e2148113fd --- /dev/null +++ b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js @@ -0,0 +1,504 @@ +/** + * @provides phuix-autocomplete + * @requires javelin-install + * javelin-dom + * phuix-icon-view + * phabricator-prefab + */ + +JX.install('PHUIXAutocomplete', { + + construct: function() { + this._map = {}; + this._datasources = {}; + this._listNodes = []; + }, + + members: { + _area: null, + _active: false, + _cursorHead: null, + _cursorTail: null, + _pixelHead: null, + _pixelTail: null, + _map: null, + _datasource: null, + _datasources: null, + _value: null, + _node: null, + _echoNode: null, + _listNode: null, + _promptNode: null, + _focus: null, + _focusRef: null, + _listNodes: null, + + setArea: function(area) { + this._area = area; + return this; + }, + + addAutocomplete: function(code, spec) { + this._map[code] = spec; + return this; + }, + + start: function() { + var area = this._area; + + JX.DOM.listen(area, 'keypress', null, JX.bind(this, this._onkeypress)); + + JX.DOM.listen( + area, + ['click', 'keyup', 'keydown', 'keypress'], + null, + JX.bind(this, this._update)); + + var select = JX.bind(this, this._onselect); + JX.DOM.listen(this._getNode(), 'click', 'typeahead-result', select); + + var device = JX.bind(this, this._ondevice); + JX.Stratcom.listen('phabricator-device-change', null, device); + + // When the user clicks away from the textarea, deactivate. + var deactivate = JX.bind(this, this._deactivate); + JX.DOM.listen(area, 'blur', null, deactivate); + }, + + _getSpec: function() { + return this._map[this._active]; + }, + + _ondevice: function() { + if (JX.Device.getDevice() != 'desktop') { + this._deactivate(); + } + }, + + _activate: function(code) { + if (JX.Device.getDevice() != 'desktop') { + return; + } + + if (!this._map[code]) { + return; + } + + var area = this._area; + var range = JX.TextAreaUtils.getSelectionRange(area); + + // Check the character immediately before the trigger character. We'll + // only activate the typeahead if it's something that we think a user + // might reasonably want to autocomplete after, like a space, newline, + // or open parenthesis. For example, if a user types "alincoln@", + // the prior letter will be the last "n" in "alincoln". They are probably + // typing an email address, not a username, so we don't activate the + // autocomplete. + var head = range.start; + var prior; + if (head > 1) { + prior = area.value.substring(head - 2, head - 1); + } else { + prior = ''; + } + + switch (prior) { + case '': + case ' ': + case '\n': + case '\t': + case '(': // Might be "(@username, what do you think?)". + case '-': // Might be an unnumbered list. + case '.': // Might be a numbered list. + case '|': // Might be a table cell. + // We'll let these autocomplete. + break; + default: + // We bail out on anything else, since the user is probably not + // typing a username or project tag. + return; + } + + this._cursorHead = head; + this._cursorTail = range.end; + this._pixelHead = JX.TextAreaUtils.getPixelDimensions( + area, + range.start, + range.end); + + var spec = this._map[code]; + if (!this._datasources[code]) { + var datasource = new JX.TypeaheadOnDemandSource(spec.datasourceURI); + datasource.listen( + 'resultsready', + JX.bind(this, this._onresults, code)); + + datasource.setTransformer(JX.bind(this, this._transformresult)); + + this._datasources[code] = datasource; + } + + this._datasource = this._datasources[code]; + this._active = code; + + var head_icon = new JX.PHUIXIconView() + .setIcon(spec.headerIcon) + .getNode(); + var head_text = spec.headerText; + + var node = this._getPromptNode(); + JX.DOM.setContent(node, [head_icon, head_text]); + }, + + _transformresult: function(fields) { + var map = JX.Prefab.transformDatasourceResults(fields); + + var icon; + if (map.icon) { + icon = new JX.PHUIXIconView() + .setIcon(map.icon) + .getNode(); + } + + map.display = [icon, map.displayName]; + + return map; + }, + + _deactivate: function() { + var node = this._getNode(); + JX.DOM.hide(node); + + this._active = false; + }, + + _onkeypress: function(e) { + var r = e.getRawEvent(); + + if (r.metaKey || r.altKey || r.ctrlKey) { + return; + } + + var code = r.charCode; + if (this._map[code]) { + setTimeout(JX.bind(this, this._activate, code), 0); + } + }, + + _onresults: function(code, nodes, value) { + if (code !== this._active) { + return; + } + + if (value !== this._value) { + return; + } + + var list = this._getListNode(); + JX.DOM.setContent(list, nodes); + + this._listNodes = nodes; + + var old_ref = this._focusRef; + this._clearFocus(); + + for (var ii = 0; ii < nodes.length; ii++) { + if (nodes[ii].rel == old_ref) { + this._setFocus(ii); + break; + } + } + + if (this._focus === null && nodes.length) { + this._setFocus(0); + } + }, + + _setFocus: function(idx) { + if (!this._listNodes[idx]) { + this._clearFocus(); + return false; + } + + if (this._focus !== null) { + JX.DOM.alterClass(this._listNodes[this._focus], 'focused', false); + } + + this._focus = idx; + this._focusRef = this._listNodes[idx].rel; + JX.DOM.alterClass(this._listNodes[idx], 'focused', true); + + return true; + }, + + _changeFocus: function(delta) { + if (this._focus === null) { + return false; + } + + return this._setFocus(this._focus + delta); + }, + + _clearFocus: function() { + this._focus = null; + this._focusRef = null; + }, + + _onselect: function (e) { + var target = e.getNode('typeahead-result'); + + for (var ii = 0; ii < this._listNodes.length; ii++) { + if (this._listNodes[ii] === target) { + this._setFocus(ii); + this._autocomplete(); + break; + } + } + + this._deactivate(); + e.kill(); + }, + + _getSuffixes: function() { + return[' ', ':', ',']; + }, + + _trim: function(str) { + var suffixes = this._getSuffixes(); + for (var ii = 0; ii < suffixes.length; ii++) { + if (str.substring(str.length - suffixes[ii].length) == suffixes[ii]) { + str = str.substring(0, str.length - suffixes[ii].length); + } + } + return str; + }, + + _update: function(e) { + if (!this._active) { + return; + } + + var special = e.getSpecialKey(); + + // Deactivate if the user types escape. + if (special == 'esc') { + this._deactivate(); + e.kill(); + return; + } + + var area = this._area; + + if (e.getType() == 'keydown') { + if (special == 'up' || special == 'down') { + var delta = (special == 'up') ? -1 : +1; + if (!this._changeFocus(delta)) { + this._deactivate(); + } + e.kill(); + return; + } + } + + if (special == 'tab' || special == 'return') { + var r = e.getRawEvent(); + if (r.shiftKey && special == 'tab') { + // Don't treat "Shift + Tab" as an autocomplete action. Instead, + // let it through normally so the focus shifts to the previous + // control. + this._deactivate(); + return; + } + + // If we autocomplete, we're done. Otherwise, just eat the event. This + // happens if you type too fast and try to tab complete before results + // load. + if (this._autocomplete()) { + this._deactivate(); + } + + e.kill(); + return; + } + + // Deactivate if the user moves the cursor to the left of the assist + // range. For example, they might press the "left" arrow to move the + // cursor to the left, or click in the textarea prior to the active + // range. + var range = JX.TextAreaUtils.getSelectionRange(area); + if (range.start < this._cursorHead) { + this._deactivate(); + return; + } + + // Deactivate if the user moves the cursor to the right of the assist + // range. For example, they might click later in the document. If the user + // is pressing the "right" arrow key, they are not allowed to move the + // cursor beyond the existing end of the text range. If they are pressing + // other keys, assume they're typing and allow the tail to move forward + // one character. + var margin; + if (special == 'right') { + margin = 0; + } else { + margin = 1; + } + + var tail = this._cursorTail; + + if ((range.start > tail + margin) || (range.end > tail + margin)) { + this._deactivate(); + return; + } + + this._cursorTail = Math.max(this._cursorTail, range.end); + + var text = area.value.substring( + this._cursorHead, + this._cursorTail); + + this._value = text; + + var pixels = JX.TextAreaUtils.getPixelDimensions( + area, + range.start, + range.end); + + var x = this._pixelHead.start.x; + var y = Math.max(this._pixelHead.end.y, pixels.end.y) + 24; + + var trim = this._trim(text); + + this._datasource.didChange(trim); + + var node = this._getNode(); + node.style.left = x + 'px'; + node.style.top = y + 'px'; + JX.DOM.show(node); + + var echo = this._getEchoNode(); + var hint = trim; + if (!hint.length) { + hint = this._getSpec().hintText; + } + + JX.DOM.setContent(echo, hint); + }, + + _autocomplete: function() { + if (this._focus === null) { + return false; + } + + var area = this._area; + var head = this._cursorHead; + var tail = this._cursorTail; + + var text = area.value; + + var ref = this._focusRef; + var result = this._datasource.getResult(ref); + if (!result) { + return false; + } + + ref = result.autocomplete; + if (!ref || !ref.length) { + return false; + } + + // If the user types a string like "@username:" (with a trailing comma), + // then presses tab or return to pick the completion, don't destroy the + // trailing character. + var suffixes = this._getSuffixes(); + var value = this._value; + for (var ii = 0; ii < suffixes.length; ii++) { + var last = value.substring(value.length - suffixes[ii].length); + if (last == suffixes[ii]) { + ref += suffixes[ii]; + break; + } + } + + area.value = text.substring(0, head - 1) + ref + text.substring(tail); + + var end = head + ref.length; + JX.TextAreaUtils.setSelectionRange(area, end, end); + + return true; + }, + + _getNode: function() { + if (!this._node) { + var head = this._getHeadNode(); + var list = this._getListNode(); + + this._node = JX.$N( + 'div', + { + className: 'phuix-autocomplete', + style: { + display: 'none' + } + }, + [head, list]); + + JX.DOM.hide(this._node); + + document.body.appendChild(this._node); + } + return this._node; + }, + + _getHeadNode: function() { + if (!this._headNode) { + this._headNode = JX.$N( + 'div', + { + className: 'phuix-autocomplete-head' + }, + [ + this._getPromptNode(), + this._getEchoNode() + ]); + } + + return this._headNode; + }, + + _getPromptNode: function() { + if (!this._promptNode) { + this._promptNode = JX.$N( + 'span', + { + className: 'phuix-autocomplete-prompt', + }); + } + return this._promptNode; + }, + + _getEchoNode: function() { + if (!this._echoNode) { + this._echoNode = JX.$N( + 'span', + { + className: 'phuix-autocomplete-echo' + }); + } + return this._echoNode; + }, + + _getListNode: function() { + if (!this._listNode) { + this._listNode = JX.$N( + 'div', + { + className: 'phuix-autocomplete-list' + }); + } + return this._listNode; + } + + } + +}); From 468031d1fd77711a4edca23cb8a1889ea2ba131b Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 13 Jan 2016 16:07:04 -0800 Subject: [PATCH 02/66] Rough initial cut of profile new profile menu Summary: Ref T10054. I haven't done any of the big-picture layout stuff yet, but this should get look-and-feel somewhere in the ballpark of reasonablness, I think. Major missing stuff: - No "collapse" state or action yet. - Menu is not full-height (requires changes to the rendering pipeline). Test Plan: {F1060941} Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15016 --- resources/celerity/map.php | 9 ++- resources/celerity/packages.php | 1 + .../CelerityDefaultPostprocessor.php | 6 ++ .../PhabricatorProjectDetailsProfilePanel.php | 4 +- .../PhabricatorProjectMembersProfilePanel.php | 4 +- ...habricatorProjectWorkboardProfilePanel.php | 4 +- .../engine/PhabricatorProfilePanelEngine.php | 5 +- .../PhabricatorLinkProfilePanel.php | 4 +- .../profilepanel/PhabricatorProfilePanel.php | 4 + .../PhabricatorProfilePanelIconSet.php | 15 ++++ src/view/layout/AphrontSideNavFilterView.php | 19 ++++- .../css/layout/phabricator-side-menu-view.css | 17 +++-- webroot/rsrc/css/phui/phui-profile-menu.css | 76 +++++++++++++++++++ 13 files changed, 142 insertions(+), 26 deletions(-) create mode 100644 webroot/rsrc/css/phui/phui-profile-menu.css diff --git a/resources/celerity/map.php b/resources/celerity/map.php index e64383cd6c..18ba9fcbc8 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => 'f30d5cbd', + 'core.pkg.css' => 'e9eca0fd', 'core.pkg.js' => '1f5f365a', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -112,7 +112,7 @@ return array( 'rsrc/css/font/phui-font-icon-base.css' => 'ecbbb4c2', 'rsrc/css/layout/phabricator-filetree-view.css' => 'fccf9f82', 'rsrc/css/layout/phabricator-hovercard-view.css' => '1239cd52', - 'rsrc/css/layout/phabricator-side-menu-view.css' => '91b7a42c', + 'rsrc/css/layout/phabricator-side-menu-view.css' => '1ddcb82f', 'rsrc/css/layout/phabricator-source-code-view.css' => 'cbeef983', 'rsrc/css/phui/calendar/phui-calendar-day.css' => 'd1cf6f93', 'rsrc/css/phui/calendar/phui-calendar-list.css' => 'c1c7f338', @@ -143,6 +143,7 @@ return array( 'rsrc/css/phui/phui-object-item-list-view.css' => '26c30d3f', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', + 'rsrc/css/phui/phui-profile-menu.css' => '5a1644af', 'rsrc/css/phui/phui-property-list-view.css' => '27b2849e', 'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591', 'rsrc/css/phui/phui-spacing.css' => '042804d6', @@ -763,7 +764,7 @@ return array( 'phabricator-remarkup-css' => 'b748dc17', 'phabricator-search-results-css' => '7dea472c', 'phabricator-shaped-request' => '7cbe244b', - 'phabricator-side-menu-view-css' => '91b7a42c', + 'phabricator-side-menu-view-css' => '1ddcb82f', 'phabricator-slowvote-css' => 'da0afb1b', 'phabricator-source-code-view-css' => 'cbeef983', 'phabricator-standard-page-view' => '3c99cdf4', @@ -821,6 +822,7 @@ return array( 'phui-object-item-list-view-css' => '26c30d3f', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', + 'phui-profile-menu-css' => '5a1644af', 'phui-property-list-view-css' => '27b2849e', 'phui-remarkup-preview-css' => '1a8f2591', 'phui-spacing-css' => '042804d6', @@ -2136,6 +2138,7 @@ return array( 'phui-spacing-css', 'phui-form-css', 'phui-icon-view-css', + 'phui-profile-menu-css', 'phabricator-application-launch-view-css', 'phabricator-action-list-view-css', 'phui-property-list-view-css', diff --git a/resources/celerity/packages.php b/resources/celerity/packages.php index bb97cb889e..5a3e296a8c 100644 --- a/resources/celerity/packages.php +++ b/resources/celerity/packages.php @@ -116,6 +116,7 @@ return array( 'phui-spacing-css', 'phui-form-css', 'phui-icon-view-css', + 'phui-profile-menu-css', 'phabricator-application-launch-view-css', 'phabricator-action-list-view-css', diff --git a/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php b/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php index 7c230d9869..527318f7f9 100644 --- a/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php +++ b/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php @@ -191,6 +191,12 @@ final class CelerityDefaultPostprocessor // Background color for "dark" themes. 'page.background.dark' => '#ebecee', + 'menu.profile.background' => '#525868', + 'menu.profile.text' => '#c6c7cb', + 'menu.profile.text.selected' => '#ffffff', + 'menu.profile.icon' => '#ffffff', + 'menu.profile.icon.disabled' => '#b9bcc2', + ); } diff --git a/src/applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php b/src/applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php index 5a8bacf9dd..97ba3a1aaa 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php +++ b/src/applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php @@ -46,9 +46,7 @@ final class PhabricatorProjectDetailsProfilePanel $href = "/project/profile/{$id}/"; - $item = id(new PHUIListItemView()) - ->setRenderNameAsTooltip(true) - ->setType(PHUIListItemView::TYPE_ICON_NAV) + $item = $this->newItem() ->setHref($href) ->setName($name) ->setProfileImage($picture); diff --git a/src/applications/project/profilepanel/PhabricatorProjectMembersProfilePanel.php b/src/applications/project/profilepanel/PhabricatorProjectMembersProfilePanel.php index 0db2a03773..b5374416aa 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectMembersProfilePanel.php +++ b/src/applications/project/profilepanel/PhabricatorProjectMembersProfilePanel.php @@ -46,9 +46,7 @@ final class PhabricatorProjectMembersProfilePanel $icon = 'fa-group'; $href = "/project/members/{$id}/"; - $item = id(new PHUIListItemView()) - ->setRenderNameAsTooltip(true) - ->setType(PHUIListItemView::TYPE_ICON_NAV) + $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon($icon); diff --git a/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php b/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php index 91f2f553f5..02b54537e5 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php +++ b/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php @@ -61,9 +61,7 @@ final class PhabricatorProjectWorkboardProfilePanel $href = "/project/board/{$id}/"; $name = $this->getDisplayName($config); - $item = id(new PHUIListItemView()) - ->setRenderNameAsTooltip(true) - ->setType(PHUIListItemView::TYPE_ICON_NAV) + $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon($icon); diff --git a/src/applications/search/engine/PhabricatorProfilePanelEngine.php b/src/applications/search/engine/PhabricatorProfilePanelEngine.php index 760665e5b2..40e95a4acc 100644 --- a/src/applications/search/engine/PhabricatorProfilePanelEngine.php +++ b/src/applications/search/engine/PhabricatorProfilePanelEngine.php @@ -131,7 +131,7 @@ final class PhabricatorProfilePanelEngine extends Phobject { public function buildNavigation() { $nav = id(new AphrontSideNavFilterView()) - ->setIconNav(true) + ->setIsProfileMenu(true) ->setBaseURI(new PhutilURI('/project/')); $panels = $this->getPanels(); @@ -303,8 +303,7 @@ final class PhabricatorProfilePanelEngine extends Phobject { ->setIcon('fa-gear') ->setHref($this->getPanelURI('configure/')) ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit) - ->setRenderNameAsTooltip(true); + ->setWorkflow(!$can_edit); } public function getConfigureURI() { diff --git a/src/applications/search/profilepanel/PhabricatorLinkProfilePanel.php b/src/applications/search/profilepanel/PhabricatorLinkProfilePanel.php index d2b19ad368..5b4c404635 100644 --- a/src/applications/search/profilepanel/PhabricatorLinkProfilePanel.php +++ b/src/applications/search/profilepanel/PhabricatorLinkProfilePanel.php @@ -82,9 +82,7 @@ final class PhabricatorLinkProfilePanel $icon_class = 'fa-link'; } - $item = id(new PHUIListItemView()) - ->setRenderNameAsTooltip(true) - ->setType(PHUIListItemView::TYPE_ICON_NAV) + $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon($icon_class); diff --git a/src/applications/search/profilepanel/PhabricatorProfilePanel.php b/src/applications/search/profilepanel/PhabricatorProfilePanel.php index 6f029927d8..54985bfc43 100644 --- a/src/applications/search/profilepanel/PhabricatorProfilePanel.php +++ b/src/applications/search/profilepanel/PhabricatorProfilePanel.php @@ -51,4 +51,8 @@ abstract class PhabricatorProfilePanel extends Phobject { ->execute(); } + protected function newItem() { + return new PHUIListItemView(); + } + } diff --git a/src/applications/search/profilepanel/PhabricatorProfilePanelIconSet.php b/src/applications/search/profilepanel/PhabricatorProfilePanelIconSet.php index 19b164e932..50efc217e0 100644 --- a/src/applications/search/profilepanel/PhabricatorProfilePanelIconSet.php +++ b/src/applications/search/profilepanel/PhabricatorProfilePanelIconSet.php @@ -26,6 +26,21 @@ final class PhabricatorProfilePanelIconSet 'icon' => 'fa-newspaper-o', 'name' => pht('Feed'), ), + array( + 'key' => 'phriction', + 'icon' => 'fa-book', + 'name' => pht('Phriction'), + ), + array( + 'key' => 'conpherence', + 'icon' => 'fa-comments', + 'name' => pht('Conpherence'), + ), + array( + 'key' => 'create', + 'icon' => 'fa-plus', + 'name' => pht('Create'), + ), ); $icons = array(); diff --git a/src/view/layout/AphrontSideNavFilterView.php b/src/view/layout/AphrontSideNavFilterView.php index 45e49f43fe..d3688ce93a 100644 --- a/src/view/layout/AphrontSideNavFilterView.php +++ b/src/view/layout/AphrontSideNavFilterView.php @@ -28,6 +28,7 @@ final class AphrontSideNavFilterView extends AphrontView { private $classes = array(); private $menuID; private $iconNav; + private $isProfileMenu; public function setMenuID($menu_id) { $this->menuID = $menu_id; @@ -55,6 +56,15 @@ final class AphrontSideNavFilterView extends AphrontView { return $this->crumbs; } + public function setIsProfileMenu($is_profile) { + $this->isProfileMenu = $is_profile; + return $this; + } + + public function getIsProfileMenu() { + return $this->isProfileMenu; + } + public function setIconNav($nav) { $this->iconNav = $nav; return $this; @@ -207,10 +217,17 @@ final class AphrontSideNavFilterView extends AphrontView { $nav_classes = array(); $nav_classes[] = 'phabricator-nav'; - if ($this->iconNav) { + + if ($this->getIsProfileMenu()) { + require_celerity_resource('phui-profile-menu-css'); + $nav_classes[] = 'phui-profile-menu'; + } else if ($this->iconNav) { $nav_classes[] = 'phabricator-icon-nav'; + } else { + $nav_classes[] = 'phabricator-basic-nav'; } + $nav_id = null; $drag_id = null; $content_id = celerity_generate_unique_node_id(); diff --git a/webroot/rsrc/css/layout/phabricator-side-menu-view.css b/webroot/rsrc/css/layout/phabricator-side-menu-view.css index 7f0d2bc720..fe8ad588fc 100644 --- a/webroot/rsrc/css/layout/phabricator-side-menu-view.css +++ b/webroot/rsrc/css/layout/phabricator-side-menu-view.css @@ -2,7 +2,7 @@ * @provides phabricator-side-menu-view-css */ -.phabricator-side-menu .phui-list-item-view { +.phabricator-basic-nav .phabricator-side-menu .phui-list-item-view { display: block; white-space: nowrap; text-decoration: none; @@ -10,7 +10,7 @@ -webkit-font-smoothing: antialiased; } -.phabricator-side-menu .phui-list-item-href { +.phabricator-basic-nav .phabricator-side-menu .phui-list-item-href { display: block; padding: 6px 8px 6px 24px; color: {$darkbluetext}; @@ -18,7 +18,7 @@ border-bottom-right-radius: 3px; } -.phabricator-side-menu .phui-list-item-selected { +.phabricator-basic-nav .phabricator-side-menu .phui-list-item-selected { background-color: rgba(0,0,0,.05); border-left: 4px solid {$sky}; border-top-right-radius: 3px; @@ -30,16 +30,18 @@ background-color: rgba(0,0,0,.1); } -.device-desktop .phabricator-side-menu .phui-list-item-selected +.device-desktop .phabricator-basic-nav .phabricator-side-menu + .phui-list-item-selected a.phui-list-item-href:hover { background-color: rgba(0,0,0,.05); } -.phabricator-side-menu .phui-list-item-selected .phui-list-item-href { +.phabricator-basic-nav .phabricator-side-menu .phui-list-item-selected + .phui-list-item-href { padding-left: 20px; } -.phabricator-side-menu .phui-list-item-type-label { +.phabricator-basic-nav .phabricator-side-menu .phui-list-item-type-label { padding: 6px 8px 4px 12px; color: {$darkbluetext}; text-transform: uppercase; @@ -48,7 +50,8 @@ border-style: solid; } -.device-desktop .phabricator-side-menu a.phui-list-item-href:hover { +.device-desktop .phabricator-basic-nav .phabricator-side-menu + a.phui-list-item-href:hover { text-decoration: none; background-color: rgba(0,0,0,.07); } diff --git a/webroot/rsrc/css/phui/phui-profile-menu.css b/webroot/rsrc/css/phui/phui-profile-menu.css new file mode 100644 index 0000000000..c1ec040b17 --- /dev/null +++ b/webroot/rsrc/css/phui/phui-profile-menu.css @@ -0,0 +1,76 @@ +/** + * @provides phui-profile-menu-css + */ + +.phui-profile-menu .phabricator-side-menu { + background: {$menu.profile.background}; + box-shadow: inset -2px 0 2px rgba(0, 0, 0, 0.150); + width: 240px; +} + +.phui-profile-menu .phabricator-nav-local { + margin-top: 0; +} + +.device-desktop .phui-profile-menu .phabricator-nav-content { + margin-left: 240px; +} + +.device-desktop .phui-profile-menu + .phabricator-standard-page-footer { + margin-left: 256px; +} + +.phui-profile-menu .phabricator-side-menu .phui-list-item-view { + position: relative; +} + +.phui-profile-menu .phabricator-side-menu .phui-list-item-href { + display: block; + text-decoration: none; + padding: 12px 8px 12px 48px; + font-size: 15px; + -webkit-font-smoothing: antialiased; + color: {$menu.profile.text}; + line-height: 22px; + overflow: hidden; + text-overflow: ellipsis; +} + +.phui-profile-menu .phabricator-side-menu .phui-list-item-icon, +.phui-profile-menu .phabricator-side-menu .phui-icon-view { + position: absolute; + left: 13px; + top: 12px; + font-size: 20px; + width: 22px; + height: 22px; + line-height: 22px; + text-align: center; + color: {$menu.profile.icon}; + background-size: 100%; +} + +.phui-profile-menu .phabricator-side-menu + .phui-list-item-disabled + .phui-list-item-icon { + color: {$menu.profile.icon.disabled}; +} + +.phui-profile-menu .phabricator-side-menu .phui-icon-view { + border-radius: 3px; +} + +.device-desktop .phui-profile-menu .phabricator-side-menu + .phui-list-item-href:hover { + background-color: rgba(0, 0, 0, 0.075); + color: {$menu.profile.text.selected}; +} + +.phui-profile-menu .phabricator-side-menu .phui-list-item-selected + .phui-list-item-href, +.device-desktop .phui-profile-menu .phabricator-side-menu + .phui-list-item-selected + .phui-list-item-href:hover { + background-color: rgba(0, 0, 0, 0.150); + color: {$menu.profile.text.selected}; +} From c019f76283ce47a3a5bcf4e15ddd0792b33a1cf0 Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 13 Jan 2016 17:29:25 -0800 Subject: [PATCH 03/66] Make profile menu full-height Summary: Ref T10054. This makes the profile menu full-height. It uses two pieces of dark magic: - `calc()`, which allows you to do math in CSS. - The `vh` unit, which is CSS for "viewport height". Apparently this kind of stuff just works now? CSS got good at some point? Test Plan: - Page looks correct in Safari, Chrome, Firefox. - Checked `caniuse.com` for `vh` and `calc()`, saw they're supported? Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15017 --- resources/celerity/map.php | 6 +-- .../CelerityDefaultPostprocessor.php | 2 + src/view/layout/AphrontSideNavFilterView.php | 40 ++++++++++++++++++- src/view/page/PhabricatorStandardPageView.php | 17 ++++++-- webroot/rsrc/css/phui/phui-profile-menu.css | 34 ++++++++++------ 5 files changed, 78 insertions(+), 21 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 18ba9fcbc8..d442419f61 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => 'e9eca0fd', + 'core.pkg.css' => '97da8581', 'core.pkg.js' => '1f5f365a', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -143,7 +143,7 @@ return array( 'rsrc/css/phui/phui-object-item-list-view.css' => '26c30d3f', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', - 'rsrc/css/phui/phui-profile-menu.css' => '5a1644af', + 'rsrc/css/phui/phui-profile-menu.css' => '213398e6', 'rsrc/css/phui/phui-property-list-view.css' => '27b2849e', 'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591', 'rsrc/css/phui/phui-spacing.css' => '042804d6', @@ -822,7 +822,7 @@ return array( 'phui-object-item-list-view-css' => '26c30d3f', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', - 'phui-profile-menu-css' => '5a1644af', + 'phui-profile-menu-css' => '213398e6', 'phui-property-list-view-css' => '27b2849e', 'phui-remarkup-preview-css' => '1a8f2591', 'phui-spacing-css' => '042804d6', diff --git a/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php b/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php index 527318f7f9..6244e8554e 100644 --- a/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php +++ b/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php @@ -197,6 +197,8 @@ final class CelerityDefaultPostprocessor 'menu.profile.icon' => '#ffffff', 'menu.profile.icon.disabled' => '#b9bcc2', + 'menu.main.height' => '44px', + ); } diff --git a/src/view/layout/AphrontSideNavFilterView.php b/src/view/layout/AphrontSideNavFilterView.php index d3688ce93a..3d5eca0a2e 100644 --- a/src/view/layout/AphrontSideNavFilterView.php +++ b/src/view/layout/AphrontSideNavFilterView.php @@ -29,11 +29,13 @@ final class AphrontSideNavFilterView extends AphrontView { private $menuID; private $iconNav; private $isProfileMenu; + private $footer = array(); public function setMenuID($menu_id) { $this->menuID = $menu_id; return $this; } + public function getMenuID() { return $this->menuID; } @@ -187,6 +189,11 @@ final class AphrontSideNavFilterView extends AphrontView { return $this->selectedFilter; } + public function appendFooter($footer) { + $this->footer[] = $footer; + return $this; + } + public function render() { if ($this->menu->getItems()) { if (!$this->baseURI) { @@ -220,7 +227,7 @@ final class AphrontSideNavFilterView extends AphrontView { if ($this->getIsProfileMenu()) { require_celerity_resource('phui-profile-menu-css'); - $nav_classes[] = 'phui-profile-menu'; + // No class, we're going to put it on the shell instead. } else if ($this->iconNav) { $nav_classes[] = 'phabricator-icon-nav'; } else { @@ -301,7 +308,17 @@ final class AphrontSideNavFilterView extends AphrontView { $nav_classes = array_merge($nav_classes, $this->classes); - return phutil_tag( + $footer = $this->footer; + + if ($this->getIsProfileMenu()) { + $internal_footer = $footer; + $external_footer = null; + } else { + $internal_footer = null; + $external_footer = $footer; + } + + $menu = phutil_tag( 'div', array( 'class' => implode(' ', $nav_classes), @@ -319,8 +336,27 @@ final class AphrontSideNavFilterView extends AphrontView { array( $crumbs, $this->renderChildren(), + $internal_footer, )), )); + + if ($this->getIsProfileMenu()) { + $shell = phutil_tag( + 'div', + array( + 'class' => 'phui-navigation-shell phui-profile-menu', + ), + array( + $menu, + )); + } else { + $shell = array( + $menu, + $external_footer, + ); + } + + return $shell; } } diff --git a/src/view/page/PhabricatorStandardPageView.php b/src/view/page/PhabricatorStandardPageView.php index 3b1c38962b..b26ce6297b 100644 --- a/src/view/page/PhabricatorStandardPageView.php +++ b/src/view/page/PhabricatorStandardPageView.php @@ -478,6 +478,8 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView $body = parent::getBody(); + $footer = $this->renderFooter(); + $nav = $this->getNavigation(); if ($nav) { $crumbs = $this->getCrumbs(); @@ -485,18 +487,25 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView $nav->setCrumbs($crumbs); } $nav->appendChild($body); - $body = phutil_implode_html('', array($nav->render())); + $nav->appendFooter($footer); + $content = phutil_implode_html('', array($nav->render())); } else { + $contnet = array(); + $crumbs = $this->getCrumbs(); if ($crumbs) { - $body = phutil_implode_html('', array($crumbs, $body)); + $content[] = $crumbs; } + + $content[] = $body; + $content[] = $footer; + + $content = phutil_implode_html('', $content); } return array( ($console ? hsprintf('') : null), - $body, - $this->renderFooter(), + $content, ); } diff --git a/webroot/rsrc/css/phui/phui-profile-menu.css b/webroot/rsrc/css/phui/phui-profile-menu.css index c1ec040b17..ddd6b2b23c 100644 --- a/webroot/rsrc/css/phui/phui-profile-menu.css +++ b/webroot/rsrc/css/phui/phui-profile-menu.css @@ -2,24 +2,34 @@ * @provides phui-profile-menu-css */ +.device-desktop .phui-navigation-shell.phui-profile-menu { + display: table; + height: calc(100vh - {$menu.main.height}); +} + +.device-desktop .phui-profile-menu .phabricator-nav { + display: table-row; +} + +.device-desktop .phui-profile-menu .phabricator-nav-local { + display: table-cell; + position: relative; + vertical-align: top; + width: 240px; + margin-top: 0; +} + +.device-desktop .phui-profile-menu .phabricator-nav-content { + display: table-cell; + margin-left: 0; +} + .phui-profile-menu .phabricator-side-menu { background: {$menu.profile.background}; box-shadow: inset -2px 0 2px rgba(0, 0, 0, 0.150); width: 240px; } -.phui-profile-menu .phabricator-nav-local { - margin-top: 0; -} - -.device-desktop .phui-profile-menu .phabricator-nav-content { - margin-left: 240px; -} - -.device-desktop .phui-profile-menu + .phabricator-standard-page-footer { - margin-left: 256px; -} - .phui-profile-menu .phabricator-side-menu .phui-list-item-view { position: relative; } From 2a6b2dbbfdf13e941781f5fee8a91d9f3c016f1e Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 14 Jan 2016 05:59:25 -0800 Subject: [PATCH 04/66] Prepare Profile Panels for adoption in other applications Summary: Ref T10054. Take specialization off the objects and put it on Engine subclasses instead. One reason for this is that certain objects (like users) might have multiple different sets of panels in the future (e.g., their user profile and their home page). Test Plan: - No user-visible changes. - PanelEngine no longer has any hardcoded "project" stuff. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15018 --- src/__phutil_library_map__.php | 4 +- .../PhabricatorProjectController.php | 2 +- .../PhabricatorProjectPanelController.php | 2 +- .../PhabricatorProjectProfilePanelEngine.php | 51 +++++++++++++++++++ .../project/storage/PhabricatorProject.php | 46 +---------------- .../PhabricatorProfilePanelEditEngine.php | 3 +- .../engine/PhabricatorProfilePanelEngine.php | 21 ++++---- .../PhabricatorProfilePanelInterface.php | 7 --- .../PhabricatorLinkProfilePanel.php | 3 +- .../profilepanel/PhabricatorProfilePanel.php | 3 +- .../PhabricatorProfilePanelConfiguration.php | 5 +- 11 files changed, 71 insertions(+), 76 deletions(-) create mode 100644 src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php delete mode 100644 src/applications/search/interface/PhabricatorProfilePanelInterface.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 3f8d654711..70a164f785 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2836,7 +2836,6 @@ phutil_register_library_map(array( 'PhabricatorProfilePanelEditor' => 'applications/search/editor/PhabricatorProfilePanelEditor.php', 'PhabricatorProfilePanelEngine' => 'applications/search/engine/PhabricatorProfilePanelEngine.php', 'PhabricatorProfilePanelIconSet' => 'applications/search/profilepanel/PhabricatorProfilePanelIconSet.php', - 'PhabricatorProfilePanelInterface' => 'applications/search/interface/PhabricatorProfilePanelInterface.php', 'PhabricatorProfilePanelPHIDType' => 'applications/search/phidtype/PhabricatorProfilePanelPHIDType.php', 'PhabricatorProject' => 'applications/project/storage/PhabricatorProject.php', 'PhabricatorProjectAddHeraldAction' => 'applications/project/herald/PhabricatorProjectAddHeraldAction.php', @@ -2902,6 +2901,7 @@ phutil_register_library_map(array( 'PhabricatorProjectPHIDResolver' => 'applications/phid/resolver/PhabricatorProjectPHIDResolver.php', 'PhabricatorProjectPanelController' => 'applications/project/controller/PhabricatorProjectPanelController.php', 'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.php', + 'PhabricatorProjectProfilePanelEngine' => 'applications/project/engine/PhabricatorProjectProfilePanelEngine.php', 'PhabricatorProjectProjectHasMemberEdgeType' => 'applications/project/edge/PhabricatorProjectProjectHasMemberEdgeType.php', 'PhabricatorProjectProjectHasObjectEdgeType' => 'applications/project/edge/PhabricatorProjectProjectHasObjectEdgeType.php', 'PhabricatorProjectProjectPHIDType' => 'applications/project/phid/PhabricatorProjectProjectPHIDType.php', @@ -7214,7 +7214,6 @@ phutil_register_library_map(array( 'PhabricatorDestructibleInterface', 'PhabricatorFulltextInterface', 'PhabricatorConduitResultInterface', - 'PhabricatorProfilePanelInterface', ), 'PhabricatorProjectAddHeraldAction' => 'PhabricatorProjectHeraldAction', 'PhabricatorProjectApplication' => 'PhabricatorApplication', @@ -7289,6 +7288,7 @@ phutil_register_library_map(array( 'PhabricatorProjectPHIDResolver' => 'PhabricatorPHIDResolver', 'PhabricatorProjectPanelController' => 'PhabricatorProjectController', 'PhabricatorProjectProfileController' => 'PhabricatorProjectController', + 'PhabricatorProjectProfilePanelEngine' => 'PhabricatorProfilePanelEngine', 'PhabricatorProjectProjectHasMemberEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectProjectHasObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectProjectPHIDType' => 'PhabricatorPHIDType', diff --git a/src/applications/project/controller/PhabricatorProjectController.php b/src/applications/project/controller/PhabricatorProjectController.php index 9c6fa2f4e2..56f5774391 100644 --- a/src/applications/project/controller/PhabricatorProjectController.php +++ b/src/applications/project/controller/PhabricatorProjectController.php @@ -102,7 +102,7 @@ abstract class PhabricatorProjectController extends PhabricatorController { if ($project) { $viewer = $this->getViewer(); - $engine = id(new PhabricatorProfilePanelEngine()) + $engine = id(new PhabricatorProjectProfilePanelEngine()) ->setViewer($viewer) ->setProfileObject($project); diff --git a/src/applications/project/controller/PhabricatorProjectPanelController.php b/src/applications/project/controller/PhabricatorProjectPanelController.php index 02b16dcfb4..49ed00f34e 100644 --- a/src/applications/project/controller/PhabricatorProjectPanelController.php +++ b/src/applications/project/controller/PhabricatorProjectPanelController.php @@ -12,7 +12,7 @@ final class PhabricatorProjectPanelController $viewer = $this->getViewer(); $project = $this->getProject(); - return id(new PhabricatorProfilePanelEngine()) + return id(new PhabricatorProjectProfilePanelEngine()) ->setProfileObject($project) ->setController($this) ->buildResponse(); diff --git a/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php b/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php new file mode 100644 index 0000000000..d37caeecf8 --- /dev/null +++ b/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php @@ -0,0 +1,51 @@ +getProfileObject(); + $id = $project->getID(); + return "/project/{$id}/panel/{$path}"; + } + + protected function getBuiltinProfilePanels($object) { + $panels = array(); + + $panels[] = $this->newPanel() + ->setBuiltinKey(PhabricatorProject::PANEL_PROFILE) + ->setPanelKey(PhabricatorProjectDetailsProfilePanel::PANELKEY); + + $panels[] = $this->newPanel() + ->setBuiltinKey(PhabricatorProject::PANEL_WORKBOARD) + ->setPanelKey(PhabricatorProjectWorkboardProfilePanel::PANELKEY); + + // TODO: This is temporary. + $uri = urisprintf( + '/maniphest/?statuses=open()&projects=%s#R', + $object->getPHID()); + + $panels[] = $this->newPanel() + ->setBuiltinKey('tasks') + ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) + ->setPanelProperty('icon', 'maniphest') + ->setPanelProperty('name', pht('Open Tasks')) + ->setPanelProperty('uri', $uri); + + // TODO: This is temporary. + $id = $object->getID(); + $panels[] = $this->newPanel() + ->setBuiltinKey('feed') + ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) + ->setPanelProperty('icon', 'feed') + ->setPanelProperty('name', pht('Feed')) + ->setPanelProperty('uri', "/project/feed/{$id}/"); + + $panels[] = $this->newPanel() + ->setBuiltinKey(PhabricatorProject::PANEL_MEMBERS) + ->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY); + + return $panels; + } + +} diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php index 99fe366583..387882df2c 100644 --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -10,8 +10,7 @@ final class PhabricatorProject extends PhabricatorProjectDAO PhabricatorCustomFieldInterface, PhabricatorDestructibleInterface, PhabricatorFulltextInterface, - PhabricatorConduitResultInterface, - PhabricatorProfilePanelInterface { + PhabricatorConduitResultInterface { protected $name; protected $status = PhabricatorProjectStatus::STATUS_ACTIVE; @@ -651,47 +650,4 @@ final class PhabricatorProject extends PhabricatorProjectDAO return array(); } - -/* -( PhabricatorProfilePanelInterface )----------------------------------- */ - - - public function getBuiltinProfilePanels() { - $panels = array(); - - $panels[] = PhabricatorProfilePanelConfiguration::initializeNewBuiltin() - ->setBuiltinKey(self::PANEL_PROFILE) - ->setPanelKey(PhabricatorProjectDetailsProfilePanel::PANELKEY); - - $panels[] = PhabricatorProfilePanelConfiguration::initializeNewBuiltin() - ->setBuiltinKey(self::PANEL_WORKBOARD) - ->setPanelKey(PhabricatorProjectWorkboardProfilePanel::PANELKEY); - - // TODO: This is temporary. - $uri = urisprintf( - '/maniphest/?statuses=open()&projects=%s#R', - $this->getPHID()); - - $panels[] = PhabricatorProfilePanelConfiguration::initializeNewBuiltin() - ->setBuiltinKey('tasks') - ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) - ->setPanelProperty('icon', 'maniphest') - ->setPanelProperty('name', pht('Open Tasks')) - ->setPanelProperty('uri', $uri); - - // TODO: This is temporary. - $id = $this->getID(); - $panels[] = PhabricatorProfilePanelConfiguration::initializeNewBuiltin() - ->setBuiltinKey('feed') - ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) - ->setPanelProperty('icon', 'feed') - ->setPanelProperty('name', pht('Feed')) - ->setPanelProperty('uri', "/project/feed/{$id}/"); - - $panels[] = PhabricatorProfilePanelConfiguration::initializeNewBuiltin() - ->setBuiltinKey(self::PANEL_MEMBERS) - ->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY); - - return $panels; - } - } diff --git a/src/applications/search/editor/PhabricatorProfilePanelEditEngine.php b/src/applications/search/editor/PhabricatorProfilePanelEditEngine.php index 7713a97f7c..3a2f725719 100644 --- a/src/applications/search/editor/PhabricatorProfilePanelEditEngine.php +++ b/src/applications/search/editor/PhabricatorProfilePanelEditEngine.php @@ -23,8 +23,7 @@ final class PhabricatorProfilePanelEditEngine return $this->panelEngine; } - public function setProfileObject( - PhabricatorProfilePanelInterface $profile_object) { + public function setProfileObject($profile_object) { $this->profileObject = $profile_object; return $this; } diff --git a/src/applications/search/engine/PhabricatorProfilePanelEngine.php b/src/applications/search/engine/PhabricatorProfilePanelEngine.php index 40e95a4acc..15fee9437a 100644 --- a/src/applications/search/engine/PhabricatorProfilePanelEngine.php +++ b/src/applications/search/engine/PhabricatorProfilePanelEngine.php @@ -1,6 +1,6 @@ viewer; } - public function setProfileObject( - PhabricatorProfilePanelInterface $profile_object) { + public function setProfileObject($profile_object) { $this->profileObject = $profile_object; return $this; } @@ -35,6 +34,8 @@ final class PhabricatorProfilePanelEngine extends Phobject { return $this->controller; } + abstract protected function getPanelURI($path); + public function buildResponse() { $controller = $this->getController(); @@ -132,7 +133,7 @@ final class PhabricatorProfilePanelEngine extends Phobject { public function buildNavigation() { $nav = id(new AphrontSideNavFilterView()) ->setIsProfileMenu(true) - ->setBaseURI(new PhutilURI('/project/')); + ->setBaseURI(new PhutilURI($this->getPanelURI(''))); $panels = $this->getPanels(); @@ -225,7 +226,7 @@ final class PhabricatorProfilePanelEngine extends Phobject { private function loadBuiltinProfilePanels() { $object = $this->getProfileObject(); - $builtins = $object->getBuiltinProfilePanels(); + $builtins = $this->getBuiltinProfilePanels($object); $panels = PhabricatorProfilePanel::getAllPanels(); @@ -310,12 +311,6 @@ final class PhabricatorProfilePanelEngine extends Phobject { return $this->getPanelURI('configure/'); } - private function getPanelURI($path) { - $project = $this->getProfileObject(); - $id = $project->getID(); - return "/project/{$id}/panel/{$path}"; - } - private function buildPanelReorderContent(array $panels) { $viewer = $this->getViewer(); $object = $this->getProfileObject(); @@ -646,4 +641,8 @@ final class PhabricatorProfilePanelEngine extends Phobject { ->addSubmitButton(pht('Save Changes')); } + protected function newPanel() { + return PhabricatorProfilePanelConfiguration::initializeNewBuiltin(); + } + } diff --git a/src/applications/search/interface/PhabricatorProfilePanelInterface.php b/src/applications/search/interface/PhabricatorProfilePanelInterface.php deleted file mode 100644 index 34d68458a8..0000000000 --- a/src/applications/search/interface/PhabricatorProfilePanelInterface.php +++ /dev/null @@ -1,7 +0,0 @@ -assertAttached($this->panel); } - public function attachProfileObject( - PhabricatorProfilePanelInterface $profile_object) { + public function attachProfileObject($profile_object) { $this->profileObject = $profile_object; return $this; } From da5d01e542051eb971db9384ec690eaba200242d Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 14 Jan 2016 06:47:06 -0800 Subject: [PATCH 05/66] Convert user profiles to Profile Panels Summary: Ref T10054. Primary goal is to be able to remove IconNav from the codebase. I've made these non-editable so users can't customize them yet. We //might// want administrators to customize these globally instead? In any case, we avoid a bunch of product questions by just locking these down for now. Test Plan: {F1061348} Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15020 --- src/__phutil_library_map__.php | 12 +- .../PhabricatorPeopleApplication.php | 10 +- .../PhabricatorPeopleCalendarController.php | 39 ++- .../PhabricatorPeopleController.php | 45 --- .../PhabricatorPeopleProfileController.php | 264 +++--------------- ...PhabricatorPeopleProfileEditController.php | 36 +-- ...bricatorPeopleProfilePictureController.php | 41 ++- ...PhabricatorPeopleProfileViewController.php | 252 +++++++++++++++++ .../PhabricatorPeopleProfilePanelEngine.php | 96 +++++++ .../PhabricatorPeopleDetailsProfilePanel.php | 59 ++++ .../engine/PhabricatorProfilePanelEngine.php | 18 +- .../PhabricatorProfilePanelIconSet.php | 15 + 12 files changed, 535 insertions(+), 352 deletions(-) create mode 100644 src/applications/people/controller/PhabricatorPeopleProfileViewController.php create mode 100644 src/applications/people/engine/PhabricatorPeopleProfilePanelEngine.php create mode 100644 src/applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 70a164f785..114afb9ec4 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2723,6 +2723,7 @@ phutil_register_library_map(array( 'PhabricatorPeopleCreateController' => 'applications/people/controller/PhabricatorPeopleCreateController.php', 'PhabricatorPeopleDatasource' => 'applications/people/typeahead/PhabricatorPeopleDatasource.php', 'PhabricatorPeopleDeleteController' => 'applications/people/controller/PhabricatorPeopleDeleteController.php', + 'PhabricatorPeopleDetailsProfilePanel' => 'applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php', 'PhabricatorPeopleDisableController' => 'applications/people/controller/PhabricatorPeopleDisableController.php', 'PhabricatorPeopleEmpowerController' => 'applications/people/controller/PhabricatorPeopleEmpowerController.php', 'PhabricatorPeopleExternalPHIDType' => 'applications/people/phid/PhabricatorPeopleExternalPHIDType.php', @@ -2741,7 +2742,9 @@ phutil_register_library_map(array( 'PhabricatorPeopleOwnerDatasource' => 'applications/people/typeahead/PhabricatorPeopleOwnerDatasource.php', 'PhabricatorPeopleProfileController' => 'applications/people/controller/PhabricatorPeopleProfileController.php', 'PhabricatorPeopleProfileEditController' => 'applications/people/controller/PhabricatorPeopleProfileEditController.php', + 'PhabricatorPeopleProfilePanelEngine' => 'applications/people/engine/PhabricatorPeopleProfilePanelEngine.php', 'PhabricatorPeopleProfilePictureController' => 'applications/people/controller/PhabricatorPeopleProfilePictureController.php', + 'PhabricatorPeopleProfileViewController' => 'applications/people/controller/PhabricatorPeopleProfileViewController.php', 'PhabricatorPeopleQuery' => 'applications/people/query/PhabricatorPeopleQuery.php', 'PhabricatorPeopleRenameController' => 'applications/people/controller/PhabricatorPeopleRenameController.php', 'PhabricatorPeopleSearchEngine' => 'applications/people/query/PhabricatorPeopleSearchEngine.php', @@ -7060,11 +7063,12 @@ phutil_register_library_map(array( 'PhabricatorPeopleAnyOwnerDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPeopleApplication' => 'PhabricatorApplication', 'PhabricatorPeopleApproveController' => 'PhabricatorPeopleController', - 'PhabricatorPeopleCalendarController' => 'PhabricatorPeopleController', + 'PhabricatorPeopleCalendarController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleController' => 'PhabricatorController', 'PhabricatorPeopleCreateController' => 'PhabricatorPeopleController', 'PhabricatorPeopleDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPeopleDeleteController' => 'PhabricatorPeopleController', + 'PhabricatorPeopleDetailsProfilePanel' => 'PhabricatorProfilePanel', 'PhabricatorPeopleDisableController' => 'PhabricatorPeopleController', 'PhabricatorPeopleEmpowerController' => 'PhabricatorPeopleController', 'PhabricatorPeopleExternalPHIDType' => 'PhabricatorPHIDType', @@ -7082,8 +7086,10 @@ phutil_register_library_map(array( 'PhabricatorPeopleNoOwnerDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPeopleOwnerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController', - 'PhabricatorPeopleProfileEditController' => 'PhabricatorPeopleController', - 'PhabricatorPeopleProfilePictureController' => 'PhabricatorPeopleController', + 'PhabricatorPeopleProfileEditController' => 'PhabricatorPeopleProfileController', + 'PhabricatorPeopleProfilePanelEngine' => 'PhabricatorProfilePanelEngine', + 'PhabricatorPeopleProfilePictureController' => 'PhabricatorPeopleProfileController', + 'PhabricatorPeopleProfileViewController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPeopleRenameController' => 'PhabricatorPeopleController', 'PhabricatorPeopleSearchEngine' => 'PhabricatorApplicationSearchEngine', diff --git a/src/applications/people/application/PhabricatorPeopleApplication.php b/src/applications/people/application/PhabricatorPeopleApplication.php index 45599907c8..48598ba838 100644 --- a/src/applications/people/application/PhabricatorPeopleApplication.php +++ b/src/applications/people/application/PhabricatorPeopleApplication.php @@ -63,10 +63,12 @@ final class PhabricatorPeopleApplication extends PhabricatorApplication { 'picture/(?P[1-9]\d*)/' => 'PhabricatorPeopleProfilePictureController', ), - '/p/(?P[\w._-]+)/' - => 'PhabricatorPeopleProfileController', - '/p/(?P[\w._-]+)/calendar/' - => 'PhabricatorPeopleCalendarController', + '/p/(?P[\w._-]+)/' => array( + '' => 'PhabricatorPeopleProfileViewController', + 'panel/' + => $this->getPanelRouting('PhabricatorPeopleProfilePanelController'), + 'calendar/' => 'PhabricatorPeopleCalendarController', + ), ); } diff --git a/src/applications/people/controller/PhabricatorPeopleCalendarController.php b/src/applications/people/controller/PhabricatorPeopleCalendarController.php index a5e64199c5..ed3d557fb8 100644 --- a/src/applications/people/controller/PhabricatorPeopleCalendarController.php +++ b/src/applications/people/controller/PhabricatorPeopleCalendarController.php @@ -1,34 +1,27 @@ getViewer(); + $username = $request->getURIData('username'); - public function willProcessRequest(array $data) { - $this->username = idx($data, 'username'); - } - - public function processRequest() { - $viewer = $this->getRequest()->getUser(); $user = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) - ->withUsernames(array($this->username)) + ->withUsernames(array($username)) ->needProfileImage(true) ->executeOne(); - if (!$user) { return new Aphront404Response(); } + $this->setUser($user); + $picture = $user->getProfileImageURI(); $now = time(); @@ -89,16 +82,16 @@ final class PhabricatorPeopleCalendarController $month_view->addEvent($event); } - $name = $user->getUsername(); + $nav = $this->getProfileMenu(); + $nav->selectFilter('calendar'); - $nav = $this->buildIconNavView($user); - $nav->selectFilter("{$name}/calendar/"); - $nav->appendChild($month_view); + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb(pht('Calendar')); - return $this->buildApplicationPage( - $nav, - array( - 'title' => pht('Calendar'), - )); + return $this->newPage() + ->setTitle(pht('Calendar')) + ->setNavigation($nav) + ->setCrumbs($crumbs) + ->appendChild($month_view); } } diff --git a/src/applications/people/controller/PhabricatorPeopleController.php b/src/applications/people/controller/PhabricatorPeopleController.php index b293c0f72c..e3b60eff2b 100644 --- a/src/applications/people/controller/PhabricatorPeopleController.php +++ b/src/applications/people/controller/PhabricatorPeopleController.php @@ -44,49 +44,4 @@ abstract class PhabricatorPeopleController extends PhabricatorController { return $this->buildSideNavView(true)->getMenu(); } - public function buildIconNavView(PhabricatorUser $user) { - $viewer = $this->getViewer(); - $picture = $user->getProfileImageURI(); - $name = $user->getUsername(); - - $nav = new AphrontSideNavFilterView(); - $nav->setIconNav(true); - $nav->setBaseURI(new PhutilURI('/p/')); - $nav->addIcon("{$name}/", $name, null, $picture); - - $class = 'PhabricatorCalendarApplication'; - if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { - $nav->addIcon( - "{$name}/calendar/", pht('Calendar'), 'fa-calendar'); - } - - $class = 'PhabricatorManiphestApplication'; - if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { - $phid = $user->getPHID(); - $view_uri = sprintf( - '/maniphest/?statuses=open()&assigned=%s#R', - $phid); - $nav->addIcon( - 'maniphest', pht('Open Tasks'), 'fa-anchor', null, $view_uri); - } - - $class = 'PhabricatorDifferentialApplication'; - if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { - $username = phutil_escape_uri($name); - $view_uri = '/differential/?authors='.$username; - $nav->addIcon( - 'differential', pht('Revisions'), 'fa-cog', null, $view_uri); - } - - $class = 'PhabricatorAuditApplication'; - if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { - $username = phutil_escape_uri($name); - $view_uri = '/audit/?authors='.$username; - $nav->addIcon( - 'audit', pht('Commits'), 'fa-code', null, $view_uri); - } - - return $nav; - } - } diff --git a/src/applications/people/controller/PhabricatorPeopleProfileController.php b/src/applications/people/controller/PhabricatorPeopleProfileController.php index a4378f380c..74705f9809 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileController.php @@ -1,257 +1,63 @@ username = idx($data, 'username'); + public function setUser(PhabricatorUser $user) { + $this->user = $user; + return $this; } - public function processRequest() { - $viewer = $this->getRequest()->getUser(); - - $user = id(new PhabricatorPeopleQuery()) - ->setViewer($viewer) - ->withUsernames(array($this->username)) - ->needBadges(true) - ->needProfileImage(true) - ->needAvailability(true) - ->executeOne(); - if (!$user) { - return new Aphront404Response(); - } - - $profile = $user->loadUserProfile(); - $username = phutil_escape_uri($user->getUserName()); - - $picture = $user->getProfileImageURI(); - - $header = id(new PHUIHeaderView()) - ->setHeader($user->getFullName()) - ->setSubheader($profile->getTitle()) - ->setImage($picture); - - $actions = id(new PhabricatorActionListView()) - ->setObject($user) - ->setUser($viewer); - - $can_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - $user, - PhabricatorPolicyCapability::CAN_EDIT); - - $actions->addAction( - id(new PhabricatorActionView()) - ->setIcon('fa-pencil') - ->setName(pht('Edit Profile')) - ->setHref($this->getApplicationURI('editprofile/'.$user->getID().'/')) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit)); - - $actions->addAction( - id(new PhabricatorActionView()) - ->setIcon('fa-picture-o') - ->setName(pht('Edit Profile Picture')) - ->setHref($this->getApplicationURI('picture/'.$user->getID().'/')) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit)); - - $class = 'PhabricatorConpherenceApplication'; - if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { - $href = id(new PhutilURI('/conpherence/new/')) - ->setQueryParam('participant', $user->getPHID()); - - $can_send = $viewer->isLoggedIn(); - - $actions->addAction( - id(new PhabricatorActionView()) - ->setIcon('fa-comments') - ->setName(pht('Send Message')) - ->setWorkflow(true) - ->setDisabled(!$can_send) - ->setHref($href)); - } - - if ($viewer->getIsAdmin()) { - $actions->addAction( - id(new PhabricatorActionView()) - ->setIcon('fa-wrench') - ->setName(pht('Edit Settings')) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit) - ->setHref('/settings/'.$user->getID().'/')); - - if ($user->getIsAdmin()) { - $empower_icon = 'fa-arrow-circle-o-down'; - $empower_name = pht('Remove Administrator'); - } else { - $empower_icon = 'fa-arrow-circle-o-up'; - $empower_name = pht('Make Administrator'); - } - - $actions->addAction( - id(new PhabricatorActionView()) - ->setIcon($empower_icon) - ->setName($empower_name) - ->setDisabled(($user->getPHID() == $viewer->getPHID())) - ->setWorkflow(true) - ->setHref($this->getApplicationURI('empower/'.$user->getID().'/'))); - - $actions->addAction( - id(new PhabricatorActionView()) - ->setIcon('fa-tag') - ->setName(pht('Change Username')) - ->setWorkflow(true) - ->setHref($this->getApplicationURI('rename/'.$user->getID().'/'))); - - if ($user->getIsDisabled()) { - $disable_icon = 'fa-check-circle-o'; - $disable_name = pht('Enable User'); - } else { - $disable_icon = 'fa-ban'; - $disable_name = pht('Disable User'); - } - - $actions->addAction( - id(new PhabricatorActionView()) - ->setIcon($disable_icon) - ->setName($disable_name) - ->setDisabled(($user->getPHID() == $viewer->getPHID())) - ->setWorkflow(true) - ->setHref($this->getApplicationURI('disable/'.$user->getID().'/'))); - - $actions->addAction( - id(new PhabricatorActionView()) - ->setIcon('fa-times') - ->setName(pht('Delete User')) - ->setDisabled(($user->getPHID() == $viewer->getPHID())) - ->setWorkflow(true) - ->setHref($this->getApplicationURI('delete/'.$user->getID().'/'))); - - $can_welcome = $user->canEstablishWebSessions(); - - $actions->addAction( - id(new PhabricatorActionView()) - ->setIcon('fa-envelope') - ->setName(pht('Send Welcome Email')) - ->setWorkflow(true) - ->setDisabled(!$can_welcome) - ->setHref($this->getApplicationURI('welcome/'.$user->getID().'/'))); - } - - $properties = $this->buildPropertyView($user, $actions); - $name = $user->getUsername(); - - $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addTextCrumb($name); - - $object_box = id(new PHUIObjectBoxView()) - ->setHeader($header) - ->addPropertyList($properties); - - $feed = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Recent Activity')) - ->appendChild($this->buildPeopleFeed($user, $viewer)); - - $badges = $this->buildBadgesView($user); - - $nav = $this->buildIconNavView($user); - $nav->selectFilter("{$name}/"); - $nav->appendChild($object_box); - $nav->appendChild($badges); - $nav->appendChild($feed); - - return $this->buildApplicationPage( - $nav, - array( - 'title' => $user->getUsername(), - )); + public function getUser() { + return $this->user; } - private function buildPropertyView( - PhabricatorUser $user, - PhabricatorActionListView $actions) { + public function buildApplicationMenu() { + $menu = $this->newApplicationMenu(); - $viewer = $this->getRequest()->getUser(); - $view = id(new PHUIPropertyListView()) - ->setUser($viewer) - ->setObject($user) - ->setActionList($actions); + $profile_menu = $this->getProfileMenu(); + if ($profile_menu) { + $menu->setProfileMenu($profile_menu); + } - $field_list = PhabricatorCustomField::getObjectFields( - $user, - PhabricatorCustomField::ROLE_VIEW); - $field_list->appendFieldsToPropertyList($user, $viewer, $view); - - return $view; + return $menu; } - private function buildBadgesView( - PhabricatorUser $user) { + protected function getProfileMenu() { + if (!$this->profileMenu) { + $user = $this->getUser(); + if ($user) { + $viewer = $this->getViewer(); - $viewer = $this->getViewer(); - $class = 'PhabricatorBadgesApplication'; - $box = null; - - if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { - $badge_phids = $user->getBadgePHIDs(); - if ($badge_phids) { - $badges = id(new PhabricatorBadgesQuery()) + $engine = id(new PhabricatorPeopleProfilePanelEngine()) ->setViewer($viewer) - ->withPHIDs($badge_phids) - ->withStatuses(array(PhabricatorBadgesBadge::STATUS_ACTIVE)) - ->execute(); + ->setProfileObject($user); - $flex = new PHUIBadgeBoxView(); - foreach ($badges as $badge) { - $item = id(new PHUIBadgeView()) - ->setIcon($badge->getIcon()) - ->setHeader($badge->getName()) - ->setSubhead($badge->getFlavor()) - ->setQuality($badge->getQuality()); - $flex->addItem($item); - } - - $box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Badges')) - ->appendChild($flex); - } + $this->profileMenu = $engine->buildNavigation(); } - return $box; + } + + return $this->profileMenu; } - private function buildPeopleFeed( - PhabricatorUser $user, - $viewer) { + protected function buildApplicationCrumbs() { + $crumbs = parent::buildApplicationCrumbs(); - $query = new PhabricatorFeedQuery(); - $query->setFilterPHIDs( - array( - $user->getPHID(), - )); - $query->setLimit(100); - $query->setViewer($viewer); - $stories = $query->execute(); - - $builder = new PhabricatorFeedBuilder($stories); - $builder->setUser($viewer); - $builder->setShowHovercards(true); - $builder->setNoDataString(pht('To begin on such a grand journey, '. - 'requires but just a single step.')); - $view = $builder->buildView(); - - return phutil_tag_div('phabricator-project-feed', $view->render()); + $user = $this->getUser(); + if ($user) { + $crumbs->addTextCrumb( + $user->getUsername(), + urisprintf('/p/%s/', $user->getUsername())); + } + return $crumbs; } } diff --git a/src/applications/people/controller/PhabricatorPeopleProfileEditController.php b/src/applications/people/controller/PhabricatorPeopleProfileEditController.php index f53278b536..b438093be7 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileEditController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileEditController.php @@ -1,25 +1,15 @@ id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $id = $request->getURIData('id'); $user = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->needProfileImage(true) ->requireCapabilities( array( @@ -31,6 +21,8 @@ final class PhabricatorPeopleProfileEditController return new Aphront404Response(); } + $this->setUser($user); + $profile_uri = '/p/'.$user->getUsername().'/'; $field_list = PhabricatorCustomField::getObjectFields( @@ -91,14 +83,12 @@ final class PhabricatorPeopleProfileEditController $form_box->setInfoView($note); } - $nav = $this->buildIconNavView($user); - $nav->selectFilter('/'); - $nav->appendChild($form_box); + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb(pht('Edit Profile')); - return $this->buildApplicationPage( - $nav, - array( - 'title' => $title, - )); + return $this->newPage() + ->setTitle($title) + ->setCrumbs($crumbs) + ->appendChild($form_box); } } diff --git a/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php b/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php index 9dabd50f66..0d9554e264 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php @@ -1,25 +1,15 @@ id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $id = $request->getURIData('id'); $user = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->needProfileImage(true) ->requireCapabilities( array( @@ -31,6 +21,8 @@ final class PhabricatorPeopleProfilePictureController return new Aphront404Response(); } + $this->setUser($user); + $profile_uri = '/p/'.$user->getUsername().'/'; $supported_formats = PhabricatorFile::getTransformableImageFormats(); @@ -256,15 +248,16 @@ final class PhabricatorPeopleProfilePictureController ->setHeaderText(pht('Upload New Picture')) ->setForm($upload_form); - $nav = $this->buildIconNavView($user); - $nav->selectFilter('/'); - $nav->appendChild($form_box); - $nav->appendChild($upload_box); + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb(pht('Edit Profile Picture')); - return $this->buildApplicationPage( - $nav, - array( - 'title' => $title, - )); + return $this->newPage() + ->setTitle($title) + ->setCrumbs($crumbs) + ->appendChild( + array( + $form_box, + $upload_box, + )); } } diff --git a/src/applications/people/controller/PhabricatorPeopleProfileViewController.php b/src/applications/people/controller/PhabricatorPeopleProfileViewController.php new file mode 100644 index 0000000000..a515dda959 --- /dev/null +++ b/src/applications/people/controller/PhabricatorPeopleProfileViewController.php @@ -0,0 +1,252 @@ +getViewer(); + $username = $request->getURIData('username'); + + $user = id(new PhabricatorPeopleQuery()) + ->setViewer($viewer) + ->withUsernames(array($username)) + ->needBadges(true) + ->needProfileImage(true) + ->needAvailability(true) + ->executeOne(); + if (!$user) { + return new Aphront404Response(); + } + + $this->setUser($user); + + $profile = $user->loadUserProfile(); + $picture = $user->getProfileImageURI(); + + $header = id(new PHUIHeaderView()) + ->setHeader($user->getFullName()) + ->setSubheader($profile->getTitle()) + ->setImage($picture); + + $actions = id(new PhabricatorActionListView()) + ->setObject($user) + ->setUser($viewer); + + $can_edit = PhabricatorPolicyFilter::hasCapability( + $viewer, + $user, + PhabricatorPolicyCapability::CAN_EDIT); + + $actions->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-pencil') + ->setName(pht('Edit Profile')) + ->setHref($this->getApplicationURI('editprofile/'.$user->getID().'/')) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit)); + + $actions->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-picture-o') + ->setName(pht('Edit Profile Picture')) + ->setHref($this->getApplicationURI('picture/'.$user->getID().'/')) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit)); + + $class = 'PhabricatorConpherenceApplication'; + if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { + $href = id(new PhutilURI('/conpherence/new/')) + ->setQueryParam('participant', $user->getPHID()); + + $can_send = $viewer->isLoggedIn(); + + $actions->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-comments') + ->setName(pht('Send Message')) + ->setWorkflow(true) + ->setDisabled(!$can_send) + ->setHref($href)); + } + + if ($viewer->getIsAdmin()) { + $actions->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-wrench') + ->setName(pht('Edit Settings')) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit) + ->setHref('/settings/'.$user->getID().'/')); + + if ($user->getIsAdmin()) { + $empower_icon = 'fa-arrow-circle-o-down'; + $empower_name = pht('Remove Administrator'); + } else { + $empower_icon = 'fa-arrow-circle-o-up'; + $empower_name = pht('Make Administrator'); + } + + $actions->addAction( + id(new PhabricatorActionView()) + ->setIcon($empower_icon) + ->setName($empower_name) + ->setDisabled(($user->getPHID() == $viewer->getPHID())) + ->setWorkflow(true) + ->setHref($this->getApplicationURI('empower/'.$user->getID().'/'))); + + $actions->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-tag') + ->setName(pht('Change Username')) + ->setWorkflow(true) + ->setHref($this->getApplicationURI('rename/'.$user->getID().'/'))); + + if ($user->getIsDisabled()) { + $disable_icon = 'fa-check-circle-o'; + $disable_name = pht('Enable User'); + } else { + $disable_icon = 'fa-ban'; + $disable_name = pht('Disable User'); + } + + $actions->addAction( + id(new PhabricatorActionView()) + ->setIcon($disable_icon) + ->setName($disable_name) + ->setDisabled(($user->getPHID() == $viewer->getPHID())) + ->setWorkflow(true) + ->setHref($this->getApplicationURI('disable/'.$user->getID().'/'))); + + $actions->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-times') + ->setName(pht('Delete User')) + ->setDisabled(($user->getPHID() == $viewer->getPHID())) + ->setWorkflow(true) + ->setHref($this->getApplicationURI('delete/'.$user->getID().'/'))); + + $can_welcome = $user->canEstablishWebSessions(); + + $actions->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-envelope') + ->setName(pht('Send Welcome Email')) + ->setWorkflow(true) + ->setDisabled(!$can_welcome) + ->setHref($this->getApplicationURI('welcome/'.$user->getID().'/'))); + } + + $properties = $this->buildPropertyView($user, $actions); + $name = $user->getUsername(); + + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb($name); + + $object_box = id(new PHUIObjectBoxView()) + ->setHeader($header) + ->addPropertyList($properties); + + $feed = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Recent Activity')) + ->appendChild($this->buildPeopleFeed($user, $viewer)); + + $badges = $this->buildBadgesView($user); + + $nav = $this->getProfileMenu(); + $nav->selectFilter(PhabricatorPeopleProfilePanelEngine::PANEL_PROFILE); + + $crumbs = $this->buildApplicationCrumbs(); + + return $this->newPage() + ->setTitle($user->getUsername()) + ->setNavigation($nav) + ->setCrumbs($crumbs) + ->appendChild( + array( + $object_box, + $badges, + $feed, + )); + } + + private function buildPropertyView( + PhabricatorUser $user, + PhabricatorActionListView $actions) { + + $viewer = $this->getRequest()->getUser(); + $view = id(new PHUIPropertyListView()) + ->setUser($viewer) + ->setObject($user) + ->setActionList($actions); + + $field_list = PhabricatorCustomField::getObjectFields( + $user, + PhabricatorCustomField::ROLE_VIEW); + $field_list->appendFieldsToPropertyList($user, $viewer, $view); + + return $view; + } + + private function buildBadgesView( + PhabricatorUser $user) { + + $viewer = $this->getViewer(); + $class = 'PhabricatorBadgesApplication'; + $box = null; + + if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { + $badge_phids = $user->getBadgePHIDs(); + if ($badge_phids) { + $badges = id(new PhabricatorBadgesQuery()) + ->setViewer($viewer) + ->withPHIDs($badge_phids) + ->withStatuses(array(PhabricatorBadgesBadge::STATUS_ACTIVE)) + ->execute(); + + $flex = new PHUIBadgeBoxView(); + foreach ($badges as $badge) { + $item = id(new PHUIBadgeView()) + ->setIcon($badge->getIcon()) + ->setHeader($badge->getName()) + ->setSubhead($badge->getFlavor()) + ->setQuality($badge->getQuality()); + $flex->addItem($item); + } + + $box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Badges')) + ->appendChild($flex); + } + } + return $box; + } + + private function buildPeopleFeed( + PhabricatorUser $user, + $viewer) { + + $query = new PhabricatorFeedQuery(); + $query->setFilterPHIDs( + array( + $user->getPHID(), + )); + $query->setLimit(100); + $query->setViewer($viewer); + $stories = $query->execute(); + + $builder = new PhabricatorFeedBuilder($stories); + $builder->setUser($viewer); + $builder->setShowHovercards(true); + $builder->setNoDataString(pht('To begin on such a grand journey, '. + 'requires but just a single step.')); + $view = $builder->buildView(); + + return phutil_tag_div('phabricator-project-feed', $view->render()); + + } + +} diff --git a/src/applications/people/engine/PhabricatorPeopleProfilePanelEngine.php b/src/applications/people/engine/PhabricatorPeopleProfilePanelEngine.php new file mode 100644 index 0000000000..60b11ffebb --- /dev/null +++ b/src/applications/people/engine/PhabricatorPeopleProfilePanelEngine.php @@ -0,0 +1,96 @@ +getProfileObject(); + $username = $user->getUsername(); + $username = phutil_escape_uri($username); + return "/p/{$username}/panel/{$path}"; + } + + protected function getBuiltinProfilePanels($object) { + $viewer = $this->getViewer(); + + $panels = array(); + + $panels[] = $this->newPanel() + ->setBuiltinKey(self::PANEL_PROFILE) + ->setPanelKey(PhabricatorPeopleDetailsProfilePanel::PANELKEY); + + // TODO: Convert this into a proper panel type. + $have_calendar = PhabricatorApplication::isClassInstalledForViewer( + 'PhabricatorCalendarApplication', + $viewer); + if ($have_calendar) { + $uri = urisprintf( + '/p/%s/calendar/', + $object->getUsername()); + + $panels[] = $this->newPanel() + ->setBuiltinKey('calendar') + ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) + ->setPanelProperty('icon', 'calendar') + ->setPanelProperty('name', pht('Calendar')) + ->setPanelProperty('uri', $uri); + } + + $have_maniphest = PhabricatorApplication::isClassInstalledForViewer( + 'PhabricatorManiphestApplication', + $viewer); + if ($have_maniphest) { + $uri = urisprintf( + '/maniphest/?statuses=open()&assigned=%s#R', + $object->getPHID()); + + $panels[] = $this->newPanel() + ->setBuiltinKey('tasks') + ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) + ->setPanelProperty('icon', 'maniphest') + ->setPanelProperty('name', pht('Open Tasks')) + ->setPanelProperty('uri', $uri); + } + + $have_differential = PhabricatorApplication::isClassInstalledForViewer( + 'PhabricatorDifferentialApplication', + $viewer); + if ($have_differential) { + $uri = urisprintf( + '/differential/?authors=%s#R', + $object->getPHID()); + + $panels[] = $this->newPanel() + ->setBuiltinKey('revisions') + ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) + ->setPanelProperty('icon', 'differential') + ->setPanelProperty('name', pht('Revisions')) + ->setPanelProperty('uri', $uri); + } + + $have_diffusion = PhabricatorApplication::isClassInstalledForViewer( + 'PhabricatorDiffusionApplication', + $viewer); + if ($have_diffusion) { + $uri = urisprintf( + '/audit/?authors=%s#R', + $object->getPHID()); + + $panels[] = $this->newPanel() + ->setBuiltinKey('commits') + ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) + ->setPanelProperty('icon', 'diffusion') + ->setPanelProperty('name', pht('Commits')) + ->setPanelProperty('uri', $uri); + } + + return $panels; + } + +} diff --git a/src/applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php b/src/applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php new file mode 100644 index 0000000000..83d45dfb9d --- /dev/null +++ b/src/applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php @@ -0,0 +1,59 @@ +getPanelProperty('name'); + + if (strlen($name)) { + return $name; + } + + return $this->getDefaultName(); + } + + public function buildEditEngineFields( + PhabricatorProfilePanelConfiguration $config) { + return array( + id(new PhabricatorTextEditField()) + ->setKey('name') + ->setLabel(pht('Name')) + ->setPlaceholder($this->getDefaultName()) + ->setValue($config->getPanelProperty('name')), + ); + } + + protected function newNavigationMenuItems( + PhabricatorProfilePanelConfiguration $config) { + + $user = $config->getProfileObject(); + + $picture = $user->getProfileImageURI(); + $name = $user->getUsername(); + $href = urisprintf( + '/p/%s/', + $user->getUsername()); + + $item = $this->newItem() + ->setHref($href) + ->setName($name) + ->setProfileImage($picture); + + return array( + $item, + ); + } + +} diff --git a/src/applications/search/engine/PhabricatorProfilePanelEngine.php b/src/applications/search/engine/PhabricatorProfilePanelEngine.php index 15fee9437a..1cf03b9bac 100644 --- a/src/applications/search/engine/PhabricatorProfilePanelEngine.php +++ b/src/applications/search/engine/PhabricatorProfilePanelEngine.php @@ -36,6 +36,10 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { abstract protected function getPanelURI($path); + protected function isPanelEngineConfigurable() { + return PhabricatorEnv::getEnvConfig('phabricator.show-prototypes'); + } + public function buildResponse() { $controller = $this->getController(); @@ -45,6 +49,18 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $request = $controller->getRequest(); $panel_action = $request->getURIData('panelAction'); + + // If the engine is not configurable, don't respond to any of the editing + // or configuration routes. + if (!$this->isPanelEngineConfigurable()) { + switch ($panel_action) { + case 'view': + break; + default: + return new Aphront404Response(); + } + } + $panel_id = $request->getURIData('panelID'); $panel_list = $this->loadPanels(); @@ -286,7 +302,7 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { } private function newConfigureMenuItem() { - if (!PhabricatorEnv::getEnvConfig('phabricator.show-prototypes')) { + if (!$this->isPanelEngineConfigurable()) { return null; } diff --git a/src/applications/search/profilepanel/PhabricatorProfilePanelIconSet.php b/src/applications/search/profilepanel/PhabricatorProfilePanelIconSet.php index 50efc217e0..bc3b15a7cf 100644 --- a/src/applications/search/profilepanel/PhabricatorProfilePanelIconSet.php +++ b/src/applications/search/profilepanel/PhabricatorProfilePanelIconSet.php @@ -36,6 +36,21 @@ final class PhabricatorProfilePanelIconSet 'icon' => 'fa-comments', 'name' => pht('Conpherence'), ), + array( + 'key' => 'differential', + 'icon' => 'fa-cog', + 'name' => pht('Differential'), + ), + array( + 'key' => 'diffusion', + 'icon' => 'fa-code', + 'name' => pht('Diffusion'), + ), + array( + 'key' => 'calendar', + 'icon' => 'fa-calendar', + 'name' => pht('Calendar'), + ), array( 'key' => 'create', 'icon' => 'fa-plus', From f4c8cdb39a14406a795a2204bc6bfe1473acce83 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 14 Jan 2016 07:17:10 -0800 Subject: [PATCH 06/66] Remove icon nav entirely Summary: Ref T10054. People, projects, and instances no longer use icon nav, so we can get rid of it in favor of profile menus. Test Plan: Grepped for everything, looked through workboards/profiles again. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15022 --- resources/celerity/map.php | 18 +++--- src/view/layout/AphrontSideNavFilterView.php | 29 --------- src/view/phui/PHUIListItemView.php | 1 - .../application/base/standard-page-view.css | 4 -- .../css/layout/phabricator-side-menu-view.css | 62 ------------------- webroot/rsrc/css/phui/phui-profile-menu.css | 1 + webroot/rsrc/css/phui/phui-workboard-view.css | 12 +--- 7 files changed, 11 insertions(+), 116 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index d442419f61..825e892eb5 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => '97da8581', + 'core.pkg.css' => '2a7bdb75', 'core.pkg.js' => '1f5f365a', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -36,7 +36,7 @@ return array( 'rsrc/css/application/base/notification-menu.css' => 'f31c0bde', 'rsrc/css/application/base/phabricator-application-launch-view.css' => '95351601', 'rsrc/css/application/base/phui-theme.css' => '6b451f24', - 'rsrc/css/application/base/standard-page-view.css' => '3c99cdf4', + 'rsrc/css/application/base/standard-page-view.css' => '7b0d68d8', 'rsrc/css/application/chatlog/chatlog.css' => 'd295b020', 'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4', 'rsrc/css/application/config/config-options.css' => '0ede4c9b', @@ -112,7 +112,7 @@ return array( 'rsrc/css/font/phui-font-icon-base.css' => 'ecbbb4c2', 'rsrc/css/layout/phabricator-filetree-view.css' => 'fccf9f82', 'rsrc/css/layout/phabricator-hovercard-view.css' => '1239cd52', - 'rsrc/css/layout/phabricator-side-menu-view.css' => '1ddcb82f', + 'rsrc/css/layout/phabricator-side-menu-view.css' => '3a3d9f41', 'rsrc/css/layout/phabricator-source-code-view.css' => 'cbeef983', 'rsrc/css/phui/calendar/phui-calendar-day.css' => 'd1cf6f93', 'rsrc/css/phui/calendar/phui-calendar-list.css' => 'c1c7f338', @@ -143,7 +143,7 @@ return array( 'rsrc/css/phui/phui-object-item-list-view.css' => '26c30d3f', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', - 'rsrc/css/phui/phui-profile-menu.css' => '213398e6', + 'rsrc/css/phui/phui-profile-menu.css' => '6123de4e', 'rsrc/css/phui/phui-property-list-view.css' => '27b2849e', 'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591', 'rsrc/css/phui/phui-spacing.css' => '042804d6', @@ -152,7 +152,7 @@ return array( 'rsrc/css/phui/phui-text.css' => 'cf019f54', 'rsrc/css/phui/phui-timeline-view.css' => '2efceff8', 'rsrc/css/phui/phui-two-column-view.css' => '39ecafb1', - 'rsrc/css/phui/phui-workboard-view.css' => '24fe2a66', + 'rsrc/css/phui/phui-workboard-view.css' => '95a54f74', 'rsrc/css/phui/phui-workpanel-view.css' => 'adec7699', 'rsrc/css/sprite-login.css' => '60e8560e', 'rsrc/css/sprite-main-header.css' => 'f07bbb87', @@ -764,10 +764,10 @@ return array( 'phabricator-remarkup-css' => 'b748dc17', 'phabricator-search-results-css' => '7dea472c', 'phabricator-shaped-request' => '7cbe244b', - 'phabricator-side-menu-view-css' => '1ddcb82f', + 'phabricator-side-menu-view-css' => '3a3d9f41', 'phabricator-slowvote-css' => 'da0afb1b', 'phabricator-source-code-view-css' => 'cbeef983', - 'phabricator-standard-page-view' => '3c99cdf4', + 'phabricator-standard-page-view' => '7b0d68d8', 'phabricator-textareautils' => '9e54692d', 'phabricator-title' => 'df5e11d2', 'phabricator-tooltip' => '1d298e3a', @@ -822,7 +822,7 @@ return array( 'phui-object-item-list-view-css' => '26c30d3f', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', - 'phui-profile-menu-css' => '213398e6', + 'phui-profile-menu-css' => '6123de4e', 'phui-property-list-view-css' => '27b2849e', 'phui-remarkup-preview-css' => '1a8f2591', 'phui-spacing-css' => '042804d6', @@ -832,7 +832,7 @@ return array( 'phui-theme-css' => '6b451f24', 'phui-timeline-view-css' => '2efceff8', 'phui-two-column-view-css' => '39ecafb1', - 'phui-workboard-view-css' => '24fe2a66', + 'phui-workboard-view-css' => '95a54f74', 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', diff --git a/src/view/layout/AphrontSideNavFilterView.php b/src/view/layout/AphrontSideNavFilterView.php index 3d5eca0a2e..5040f81efc 100644 --- a/src/view/layout/AphrontSideNavFilterView.php +++ b/src/view/layout/AphrontSideNavFilterView.php @@ -27,7 +27,6 @@ final class AphrontSideNavFilterView extends AphrontView { private $crumbs; private $classes = array(); private $menuID; - private $iconNav; private $isProfileMenu; private $footer = array(); @@ -67,11 +66,6 @@ final class AphrontSideNavFilterView extends AphrontView { return $this->isProfileMenu; } - public function setIconNav($nav) { - $this->iconNav = $nav; - return $this; - } - public function setActive($active) { $this->active = $active; return $this; @@ -105,26 +99,6 @@ final class AphrontSideNavFilterView extends AphrontView { $key, $name, $uri, PHUIListItemView::TYPE_LINK); } - public function addIcon($key, $name, $icon, $image = null, $uri = null) { - if (!$uri) { - $href = clone $this->baseURI; - $href->setPath(rtrim($href->getPath().$key, '/').'/'); - $href = (string)$href; - } else { - $href = $uri; - } - - $item = id(new PHUIListItemView()) - ->setKey($key) - ->setRenderNameAsTooltip(true) - ->setType(PHUIListItemView::TYPE_ICON_NAV) - ->setIcon($icon) - ->setHref($href) - ->setName($name) - ->setProfileImage($image); - return $this->addMenuItem($item); - } - public function addButton($key, $name, $uri = null) { return $this->addThing( $key, $name, $uri, PHUIListItemView::TYPE_BUTTON); @@ -228,13 +202,10 @@ final class AphrontSideNavFilterView extends AphrontView { if ($this->getIsProfileMenu()) { require_celerity_resource('phui-profile-menu-css'); // No class, we're going to put it on the shell instead. - } else if ($this->iconNav) { - $nav_classes[] = 'phabricator-icon-nav'; } else { $nav_classes[] = 'phabricator-basic-nav'; } - $nav_id = null; $drag_id = null; $content_id = celerity_generate_unique_node_id(); diff --git a/src/view/phui/PHUIListItemView.php b/src/view/phui/PHUIListItemView.php index e877049840..45c2b56128 100644 --- a/src/view/phui/PHUIListItemView.php +++ b/src/view/phui/PHUIListItemView.php @@ -9,7 +9,6 @@ final class PHUIListItemView extends AphrontTagView { const TYPE_CUSTOM = 'type-custom'; const TYPE_DIVIDER = 'type-divider'; const TYPE_ICON = 'type-icon'; - const TYPE_ICON_NAV = 'type-icon-nav'; const STATUS_WARN = 'phui-list-item-warn'; const STATUS_FAIL = 'phui-list-item-fail'; diff --git a/webroot/rsrc/css/application/base/standard-page-view.css b/webroot/rsrc/css/application/base/standard-page-view.css index 9670ddd7ae..830554db3e 100644 --- a/webroot/rsrc/css/application/base/standard-page-view.css +++ b/webroot/rsrc/css/application/base/standard-page-view.css @@ -37,10 +37,6 @@ margin-left: 221px; } -.device-desktop div.phabricator-icon-nav + .phabricator-standard-page-footer { - margin-left: 58px; -} - .device .phabricator-side-menu-home + .phabricator-standard-page-footer { display: none; } diff --git a/webroot/rsrc/css/layout/phabricator-side-menu-view.css b/webroot/rsrc/css/layout/phabricator-side-menu-view.css index fe8ad588fc..5b425c2a5f 100644 --- a/webroot/rsrc/css/layout/phabricator-side-menu-view.css +++ b/webroot/rsrc/css/layout/phabricator-side-menu-view.css @@ -26,10 +26,6 @@ font-weight: bold; } -.phabricator-icon-nav .phabricator-side-menu .phui-list-item-selected { - background-color: rgba(0,0,0,.1); -} - .device-desktop .phabricator-basic-nav .phabricator-side-menu .phui-list-item-selected a.phui-list-item-href:hover { @@ -55,61 +51,3 @@ text-decoration: none; background-color: rgba(0,0,0,.07); } - -.device-desktop .phabricator-icon-nav a.phui-list-item-href:hover - .phui-list-item-icon { - color: {$darkbluetext}; - } - -.device-desktop .phabricator-icon-nav .phabricator-nav-local { - width: 40px; - margin-top: 16px; - border-color: {$lightblueborder}; - border-width: 1px 1px 1px 0; - border-style: solid; - background-color: #fff; - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} - -.device-desktop .phabricator-icon-nav .phabricator-nav-content { - margin-left: 41px; -} - -.phabricator-icon-nav .phabricator-side-menu .phui-list-item-href { - height: 40px; - width: 40px; - padding: 0; -} - -.phabricator-icon-nav .phabricator-side-menu .phui-list-item-icon { - font-size: 20px; - width: 40px; - line-height: 38px; - text-align: center; - vertical-align: bottom; - text-shadow: {$whitetextshadow}; - color: {$blue}; -} - -.phabricator-icon-nav .phabricator-side-menu .phui-list-item-icon.grey { - color: {$lightgreyborder}; -} - -.phabricator-icon-nav .phabricator-side-menu .phui-list-item-selected { - border: none; -} - -.phabricator-icon-nav .phabricator-side-menu .phui-list-item-selected - .phui-icon-view { - color: {$darkbluetext}; -} - -.phabricator-icon-nav .phui-icon-view.phuihead-small { - height: 24px; - width: 24px; - border: 1px solid #fff; - background-size: 24px; - display: inline-block; - margin: 7px; -} diff --git a/webroot/rsrc/css/phui/phui-profile-menu.css b/webroot/rsrc/css/phui/phui-profile-menu.css index ddd6b2b23c..d8059b3851 100644 --- a/webroot/rsrc/css/phui/phui-profile-menu.css +++ b/webroot/rsrc/css/phui/phui-profile-menu.css @@ -4,6 +4,7 @@ .device-desktop .phui-navigation-shell.phui-profile-menu { display: table; + width: 100%; height: calc(100vh - {$menu.main.height}); } diff --git a/webroot/rsrc/css/phui/phui-workboard-view.css b/webroot/rsrc/css/phui/phui-workboard-view.css index e6817c6254..38126fa786 100644 --- a/webroot/rsrc/css/phui/phui-workboard-view.css +++ b/webroot/rsrc/css/phui/phui-workboard-view.css @@ -38,7 +38,7 @@ } .device-desktop .project-board-wrapper .phui-workboard-view-shadow { - left: 53px; + left: 253px; } .device-desktop .phui-workboard-view .aphront-multi-column-fixed @@ -86,13 +86,3 @@ margin: 8px 0 2px 0; padding: 0; } - -.device-desktop .phabricator-icon-nav.project-board-nav - .phabricator-nav-local { - margin-top: 64px; -} - -.device-desktop .phabricator-icon-nav.project-board-nav - .phabricator-nav-content { - margin: 0; -} From 22aebab1c18cc76b50a311e7265250cc9c7b02d8 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 14 Jan 2016 14:34:21 -0800 Subject: [PATCH 07/66] Add a visual divider element to profile menus Summary: Ref T10054. Test Plan: {F1061529} Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15024 --- resources/celerity/map.php | 6 +-- src/__phutil_library_map__.php | 2 + .../PhabricatorDividerProfilePanel.php | 48 +++++++++++++++++++ webroot/rsrc/css/phui/phui-profile-menu.css | 6 +++ 4 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/applications/search/profilepanel/PhabricatorDividerProfilePanel.php diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 825e892eb5..f08c2ddd96 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => '2a7bdb75', + 'core.pkg.css' => '30316566', 'core.pkg.js' => '1f5f365a', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -143,7 +143,7 @@ return array( 'rsrc/css/phui/phui-object-item-list-view.css' => '26c30d3f', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', - 'rsrc/css/phui/phui-profile-menu.css' => '6123de4e', + 'rsrc/css/phui/phui-profile-menu.css' => '05546270', 'rsrc/css/phui/phui-property-list-view.css' => '27b2849e', 'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591', 'rsrc/css/phui/phui-spacing.css' => '042804d6', @@ -822,7 +822,7 @@ return array( 'phui-object-item-list-view-css' => '26c30d3f', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', - 'phui-profile-menu-css' => '6123de4e', + 'phui-profile-menu-css' => '05546270', 'phui-property-list-view-css' => '27b2849e', 'phui-remarkup-preview-css' => '1a8f2591', 'phui-spacing-css' => '042804d6', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 114afb9ec4..31ad0d1200 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2154,6 +2154,7 @@ phutil_register_library_map(array( 'PhabricatorDisabledUserController' => 'applications/auth/controller/PhabricatorDisabledUserController.php', 'PhabricatorDisplayPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorDisplayPreferencesSettingsPanel.php', 'PhabricatorDisqusAuthProvider' => 'applications/auth/provider/PhabricatorDisqusAuthProvider.php', + 'PhabricatorDividerProfilePanel' => 'applications/search/profilepanel/PhabricatorDividerProfilePanel.php', 'PhabricatorDivinerApplication' => 'applications/diviner/application/PhabricatorDivinerApplication.php', 'PhabricatorDoorkeeperApplication' => 'applications/doorkeeper/application/PhabricatorDoorkeeperApplication.php', 'PhabricatorDraft' => 'applications/draft/storage/PhabricatorDraft.php', @@ -6412,6 +6413,7 @@ phutil_register_library_map(array( 'PhabricatorDisabledUserController' => 'PhabricatorAuthController', 'PhabricatorDisplayPreferencesSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorDisqusAuthProvider' => 'PhabricatorOAuth2AuthProvider', + 'PhabricatorDividerProfilePanel' => 'PhabricatorProfilePanel', 'PhabricatorDivinerApplication' => 'PhabricatorApplication', 'PhabricatorDoorkeeperApplication' => 'PhabricatorApplication', 'PhabricatorDraft' => 'PhabricatorDraftDAO', diff --git a/src/applications/search/profilepanel/PhabricatorDividerProfilePanel.php b/src/applications/search/profilepanel/PhabricatorDividerProfilePanel.php new file mode 100644 index 0000000000..1458cac56c --- /dev/null +++ b/src/applications/search/profilepanel/PhabricatorDividerProfilePanel.php @@ -0,0 +1,48 @@ +setValue( + pht( + 'This is a visual divider which you can use to separate '. + 'sections in the menu. It does not have any configurable '. + 'options.')), + ); + } + + protected function newNavigationMenuItems( + PhabricatorProfilePanelConfiguration $config) { + + $item = $this->newItem() + ->addClass('phui-divider'); + + return array( + $item, + ); + } + +} diff --git a/webroot/rsrc/css/phui/phui-profile-menu.css b/webroot/rsrc/css/phui/phui-profile-menu.css index d8059b3851..ed874954f9 100644 --- a/webroot/rsrc/css/phui/phui-profile-menu.css +++ b/webroot/rsrc/css/phui/phui-profile-menu.css @@ -85,3 +85,9 @@ background-color: rgba(0, 0, 0, 0.150); color: {$menu.profile.text.selected}; } + + +.phui-profile-menu .phabricator-side-menu .phui-divider { + margin: 4px 0; + border-bottom: 1px solid rgba(0, 0, 0, 0.200); +} From 77447fc945835109ea94baed22bbf8e2e9f9c9bc Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 14 Jan 2016 15:29:21 -0800 Subject: [PATCH 08/66] Add a motivational profile menu panel Summary: Motivate your employees with inspirational quotes. A new quote every day! Test Plan: So inspirational. Reviewers: chad Reviewed By: chad Differential Revision: https://secure.phabricator.com/D15026 --- resources/celerity/map.php | 6 +- src/__phutil_library_map__.php | 2 + .../PhabricatorMotivatorProfilePanel.php | 151 ++++++++++++++++++ webroot/rsrc/css/phui/phui-profile-menu.css | 16 +- 4 files changed, 171 insertions(+), 4 deletions(-) create mode 100644 src/applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php diff --git a/resources/celerity/map.php b/resources/celerity/map.php index f08c2ddd96..44902c07da 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => '30316566', + 'core.pkg.css' => '3a97c8b9', 'core.pkg.js' => '1f5f365a', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -143,7 +143,7 @@ return array( 'rsrc/css/phui/phui-object-item-list-view.css' => '26c30d3f', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', - 'rsrc/css/phui/phui-profile-menu.css' => '05546270', + 'rsrc/css/phui/phui-profile-menu.css' => 'e8030bb3', 'rsrc/css/phui/phui-property-list-view.css' => '27b2849e', 'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591', 'rsrc/css/phui/phui-spacing.css' => '042804d6', @@ -822,7 +822,7 @@ return array( 'phui-object-item-list-view-css' => '26c30d3f', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', - 'phui-profile-menu-css' => '05546270', + 'phui-profile-menu-css' => 'e8030bb3', 'phui-property-list-view-css' => '27b2849e', 'phui-remarkup-preview-css' => '1a8f2591', 'phui-spacing-css' => '042804d6', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 31ad0d1200..c7dd1287bd 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2552,6 +2552,7 @@ phutil_register_library_map(array( 'PhabricatorMetaMTASendGridReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTASendGridReceiveController.php', 'PhabricatorMetaMTAWorker' => 'applications/metamta/PhabricatorMetaMTAWorker.php', 'PhabricatorMetronomicTriggerClock' => 'infrastructure/daemon/workers/clock/PhabricatorMetronomicTriggerClock.php', + 'PhabricatorMotivatorProfilePanel' => 'applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php', 'PhabricatorMultiColumnUIExample' => 'applications/uiexample/examples/PhabricatorMultiColumnUIExample.php', 'PhabricatorMultiFactorSettingsPanel' => 'applications/settings/panel/PhabricatorMultiFactorSettingsPanel.php', 'PhabricatorMultimeterApplication' => 'applications/multimeter/application/PhabricatorMultimeterApplication.php', @@ -6863,6 +6864,7 @@ phutil_register_library_map(array( 'PhabricatorMetaMTASendGridReceiveController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAWorker' => 'PhabricatorWorker', 'PhabricatorMetronomicTriggerClock' => 'PhabricatorTriggerClock', + 'PhabricatorMotivatorProfilePanel' => 'PhabricatorProfilePanel', 'PhabricatorMultiColumnUIExample' => 'PhabricatorUIExample', 'PhabricatorMultiFactorSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorMultimeterApplication' => 'PhabricatorApplication', diff --git a/src/applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php b/src/applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php new file mode 100644 index 0000000000..bee5843f75 --- /dev/null +++ b/src/applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php @@ -0,0 +1,151 @@ +getOptions(); + $name = idx($options, $config->getPanelProperty('source')); + if ($name !== null) { + return pht('Motivator: %s', $name); + } else { + return pht('Motivator'); + } + } + + public function buildEditEngineFields( + PhabricatorProfilePanelConfiguration $config) { + return array( + id(new PhabricatorInstructionsEditField()) + ->setValue( + pht( + 'Motivate your team with inspirational quotes from great minds. '. + 'This panel shows a new quote every day.')), + id(new PhabricatorSelectEditField()) + ->setKey('source') + ->setLabel(pht('Source')) + ->setOptions($this->getOptions()), + ); + } + + private function getOptions() { + return array( + 'catfacts' => pht('Cat Facts'), + ); + } + + protected function newNavigationMenuItems( + PhabricatorProfilePanelConfiguration $config) { + + $source = $config->getPanelProperty('source'); + + switch ($source) { + case 'catfacts': + default: + $facts = $this->getCatFacts(); + break; + } + + $fact = $this->selectFact($facts); + + switch ($source) { + case 'catfacts': + default: + $fact = array( + id(new PHUIIconView())->setIconFont('fa-paw'), + ' ', + $fact, + ); + break; + } + + $fact = phutil_tag( + 'div', + array( + 'class' => 'phui-motivator', + ), + $fact); + + $item = $this->newItem() + ->appendChild($fact); + + return array( + $item, + ); + } + + private function getCatFacts() { + return array( + pht('Cats purr when they are happy, upset, or asleep.'), + pht('The first cats evolved on the savanah about 8,000 years ago.'), + pht( + 'Cats have a tail, two feet, between one and three ears, and two '. + 'other feet.'), + pht('Cats use their keen sense of smell to avoid feeling empathy.'), + pht('The first cats evolved in swamps about 65 years ago.'), + pht( + 'You can tell how warm a cat is by examining the coloration: cooler '. + 'areas are darker.'), + pht( + 'Cat tails are flexible because they contain thousands of tiny '. + 'bones.'), + pht( + 'A cattail is a wetland plant with an appearance that resembles '. + 'the tail of a cat.'), + pht( + 'Cats must eat a diet rich in fish to replace the tiny bones in '. + 'their tails.'), + pht('Cats are stealthy predators and nearly invisible to radar.'), + pht( + 'Cats use a special type of magnetism to help them land on their '. + 'feet.'), + pht( + 'A cat can run seven times faster than a human, but only for a '. + 'short distance.'), + pht( + 'The largest recorded cat was nearly 11 inches long from nose to '. + 'tail.'), + pht( + 'Not all cats can retract their claws, but most of them can.'), + pht( + 'In the wild, cats and racooons sometimes hunt together in packs.'), + pht( + 'The Spanish word for cat is "cato". The biggest cat is called '. + '"el cato".'), + pht( + 'The Japanese word for cat is "kome", which is also the word for '. + 'rice. Japanese cats love to eat rice, so the two are synonymous.'), + ); + } + + private function selectFact(array $facts) { + // This is a simple pseudorandom number generator that avoids touching + // srand(), because it would seed it to a highly predictable value. It + // selects a new fact every day. + + $seed = ((int)date('Y') * 366) + (int)date('z'); + for ($ii = 0; $ii < 32; $ii++) { + $seed = ((1664525 * $seed) + 1013904223) % (1 << 31); + } + + return $facts[$seed % count($facts)]; + } + + +} diff --git a/webroot/rsrc/css/phui/phui-profile-menu.css b/webroot/rsrc/css/phui/phui-profile-menu.css index ed874954f9..6616876077 100644 --- a/webroot/rsrc/css/phui/phui-profile-menu.css +++ b/webroot/rsrc/css/phui/phui-profile-menu.css @@ -48,7 +48,8 @@ } .phui-profile-menu .phabricator-side-menu .phui-list-item-icon, -.phui-profile-menu .phabricator-side-menu .phui-icon-view { +.phui-profile-menu .phabricator-side-menu + .phui-list-item-href .phui-icon-view { position: absolute; left: 13px; top: 12px; @@ -91,3 +92,16 @@ margin: 4px 0; border-bottom: 1px solid rgba(0, 0, 0, 0.200); } + +.phui-profile-menu .phabricator-side-menu .phui-motivator { + white-space: normal; + padding: 18px 15px; + font-size: 12px; + color: {$menu.profile.text}; +} + +.phui-profile-menu .phabricator-side-menu .phui-motivator .phui-icon-view { + position: static; + font-size: 12px; + color: {$menu.profile.text}; +} From 3c19004f9f4196c46a2e551add600070b55e4576 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 15 Jan 2016 09:30:29 -0800 Subject: [PATCH 09/66] Fix blur and sort behavior for autocomplete Summary: Ref T10163. - If you click a result, we get a blur before your click hits, and deactivate before the click can work. Instead, wait before responding to blur. - Use the standard sort handler which puts unixnames over human names. Also use the standard filter which deals with disabled users not matching unless they're the only match. Test Plan: - Clicked a result, got a replacement. - Named myself "dog dog", typed "@dog", user "@dog" was now first match despite me being "@admin". - Used normal typeaheads to make sure I didn't break sort handler. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10163 Differential Revision: https://secure.phabricator.com/D15031 --- resources/celerity/map.php | 46 +++---- webroot/rsrc/js/core/Prefab.js | 151 +++++++++++---------- webroot/rsrc/js/phuix/PHUIXAutocomplete.js | 13 +- 3 files changed, 110 insertions(+), 100 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 44902c07da..00959be9cf 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -8,7 +8,7 @@ return array( 'names' => array( 'core.pkg.css' => '3a97c8b9', - 'core.pkg.js' => '1f5f365a', + 'core.pkg.js' => '5813273d', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', 'differential.pkg.js' => 'f83532f8', @@ -458,7 +458,7 @@ return array( 'rsrc/js/core/KeyboardShortcutManager.js' => 'c1700f6f', 'rsrc/js/core/MultirowRowManager.js' => 'b5d57730', 'rsrc/js/core/Notification.js' => 'ccf1cbf8', - 'rsrc/js/core/Prefab.js' => 'a15cbd65', + 'rsrc/js/core/Prefab.js' => 'e67df814', 'rsrc/js/core/ShapedRequest.js' => '7cbe244b', 'rsrc/js/core/TextAreaUtils.js' => '9e54692d', 'rsrc/js/core/Title.js' => 'df5e11d2', @@ -507,7 +507,7 @@ return array( 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', - 'rsrc/js/phuix/PHUIXAutocomplete.js' => 'c5f5e42f', + 'rsrc/js/phuix/PHUIXAutocomplete.js' => '2b735afc', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 'rsrc/js/phuix/PHUIXFormControl.js' => '8fba1997', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', @@ -760,7 +760,7 @@ return array( 'phabricator-notification-menu-css' => 'f31c0bde', 'phabricator-object-selector-css' => '85ee8ce6', 'phabricator-phtize' => 'd254d646', - 'phabricator-prefab' => 'a15cbd65', + 'phabricator-prefab' => 'e67df814', 'phabricator-remarkup-css' => 'b748dc17', 'phabricator-search-results-css' => '7dea472c', 'phabricator-shaped-request' => '7cbe244b', @@ -836,7 +836,7 @@ return array( 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', - 'phuix-autocomplete' => 'c5f5e42f', + 'phuix-autocomplete' => '2b735afc', 'phuix-dropdown-menu' => 'bd4c8dca', 'phuix-form-control-view' => '8fba1997', 'phuix-icon-view' => 'bff6884b', @@ -1023,6 +1023,12 @@ return array( 'javelin-install', 'javelin-util', ), + '2b735afc' => array( + 'javelin-install', + 'javelin-dom', + 'phuix-icon-view', + 'phabricator-prefab', + ), '2b8de964' => array( 'javelin-install', 'javelin-util', @@ -1589,18 +1595,6 @@ return array( 'javelin-dom', 'javelin-reactor-dom', ), - 'a15cbd65' => array( - 'javelin-install', - 'javelin-util', - 'javelin-dom', - 'javelin-typeahead', - 'javelin-tokenizer', - 'javelin-typeahead-preloaded-source', - 'javelin-typeahead-ondemand-source', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-util', - ), 'a16ec1c6' => array( 'javelin-install', 'javelin-dom', @@ -1799,12 +1793,6 @@ return array( 'javelin-dom', 'javelin-vector', ), - 'c5f5e42f' => array( - 'javelin-install', - 'javelin-dom', - 'phuix-icon-view', - 'phabricator-prefab', - ), 'c6f720ff' => array( 'javelin-install', 'javelin-dom', @@ -1977,6 +1965,18 @@ return array( 'javelin-workflow', 'javelin-magical-init', ), + 'e67df814' => array( + 'javelin-install', + 'javelin-util', + 'javelin-dom', + 'javelin-typeahead', + 'javelin-tokenizer', + 'javelin-typeahead-preloaded-source', + 'javelin-typeahead-ondemand-source', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-util', + ), 'e6e25838' => array( 'javelin-install', ), diff --git a/webroot/rsrc/js/core/Prefab.js b/webroot/rsrc/js/core/Prefab.js index 5f5c210273..5948958c8f 100644 --- a/webroot/rsrc/js/core/Prefab.js +++ b/webroot/rsrc/js/core/Prefab.js @@ -99,81 +99,8 @@ JX.install('Prefab', { datasource = new JX.TypeaheadPreloadedSource(config.src); } - // Sort results so that the viewing user always comes up first; after - // that, prefer unixname matches to realname matches. - - var sort_handler = function(value, list, cmp) { - var priority_hits = {}; - var self_hits = {}; - - var tokens = this.tokenize(value); - - for (var ii = 0; ii < list.length; ii++) { - var item = list[ii]; - - for (var jj = 0; jj < tokens.length; jj++) { - if (item.name.indexOf(tokens[jj]) === 0) { - priority_hits[item.id] = true; - } - } - - if (!item.priority) { - continue; - } - - if (config.username && item.priority == config.username) { - self_hits[item.id] = true; - } - - for (var hh = 0; hh < tokens.length; hh++) { - if (item.priority.substr(0, tokens[hh].length) == tokens[hh]) { - priority_hits[item.id] = true; - } - } - } - - list.sort(function(u, v) { - if (self_hits[u.id] != self_hits[v.id]) { - return self_hits[v.id] ? 1 : -1; - } - - // If one result is open and one is closed, show the open result - // first. The "!" tricks here are becaused closed values are display - // strings, so the value is either `null` or some truthy string. If - // we compare the values directly, we'll apply this rule to two - // objects which are both closed but for different reasons, like - // "Archived" and "Disabled". - - var u_open = !u.closed; - var v_open = !v.closed; - - if (u_open != v_open) { - if (u_open) { - return -1; - } else { - return 1; - } - } - - if (priority_hits[u.id] != priority_hits[v.id]) { - return priority_hits[v.id] ? 1 : -1; - } - - // Sort users ahead of other result types. - if (u.priorityType != v.priorityType) { - if (u.priorityType == 'user') { - return -1; - } - if (v.priorityType == 'user') { - return 1; - } - } - - return cmp(u, v); - }); - }; - - datasource.setSortHandler(JX.bind(datasource, sort_handler)); + datasource.setSortHandler( + JX.bind(datasource, JX.Prefab.sortHandler, config)); datasource.setFilterHandler(JX.Prefab.filterClosedResults); datasource.setTransformer(JX.Prefab.transformDatasourceResults); @@ -251,6 +178,80 @@ JX.install('Prefab', { }; }, + sortHandler: function(config, value, list, cmp) { + // Sort results so that the viewing user always comes up first; after + // that, prefer unixname matches to realname matches. + var priority_hits = {}; + var self_hits = {}; + + var tokens = this.tokenize(value); + + for (var ii = 0; ii < list.length; ii++) { + var item = list[ii]; + + for (var jj = 0; jj < tokens.length; jj++) { + if (item.name.indexOf(tokens[jj]) === 0) { + priority_hits[item.id] = true; + } + } + + if (!item.priority) { + continue; + } + + if (config.username && item.priority == config.username) { + self_hits[item.id] = true; + } + + for (var hh = 0; hh < tokens.length; hh++) { + if (item.priority.substr(0, tokens[hh].length) == tokens[hh]) { + priority_hits[item.id] = true; + } + } + } + + list.sort(function(u, v) { + if (self_hits[u.id] != self_hits[v.id]) { + return self_hits[v.id] ? 1 : -1; + } + + // If one result is open and one is closed, show the open result + // first. The "!" tricks here are becaused closed values are display + // strings, so the value is either `null` or some truthy string. If + // we compare the values directly, we'll apply this rule to two + // objects which are both closed but for different reasons, like + // "Archived" and "Disabled". + + var u_open = !u.closed; + var v_open = !v.closed; + + if (u_open != v_open) { + if (u_open) { + return -1; + } else { + return 1; + } + } + + if (priority_hits[u.id] != priority_hits[v.id]) { + return priority_hits[v.id] ? 1 : -1; + } + + // Sort users ahead of other result types. + if (u.priorityType != v.priorityType) { + if (u.priorityType == 'user') { + return -1; + } + if (v.priorityType == 'user') { + return 1; + } + } + + return cmp(u, v); + }); + }, + + /** * Filter callback for tokenizers and typeaheads which filters out closed * or disabled objects unless they are the only options. diff --git a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js index e2148113fd..67e8b4a32a 100644 --- a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js +++ b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js @@ -60,8 +60,14 @@ JX.install('PHUIXAutocomplete', { var device = JX.bind(this, this._ondevice); JX.Stratcom.listen('phabricator-device-change', null, device); - // When the user clicks away from the textarea, deactivate. - var deactivate = JX.bind(this, this._deactivate); + // When the user clicks away from the textarea, deactivate. However, we + // don't want to deactivate if we're blurring because they clicked an + // option in the dropdown, so put a timeout on the deactivation. This + // will let the click run first if they did actually click a result. + var deactivate = JX.bind(this, function() { + setTimeout(JX.bind(this, this._deactivate), 10); + }); + JX.DOM.listen(area, 'blur', null, deactivate); }, @@ -134,6 +140,9 @@ JX.install('PHUIXAutocomplete', { JX.bind(this, this._onresults, code)); datasource.setTransformer(JX.bind(this, this._transformresult)); + datasource.setSortHandler( + JX.bind(datasource, JX.Prefab.sortHandler, {})); + datasource.setFilterHandler(JX.Prefab.filterClosedResults); this._datasources[code] = datasource; } From 7f19216e4499b0370fff4a5c1dfc2a94b54ab245 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 15 Jan 2016 09:38:39 -0800 Subject: [PATCH 10/66] Better fix for autocomplete blur (select on mousedown instead of delaying blur) Summary: Ref T10163. I would still sometimes not get a replacement after clicking with the delayed blur. This seems to fix the issue more consistently: instead of listening for a click event (which fires after the blur), listen for a mousedown event (which fires before the blur). Test Plan: Observed consistent selection via mouse locally. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10163 Differential Revision: https://secure.phabricator.com/D15032 --- resources/celerity/map.php | 16 ++++++++-------- webroot/rsrc/js/phuix/PHUIXAutocomplete.js | 12 +++--------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 00959be9cf..db8912ccf6 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -507,7 +507,7 @@ return array( 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', - 'rsrc/js/phuix/PHUIXAutocomplete.js' => '2b735afc', + 'rsrc/js/phuix/PHUIXAutocomplete.js' => '3d6e37cc', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 'rsrc/js/phuix/PHUIXFormControl.js' => '8fba1997', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', @@ -836,7 +836,7 @@ return array( 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', - 'phuix-autocomplete' => '2b735afc', + 'phuix-autocomplete' => '3d6e37cc', 'phuix-dropdown-menu' => 'bd4c8dca', 'phuix-form-control-view' => '8fba1997', 'phuix-icon-view' => 'bff6884b', @@ -1023,12 +1023,6 @@ return array( 'javelin-install', 'javelin-util', ), - '2b735afc' => array( - 'javelin-install', - 'javelin-dom', - 'phuix-icon-view', - 'phabricator-prefab', - ), '2b8de964' => array( 'javelin-install', 'javelin-util', @@ -1086,6 +1080,12 @@ return array( 'javelin-util', 'javelin-uri', ), + '3d6e37cc' => array( + 'javelin-install', + 'javelin-dom', + 'phuix-icon-view', + 'phabricator-prefab', + ), '3ee3408b' => array( 'javelin-behavior', 'javelin-behavior-device', diff --git a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js index 67e8b4a32a..118ae7e293 100644 --- a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js +++ b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js @@ -55,19 +55,13 @@ JX.install('PHUIXAutocomplete', { JX.bind(this, this._update)); var select = JX.bind(this, this._onselect); - JX.DOM.listen(this._getNode(), 'click', 'typeahead-result', select); + JX.DOM.listen(this._getNode(), 'mousedown', 'typeahead-result', select); var device = JX.bind(this, this._ondevice); JX.Stratcom.listen('phabricator-device-change', null, device); - // When the user clicks away from the textarea, deactivate. However, we - // don't want to deactivate if we're blurring because they clicked an - // option in the dropdown, so put a timeout on the deactivation. This - // will let the click run first if they did actually click a result. - var deactivate = JX.bind(this, function() { - setTimeout(JX.bind(this, this._deactivate), 10); - }); - + // When the user clicks away from the textarea, deactivate. + var deactivate = JX.bind(this, this._deactivate); JX.DOM.listen(area, 'blur', null, deactivate); }, From 2d495e97014d2834f76cdff9bc392a16b51428df Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 15 Jan 2016 11:10:38 -0800 Subject: [PATCH 11/66] Improve autocomplete behavior when typing ordered lists Summary: Ref T10163. - If a user types an autocomplete character ("@" or "#") and then a space, deactivate immediately (probably an ordered list). - If a user types an autocomplete character indented on a line with no other prior text, don't activate (probably an ordered list or code block). Test Plan: Typed: - `# `, saw immediate deactivation. - ` #`, saw no activation in the first place. - `#x`, saw activation. - `asdf #x`, saw activation. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10163 Differential Revision: https://secure.phabricator.com/D15033 --- resources/celerity/map.php | 6 +++--- webroot/rsrc/js/phuix/PHUIXAutocomplete.js | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index db8912ccf6..dafe3e3166 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -507,7 +507,7 @@ return array( 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', - 'rsrc/js/phuix/PHUIXAutocomplete.js' => '3d6e37cc', + 'rsrc/js/phuix/PHUIXAutocomplete.js' => '3dfff01f', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 'rsrc/js/phuix/PHUIXFormControl.js' => '8fba1997', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', @@ -836,7 +836,7 @@ return array( 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', - 'phuix-autocomplete' => '3d6e37cc', + 'phuix-autocomplete' => '3dfff01f', 'phuix-dropdown-menu' => 'bd4c8dca', 'phuix-form-control-view' => '8fba1997', 'phuix-icon-view' => 'bff6884b', @@ -1080,7 +1080,7 @@ return array( 'javelin-util', 'javelin-uri', ), - '3d6e37cc' => array( + '3dfff01f' => array( 'javelin-install', 'javelin-dom', 'phuix-icon-view', diff --git a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js index 118ae7e293..7df865138b 100644 --- a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js +++ b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js @@ -119,6 +119,16 @@ JX.install('PHUIXAutocomplete', { return; } + // Get all the text on the current line. If the line begins with + // whitespace, don't activate: the user is probably typing code or a + // numbered list. + var line = area.value.substring(0, head); + line = line.split('\n'); + line = line[line.length - 1]; + if (line.match(/^\s+/)) { + return; + } + this._cursorHead = head; this._cursorTail = range.end; this._pixelHead = JX.TextAreaUtils.getPixelDimensions( @@ -370,6 +380,13 @@ JX.install('PHUIXAutocomplete', { var x = this._pixelHead.start.x; var y = Math.max(this._pixelHead.end.y, pixels.end.y) + 24; + // If the first character after the trigger is a space, just deactivate + // immediately. This occurs if a user types a numbered list using "#". + if (text.length && text[0] == ' ') { + this._deactivate(); + return; + } + var trim = this._trim(text); this._datasource.didChange(trim); From df272dfa266bbf7de8d5b5520ec41e9040211ed6 Mon Sep 17 00:00:00 2001 From: epriestley Date: Sat, 16 Jan 2016 12:24:29 -0800 Subject: [PATCH 12/66] Allow autocomplete to activate after ">", ":" or "!" Summary: Ref T10163. This allows activation in blockquotes or after `NOTE:`, for consistency. Test Plan: Typed `>@dog`, etc., got autocomplete. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10163 Differential Revision: https://secure.phabricator.com/D15035 --- resources/celerity/map.php | 16 ++++++++-------- webroot/rsrc/js/phuix/PHUIXAutocomplete.js | 3 +++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index dafe3e3166..6d064736a6 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -507,7 +507,7 @@ return array( 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', - 'rsrc/js/phuix/PHUIXAutocomplete.js' => '3dfff01f', + 'rsrc/js/phuix/PHUIXAutocomplete.js' => '3601bdd1', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 'rsrc/js/phuix/PHUIXFormControl.js' => '8fba1997', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', @@ -836,7 +836,7 @@ return array( 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', - 'phuix-autocomplete' => '3dfff01f', + 'phuix-autocomplete' => '3601bdd1', 'phuix-dropdown-menu' => 'bd4c8dca', 'phuix-form-control-view' => '8fba1997', 'phuix-icon-view' => 'bff6884b', @@ -1064,6 +1064,12 @@ return array( 'javelin-vector', 'phuix-autocomplete', ), + '3601bdd1' => array( + 'javelin-install', + 'javelin-dom', + 'phuix-icon-view', + 'phabricator-prefab', + ), '3ab51e2c' => array( 'javelin-behavior', 'javelin-behavior-device', @@ -1080,12 +1086,6 @@ return array( 'javelin-util', 'javelin-uri', ), - '3dfff01f' => array( - 'javelin-install', - 'javelin-dom', - 'phuix-icon-view', - 'phabricator-prefab', - ), '3ee3408b' => array( 'javelin-behavior', 'javelin-behavior-device', diff --git a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js index 7df865138b..e35f31ce98 100644 --- a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js +++ b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js @@ -111,6 +111,9 @@ JX.install('PHUIXAutocomplete', { case '-': // Might be an unnumbered list. case '.': // Might be a numbered list. case '|': // Might be a table cell. + case '>': // Might be a blockquote. + case '!': // Might be a blockquote attribution line. + case ':': // Might be a "NOTE:". // We'll let these autocomplete. break; default: From 4f3a9a8aca25eeeba5b35d6f5bdbc299129c900e Mon Sep 17 00:00:00 2001 From: epriestley Date: Sat, 16 Jan 2016 13:36:27 -0800 Subject: [PATCH 13/66] Immediately cancel autocomplete if the user types certain characters anywhere Summary: Ref T10163. Some characters are almost certainly punctuation or markup rather than autocomplete requests. Immediately cancel any active autocomplete when the user types one of these. Note that some of these are also suffix characters. If you type `@dog,`, you have until the next character to decide you actually mean to autocomplete. Once you type something else we deactivate. If you type `#dog#` or `##`, we deactivate immediately. Test Plan: Typed `@dog#`, etc. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10163 Differential Revision: https://secure.phabricator.com/D15036 --- resources/celerity/map.php | 16 ++++++++-------- webroot/rsrc/js/phuix/PHUIXAutocomplete.js | 20 +++++++++++++++++++- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 6d064736a6..112ce12508 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -507,7 +507,7 @@ return array( 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', - 'rsrc/js/phuix/PHUIXAutocomplete.js' => '3601bdd1', + 'rsrc/js/phuix/PHUIXAutocomplete.js' => '569edc21', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 'rsrc/js/phuix/PHUIXFormControl.js' => '8fba1997', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', @@ -836,7 +836,7 @@ return array( 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', - 'phuix-autocomplete' => '3601bdd1', + 'phuix-autocomplete' => '569edc21', 'phuix-dropdown-menu' => 'bd4c8dca', 'phuix-form-control-view' => '8fba1997', 'phuix-icon-view' => 'bff6884b', @@ -1064,12 +1064,6 @@ return array( 'javelin-vector', 'phuix-autocomplete', ), - '3601bdd1' => array( - 'javelin-install', - 'javelin-dom', - 'phuix-icon-view', - 'phabricator-prefab', - ), '3ab51e2c' => array( 'javelin-behavior', 'javelin-behavior-device', @@ -1210,6 +1204,12 @@ return array( 'javelin-vector', 'javelin-dom', ), + '569edc21' => array( + 'javelin-install', + 'javelin-dom', + 'phuix-icon-view', + 'phabricator-prefab', + ), '56a1ca03' => array( 'javelin-behavior', 'javelin-behavior-device', diff --git a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js index e35f31ce98..8e3eb00481 100644 --- a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js +++ b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js @@ -276,7 +276,13 @@ JX.install('PHUIXAutocomplete', { }, _getSuffixes: function() { - return[' ', ':', ',']; + return [' ', ':', ',', ')']; + }, + + _getCancelCharacters: function() { + // The "." character does not cancel because of projects named + // "node.js" or "blog.mycompany.com". + return ['#', '@', ',', '!', '?']; }, _trim: function(str) { @@ -392,6 +398,18 @@ JX.install('PHUIXAutocomplete', { var trim = this._trim(text); + // Deactivate immediately if a user types a character that we are + // reasonably sure means they don't want to use the autocomplete. For + // example, "##" is almost certainly a header or monospaced text, not + // a project autocompletion. + var cancels = this._getCancelCharacters(); + for (var ii = 0; ii < cancels.length; ii++) { + if (trim.indexOf(cancels[ii]) !== -1) { + this._deactivate(); + return; + } + } + this._datasource.didChange(trim); var node = this._getNode(); From 14ebf662f30aa4385c2573e14d109fdd223ccb21 Mon Sep 17 00:00:00 2001 From: epriestley Date: Sat, 16 Jan 2016 13:43:35 -0800 Subject: [PATCH 14/66] Don't show the autocompleter until the user types at least one character Summary: Ref T10163. Activate on `@d`, not just `@`. Note that if you type `@d` and then press delete once so you're left with `@`, we stay active (and show the "type a username" hint). Test Plan: - Typed `@`, no completer. - Typed `d`, got completer. - Typed delete, still had completer, now showing hint prompt. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10163 Differential Revision: https://secure.phabricator.com/D15037 --- resources/celerity/map.php | 16 +++++------ webroot/rsrc/js/phuix/PHUIXAutocomplete.js | 31 +++++++++++++++++----- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 112ce12508..8c46a7459c 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -507,7 +507,7 @@ return array( 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', - 'rsrc/js/phuix/PHUIXAutocomplete.js' => '569edc21', + 'rsrc/js/phuix/PHUIXAutocomplete.js' => '377c9b3e', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 'rsrc/js/phuix/PHUIXFormControl.js' => '8fba1997', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', @@ -836,7 +836,7 @@ return array( 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', - 'phuix-autocomplete' => '569edc21', + 'phuix-autocomplete' => '377c9b3e', 'phuix-dropdown-menu' => 'bd4c8dca', 'phuix-form-control-view' => '8fba1997', 'phuix-icon-view' => 'bff6884b', @@ -1064,6 +1064,12 @@ return array( 'javelin-vector', 'phuix-autocomplete', ), + '377c9b3e' => array( + 'javelin-install', + 'javelin-dom', + 'phuix-icon-view', + 'phabricator-prefab', + ), '3ab51e2c' => array( 'javelin-behavior', 'javelin-behavior-device', @@ -1204,12 +1210,6 @@ return array( 'javelin-vector', 'javelin-dom', ), - '569edc21' => array( - 'javelin-install', - 'javelin-dom', - 'phuix-icon-view', - 'phabricator-prefab', - ), '56a1ca03' => array( 'javelin-behavior', 'javelin-behavior-device', diff --git a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js index 8e3eb00481..f8d5bea942 100644 --- a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js +++ b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js @@ -32,6 +32,9 @@ JX.install('PHUIXAutocomplete', { _focus: null, _focusRef: null, _listNodes: null, + _x: null, + _y: null, + _visible: false, setArea: function(area) { this._area = area; @@ -186,6 +189,7 @@ JX.install('PHUIXAutocomplete', { JX.DOM.hide(node); this._active = false; + this._visible = false; }, _onkeypress: function(e) { @@ -412,18 +416,33 @@ JX.install('PHUIXAutocomplete', { this._datasource.didChange(trim); - var node = this._getNode(); - node.style.left = x + 'px'; - node.style.top = y + 'px'; - JX.DOM.show(node); + this._x = x; + this._y = y; - var echo = this._getEchoNode(); var hint = trim; - if (!hint.length) { + if (hint.length) { + // We only show the autocompleter after the user types at least one + // character. For example, "@" does not trigger it, but "@d" does. + this._visible = true; + } else { hint = this._getSpec().hintText; } + var echo = this._getEchoNode(); JX.DOM.setContent(echo, hint); + + this._redraw(); + }, + + _redraw: function() { + if (!this._visible) { + return; + } + + var node = this._getNode(); + node.style.left = this._x + 'px'; + node.style.top = this._y + 'px'; + JX.DOM.show(node); }, _autocomplete: function() { From 849b4c765a1f02622b4adb134417f8c2945232d1 Mon Sep 17 00:00:00 2001 From: epriestley Date: Sat, 16 Jan 2016 14:00:02 -0800 Subject: [PATCH 15/66] When the autocompleter would fall off the bottom of the screen, put it above the text instead Summary: Ref T10163. In cases like Conpherence, the autocompleter can currently render off the bottom of the screen. Put it above if it would be offscreen. Test Plan: {F1062286} Reviewers: chad Reviewed By: chad Maniphest Tasks: T10163 Differential Revision: https://secure.phabricator.com/D15038 --- resources/celerity/map.php | 16 ++++++++-------- webroot/rsrc/js/phuix/PHUIXAutocomplete.js | 22 ++++++++++++++++++++-- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 8c46a7459c..d4cccb53eb 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -507,7 +507,7 @@ return array( 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', - 'rsrc/js/phuix/PHUIXAutocomplete.js' => '377c9b3e', + 'rsrc/js/phuix/PHUIXAutocomplete.js' => '5582787f', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 'rsrc/js/phuix/PHUIXFormControl.js' => '8fba1997', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', @@ -836,7 +836,7 @@ return array( 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', - 'phuix-autocomplete' => '377c9b3e', + 'phuix-autocomplete' => '5582787f', 'phuix-dropdown-menu' => 'bd4c8dca', 'phuix-form-control-view' => '8fba1997', 'phuix-icon-view' => 'bff6884b', @@ -1064,12 +1064,6 @@ return array( 'javelin-vector', 'phuix-autocomplete', ), - '377c9b3e' => array( - 'javelin-install', - 'javelin-dom', - 'phuix-icon-view', - 'phabricator-prefab', - ), '3ab51e2c' => array( 'javelin-behavior', 'javelin-behavior-device', @@ -1204,6 +1198,12 @@ return array( 'javelin-request', 'javelin-typeahead-source', ), + '5582787f' => array( + 'javelin-install', + 'javelin-dom', + 'phuix-icon-view', + 'phabricator-prefab', + ), '558829c2' => array( 'javelin-stratcom', 'javelin-behavior', diff --git a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js index f8d5bea942..eaf592e65b 100644 --- a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js +++ b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js @@ -232,6 +232,8 @@ JX.install('PHUIXAutocomplete', { if (this._focus === null && nodes.length) { this._setFocus(0); } + + this._redraw(); }, _setFocus: function(idx) { @@ -440,9 +442,25 @@ JX.install('PHUIXAutocomplete', { } var node = this._getNode(); - node.style.left = this._x + 'px'; - node.style.top = this._y + 'px'; JX.DOM.show(node); + + var p = new JX.Vector(this._x, this._y); + var s = JX.Vector.getScroll(); + var v = JX.Vector.getViewport(); + + // If the menu would run off the bottom of the screen when showing the + // maximum number of possible choices, put it above instead. We're doing + // this based on the maximum size so the menu doesn't jump up and down + // as results arrive. + + var option_height = 30; + var extra_margin = 24; + if ((s.y + v.y) < (p.y + (5 * option_height) + extra_margin)) { + var d = JX.Vector.getDim(node); + p.y = p.y - d.y - 36; + } + + p.setPos(node); }, _autocomplete: function() { From 75b8d3312bbbb54a86028971dee7488f568713b7 Mon Sep 17 00:00:00 2001 From: epriestley Date: Sat, 16 Jan 2016 14:33:03 -0800 Subject: [PATCH 16/66] Hide the autocompleter intelligently when you ignore it and keep typing Summary: Ref T10163. When we think the user has finished typing a word (because they typed a space, period, or other similar characters) and nothing else they might type could possibly change the outcome (usually because the words they have typed already match nothing), just deactivate the autocomplete. As a special case, if the word they have typed already select exactly one result, //and// they have already typed exactly that result, assume they just typed it from memory and deactivate. Test Plan: - Typed `@dog qwer zxcv` and saw autocomplete deactivate on the space before `z` (on my local install, `@dog` is ambiguous but `@dog qwer` matches nothing). - Typed `@epriestley ` and saw autocomplete deactivate on space. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10163 Differential Revision: https://secure.phabricator.com/D15039 --- resources/celerity/map.php | 50 ++++---- .../source/TypeaheadOnDemandSource.js | 19 ++- .../typeahead/source/TypeaheadSource.js | 2 +- webroot/rsrc/js/phuix/PHUIXAutocomplete.js | 114 +++++++++++++++++- 4 files changed, 152 insertions(+), 33 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index d4cccb53eb..3dec5a890b 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -8,7 +8,7 @@ return array( 'names' => array( 'core.pkg.css' => '3a97c8b9', - 'core.pkg.js' => '5813273d', + 'core.pkg.js' => '573e6664', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', 'differential.pkg.js' => 'f83532f8', @@ -249,9 +249,9 @@ return array( 'rsrc/externals/javelin/lib/control/typeahead/Typeahead.js' => '70baed2f', 'rsrc/externals/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js' => 'e6e25838', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadCompositeSource.js' => '503e17fd', - 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js' => '8b3fd187', + 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js' => '013ffff9', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js' => '54f314a0', - 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => '2818f5ce', + 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => '1bc11c4a', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js' => '6c0e62fa', 'rsrc/externals/raphael/g.raphael.js' => '40dde778', 'rsrc/externals/raphael/g.raphael.line.js' => '40da039e', @@ -507,7 +507,7 @@ return array( 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', - 'rsrc/js/phuix/PHUIXAutocomplete.js' => '5582787f', + 'rsrc/js/phuix/PHUIXAutocomplete.js' => '0abdd4a8', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 'rsrc/js/phuix/PHUIXFormControl.js' => '8fba1997', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', @@ -709,9 +709,9 @@ return array( 'javelin-typeahead' => '70baed2f', 'javelin-typeahead-composite-source' => '503e17fd', 'javelin-typeahead-normalizer' => 'e6e25838', - 'javelin-typeahead-ondemand-source' => '8b3fd187', + 'javelin-typeahead-ondemand-source' => '013ffff9', 'javelin-typeahead-preloaded-source' => '54f314a0', - 'javelin-typeahead-source' => '2818f5ce', + 'javelin-typeahead-source' => '1bc11c4a', 'javelin-typeahead-static-source' => '6c0e62fa', 'javelin-uri' => 'c989ade3', 'javelin-util' => '93cc50d6', @@ -836,7 +836,7 @@ return array( 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', - 'phuix-autocomplete' => '5582787f', + 'phuix-autocomplete' => '0abdd4a8', 'phuix-dropdown-menu' => 'bd4c8dca', 'phuix-form-control-view' => '8fba1997', 'phuix-icon-view' => 'bff6884b', @@ -863,6 +863,12 @@ return array( 'unhandled-exception-css' => '4c96257a', ), 'requires' => array( + '013ffff9' => array( + 'javelin-install', + 'javelin-util', + 'javelin-request', + 'javelin-typeahead-source', + ), '01774ab2' => array( 'javelin-dom', 'javelin-util', @@ -911,6 +917,12 @@ return array( 'javelin-dom', 'javelin-router', ), + '0abdd4a8' => array( + 'javelin-install', + 'javelin-dom', + 'phuix-icon-view', + 'phabricator-prefab', + ), '0b7a4f6e' => array( 'javelin-behavior', 'javelin-typeahead-ondemand-source', @@ -950,6 +962,12 @@ return array( 'javelin-util', 'phabricator-keyboard-shortcut-manager', ), + '1bc11c4a' => array( + 'javelin-install', + 'javelin-util', + 'javelin-dom', + 'javelin-typeahead-normalizer', + ), '1d298e3a' => array( 'javelin-install', 'javelin-util', @@ -1009,12 +1027,6 @@ return array( 'phabricator-drag-and-drop-file-upload', 'phabricator-draggable-list', ), - '2818f5ce' => array( - 'javelin-install', - 'javelin-util', - 'javelin-dom', - 'javelin-typeahead-normalizer', - ), '2926fff2' => array( 'javelin-behavior', 'javelin-dom', @@ -1198,12 +1210,6 @@ return array( 'javelin-request', 'javelin-typeahead-source', ), - '5582787f' => array( - 'javelin-install', - 'javelin-dom', - 'phuix-icon-view', - 'phabricator-prefab', - ), '558829c2' => array( 'javelin-stratcom', 'javelin-behavior', @@ -1489,12 +1495,6 @@ return array( 'javelin-stratcom', 'javelin-vector', ), - '8b3fd187' => array( - 'javelin-install', - 'javelin-util', - 'javelin-request', - 'javelin-typeahead-source', - ), '8bdb2835' => array( 'phui-fontkit-css', ), diff --git a/webroot/rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js b/webroot/rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js index fd601478a0..5b301dc6fe 100644 --- a/webroot/rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js +++ b/webroot/rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js @@ -38,7 +38,7 @@ JX.install('TypeaheadOnDemandSource', { lastChange : null, haveData : null, - didChange : function(raw_value) { + didChange : function(raw_value, force) { this.lastChange = JX.now(); var value = this.normalize(raw_value); @@ -59,10 +59,19 @@ JX.install('TypeaheadOnDemandSource', { } this.waitForResults(); - setTimeout( - JX.bind(this, this.sendRequest, this.lastChange, value, raw_value), - this.getQueryDelay() - ); + + var send_request = JX.bind( + this, + this.sendRequest, + this.lastChange, + value, + raw_value); + + if (force) { + send_request(); + } else { + setTimeout(send_request, this.getQueryDelay()); + } } }, diff --git a/webroot/rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js b/webroot/rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js index e4c68f3742..74dc1c2453 100644 --- a/webroot/rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js +++ b/webroot/rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js @@ -289,7 +289,7 @@ JX.install('TypeaheadSource', { this.filterAndSortHits(value, hits); var nodes = this.renderNodes(value, hits); - this.invoke('resultsready', nodes, value); + this.invoke('resultsready', nodes, value, partial); if (!partial) { this.invoke('complete'); } diff --git a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js index eaf592e65b..d34909c44f 100644 --- a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js +++ b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js @@ -12,6 +12,7 @@ JX.install('PHUIXAutocomplete', { this._map = {}; this._datasources = {}; this._listNodes = []; + this._resultMap = {}; }, members: { @@ -35,6 +36,7 @@ JX.install('PHUIXAutocomplete', { _x: null, _y: null, _visible: false, + _resultMap: null, setArea: function(area) { this._area = area; @@ -205,7 +207,30 @@ JX.install('PHUIXAutocomplete', { } }, - _onresults: function(code, nodes, value) { + _onresults: function(code, nodes, value, partial) { + // Even if these results are out of date, we still want to fill in the + // result map so we can terminate things later. + if (!partial) { + if (!this._resultMap[code]) { + this._resultMap[code] = {}; + } + + var hits = []; + for (var ii = 0; ii < nodes.length; ii++) { + var result = this._datasources[code].getResult(nodes[ii].rel); + if (!result) { + hits = null; + break; + } + + hits.push(result.autocomplete); + } + + if (hits !== null) { + this._resultMap[code][value] = hits; + } + } + if (code !== this._active) { return; } @@ -214,6 +239,13 @@ JX.install('PHUIXAutocomplete', { return; } + if (this._isTerminatedString(value)) { + if (this._hasUnrefinableResults(value)) { + this._deactivate(); + return; + } + } + var list = this._getListNode(); JX.DOM.setContent(list, nodes); @@ -291,6 +323,59 @@ JX.install('PHUIXAutocomplete', { return ['#', '@', ',', '!', '?']; }, + _getTerminators: function() { + return [' ', ':', ',', '.', '!', '?']; + }, + + _isTerminatedString: function(string) { + var terminators = this._getTerminators(); + for (var ii = 0; ii < terminators.length; ii++) { + var term = terminators[ii]; + if (string.substring(string.length - term.length) == term) { + return true; + } + } + + return false; + }, + + _hasUnrefinableResults: function(query) { + if (!this._resultMap[this._active]) { + return false; + } + + var map = this._resultMap[this._active]; + + for (var ii = 1; ii < query.length; ii++) { + var prefix = query.substring(0, ii); + if (map.hasOwnProperty(prefix)) { + var results = map[prefix]; + + // If any prefix of the query has no results, the full query also + // has no results so we can not refine them. + if (!results.length) { + return true; + } + + // If there is exactly one match and the it is a prefix of the query, + // we can safely assume the user just typed out the right result + // from memory and doesn't need to refine it. + if (results.length == 1) { + // Strip the first character off, like a "#" or "@". + var result = results[0].substring(1); + + if (query.length >= result.length) { + if (query.substring(0, result.length) === result) { + return true; + } + } + } + } + } + + return false; + }, + _trim: function(str) { var suffixes = this._getSuffixes(); for (var ii = 0; ii < suffixes.length; ii++) { @@ -416,7 +501,32 @@ JX.install('PHUIXAutocomplete', { } } - this._datasource.didChange(trim); + // If the input is terminated by a space or another word-terminating + // punctuation mark, we're going to deactivate if the results can not + // be refined by addding more words. + + // The idea is that if you type "@alan ab", you're allowed to keep + // editing "ab" until you type a space, period, or other terminator, + // since you might not be sure how to spell someone's last name or the + // second word of a project. + + // Once you do terminate a word, if the words you have have entered match + // nothing or match only one exact match, we can safely deactivate and + // assume you're just typing text because further words could never + // refine the result set. + + var force; + if (this._isTerminatedString(text)) { + if (this._hasUnrefinableResults(text)) { + this._deactivate(); + return; + } + force = true; + } else { + force = false; + } + + this._datasource.didChange(trim, force); this._x = x; this._y = y; From 75781dba1add1f2be3510bbd87a9df41f60b0ac9 Mon Sep 17 00:00:00 2001 From: epriestley Date: Sat, 16 Jan 2016 14:59:17 -0800 Subject: [PATCH 17/66] Improve autocomplete behavior in lists and with noncompleting results Summary: Ref T10163. Currently, we don't activate on indented lines, but were too aggressive about this, and would not activate on lines like ` - Hey, @user...`, where we should. Instead, don't activate on indented lines if there's only an indent (i.e., `#` probably means enumerated list). Also, if results don't have autocompletes (rare but possible with projects missing slugs), improve behavior. Test Plan: - Typed ` #a`, got no autocomplete. - Missing slug thing is a pain to test locallly, `#1 z z z z` reproduces in production. I'll just verify it there. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10163 Differential Revision: https://secure.phabricator.com/D15040 --- resources/celerity/map.php | 16 ++++++++-------- webroot/rsrc/js/phuix/PHUIXAutocomplete.js | 13 +++++++++---- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 3dec5a890b..8f22b91818 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -507,7 +507,7 @@ return array( 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', - 'rsrc/js/phuix/PHUIXAutocomplete.js' => '0abdd4a8', + 'rsrc/js/phuix/PHUIXAutocomplete.js' => '8bbbad27', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 'rsrc/js/phuix/PHUIXFormControl.js' => '8fba1997', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', @@ -836,7 +836,7 @@ return array( 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', - 'phuix-autocomplete' => '0abdd4a8', + 'phuix-autocomplete' => '8bbbad27', 'phuix-dropdown-menu' => 'bd4c8dca', 'phuix-form-control-view' => '8fba1997', 'phuix-icon-view' => 'bff6884b', @@ -917,12 +917,6 @@ return array( 'javelin-dom', 'javelin-router', ), - '0abdd4a8' => array( - 'javelin-install', - 'javelin-dom', - 'phuix-icon-view', - 'phabricator-prefab', - ), '0b7a4f6e' => array( 'javelin-behavior', 'javelin-typeahead-ondemand-source', @@ -1495,6 +1489,12 @@ return array( 'javelin-stratcom', 'javelin-vector', ), + '8bbbad27' => array( + 'javelin-install', + 'javelin-dom', + 'phuix-icon-view', + 'phabricator-prefab', + ), '8bdb2835' => array( 'phui-fontkit-css', ), diff --git a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js index d34909c44f..b94688e086 100644 --- a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js +++ b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js @@ -127,13 +127,13 @@ JX.install('PHUIXAutocomplete', { return; } - // Get all the text on the current line. If the line begins with - // whitespace, don't activate: the user is probably typing code or a + // Get all the text on the current line. If the line only contains + // whitespace, don't actiavte: the user is probably typing code or a // numbered list. - var line = area.value.substring(0, head); + var line = area.value.substring(0, head - 1); line = line.split('\n'); line = line[line.length - 1]; - if (line.match(/^\s+/)) { + if (line.match(/^\s+$/)) { return; } @@ -223,6 +223,11 @@ JX.install('PHUIXAutocomplete', { break; } + if (!result.autocomplete || !result.autocomplete.length) { + hits = null; + break; + } + hits.push(result.autocomplete); } From b7fe07bbd6fb0bed86e18d6204b26982ac9effb8 Mon Sep 17 00:00:00 2001 From: epriestley Date: Sat, 16 Jan 2016 15:06:15 -0800 Subject: [PATCH 18/66] When autocompleting, add a space if a user didn't already add something Summary: Ref T10163. When a user autocompletes, add a space for them, unless they already added a comma, colon, or space themsevles. Test Plan: Autocompleted `@dog`, got `@dog `. Autocompleted `@epriestley,` got `@epriestley,`. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10163 Differential Revision: https://secure.phabricator.com/D15041 --- resources/celerity/map.php | 16 ++++++++-------- webroot/rsrc/js/phuix/PHUIXAutocomplete.js | 9 ++++++++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 8f22b91818..a41af25a7e 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -507,7 +507,7 @@ return array( 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', - 'rsrc/js/phuix/PHUIXAutocomplete.js' => '8bbbad27', + 'rsrc/js/phuix/PHUIXAutocomplete.js' => 'fc10c813', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 'rsrc/js/phuix/PHUIXFormControl.js' => '8fba1997', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', @@ -836,7 +836,7 @@ return array( 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', - 'phuix-autocomplete' => '8bbbad27', + 'phuix-autocomplete' => 'fc10c813', 'phuix-dropdown-menu' => 'bd4c8dca', 'phuix-form-control-view' => '8fba1997', 'phuix-icon-view' => 'bff6884b', @@ -1489,12 +1489,6 @@ return array( 'javelin-stratcom', 'javelin-vector', ), - '8bbbad27' => array( - 'javelin-install', - 'javelin-dom', - 'phuix-icon-view', - 'phabricator-prefab', - ), '8bdb2835' => array( 'phui-fontkit-css', ), @@ -2092,6 +2086,12 @@ return array( 'javelin-behavior-device', 'phabricator-keyboard-shortcut', ), + 'fc10c813' => array( + 'javelin-install', + 'javelin-dom', + 'phuix-icon-view', + 'phabricator-prefab', + ), 'fc91ab6c' => array( 'javelin-behavior', 'javelin-dom', diff --git a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js index b94688e086..beb3660718 100644 --- a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js +++ b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js @@ -600,19 +600,26 @@ JX.install('PHUIXAutocomplete', { return false; } - // If the user types a string like "@username:" (with a trailing comma), + // If the user types a string like "@username:" (with a trailing colon), // then presses tab or return to pick the completion, don't destroy the // trailing character. var suffixes = this._getSuffixes(); var value = this._value; + var found_suffix = false; for (var ii = 0; ii < suffixes.length; ii++) { var last = value.substring(value.length - suffixes[ii].length); if (last == suffixes[ii]) { ref += suffixes[ii]; + found_suffix = true; break; } } + // If we didn't find an existing suffix, add a space. + if (!found_suffix) { + ref = ref + ' '; + } + area.value = text.substring(0, head - 1) + ref + text.substring(tail); var end = head + ref.length; From 7ab970d1a7d347d2d318f9cedbe11ac75addfa3a Mon Sep 17 00:00:00 2001 From: epriestley Date: Sat, 16 Jan 2016 15:36:45 -0800 Subject: [PATCH 19/66] Eat right-click, etc., on autocomplete suggestion menu Summary: Ref T10163. If you right-click the suggestion menu, just eat it. I don't think we can really choose a different behavior reasonably, or that users have any reason to do this. I'm leaving "clicking the header dismisses it", I think that behavior is fine and reasonable. Test Plan: Control-clicked a suggestion menu, didn't trigger a suggestion. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10163 Differential Revision: https://secure.phabricator.com/D15042 --- resources/celerity/map.php | 16 ++++++++-------- webroot/rsrc/js/phuix/PHUIXAutocomplete.js | 8 ++++++++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index a41af25a7e..97150f6c74 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -507,7 +507,7 @@ return array( 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', - 'rsrc/js/phuix/PHUIXAutocomplete.js' => 'fc10c813', + 'rsrc/js/phuix/PHUIXAutocomplete.js' => '21dc9144', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 'rsrc/js/phuix/PHUIXFormControl.js' => '8fba1997', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', @@ -836,7 +836,7 @@ return array( 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', - 'phuix-autocomplete' => 'fc10c813', + 'phuix-autocomplete' => '21dc9144', 'phuix-dropdown-menu' => 'bd4c8dca', 'phuix-form-control-view' => '8fba1997', 'phuix-icon-view' => 'bff6884b', @@ -1004,6 +1004,12 @@ return array( 'javelin-stratcom', 'conpherence-thread-manager', ), + '21dc9144' => array( + 'javelin-install', + 'javelin-dom', + 'phuix-icon-view', + 'phabricator-prefab', + ), '2290aeef' => array( 'javelin-install', 'javelin-dom', @@ -2086,12 +2092,6 @@ return array( 'javelin-behavior-device', 'phabricator-keyboard-shortcut', ), - 'fc10c813' => array( - 'javelin-install', - 'javelin-dom', - 'phuix-icon-view', - 'phabricator-prefab', - ), 'fc91ab6c' => array( 'javelin-behavior', 'javelin-dom', diff --git a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js index beb3660718..3bc5cf0166 100644 --- a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js +++ b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js @@ -304,6 +304,14 @@ JX.install('PHUIXAutocomplete', { }, _onselect: function (e) { + if (!e.isNormalMouseEvent()) { + // Eat right clicks, control clicks, etc., on the results. These can + // not do anything meaningful and if we let them through they'll blur + // the field and dismiss the results. + e.kill(); + return; + } + var target = e.getNode('typeahead-result'); for (var ii = 0; ii < this._listNodes.length; ii++) { From 495e1384dd5c3d1baf0e1a50b95ee4320c50086f Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 18 Jan 2016 06:57:16 -0800 Subject: [PATCH 20/66] Fix project queries in Ponder Summary: Fixes T10167. We were dropping infrastructure joins. Test Plan: Queried for questions by project. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10167 Differential Revision: https://secure.phabricator.com/D15043 --- src/applications/ponder/query/PonderQuestionQuery.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/applications/ponder/query/PonderQuestionQuery.php b/src/applications/ponder/query/PonderQuestionQuery.php index 480f2c3296..9762f925f5 100644 --- a/src/applications/ponder/query/PonderQuestionQuery.php +++ b/src/applications/ponder/query/PonderQuestionQuery.php @@ -129,13 +129,13 @@ final class PonderQuestionQuery return $questions; } - protected function buildJoinClauseParts(AphrontDatabaseConnection $conn_r) { - $joins = array(); + protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) { + $joins = parent::buildJoinClauseParts($conn); if ($this->answererPHIDs) { $answer_table = new PonderAnswer(); $joins[] = qsprintf( - $conn_r, + $conn, 'JOIN %T a ON a.questionID = q.id AND a.authorPHID IN (%Ls)', $answer_table->getTableName(), $this->answererPHIDs); From 45a4a68628b96f134847a19659250a6f39a3bdbb Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 18 Jan 2016 07:10:00 -0800 Subject: [PATCH 21/66] Distinguish between "no coverage information" and "no test coverage" better Summary: Fixes T10169. Diffs with no build targets were incorrectly showing as though they had no test coverage, when we actually want to show them having no coverage information available. Test Plan: Viewed an older revision, saw a column of "Not Executable" before change, now see no column. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10169 Differential Revision: https://secure.phabricator.com/D15044 --- .../DifferentialChangesetViewController.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/applications/differential/controller/DifferentialChangesetViewController.php b/src/applications/differential/controller/DifferentialChangesetViewController.php index 3f08ce4883..01bdd395a7 100644 --- a/src/applications/differential/controller/DifferentialChangesetViewController.php +++ b/src/applications/differential/controller/DifferentialChangesetViewController.php @@ -400,16 +400,23 @@ final class DifferentialChangesetViewController extends DifferentialController { private function loadCoverage(DifferentialChangeset $changeset) { $target_phids = $changeset->getDiff()->getBuildTargetPHIDs(); if (!$target_phids) { - return array(); + return null; } $unit = id(new HarbormasterBuildUnitMessage())->loadAllWhere( 'buildTargetPHID IN (%Ls)', $target_phids); + if (!$unit) { + return null; + } + $coverage = array(); foreach ($unit as $message) { - $test_coverage = $message->getProperty('coverage', array()); + $test_coverage = $message->getProperty('coverage'); + if ($test_coverage === null) { + continue; + } $coverage_data = idx($test_coverage, $changeset->getFileName()); if (!strlen($coverage_data)) { continue; @@ -417,6 +424,10 @@ final class DifferentialChangesetViewController extends DifferentialController { $coverage[] = $coverage_data; } + if (!$coverage) { + return null; + } + return ArcanistUnitTestResult::mergeCoverage($coverage); } From 9ae48d4026fcf4c87c69fb77155d4938140043e0 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 18 Jan 2016 07:28:23 -0800 Subject: [PATCH 22/66] Fix smushing of multiple values in Projects "Additional Hashtags" field Summary: Ref T10168. When we render this control, we currently don't put commas into the value correctly if there are multiple alternative hashtags. Test Plan: Edited a project with multiple alternate hashtags. Before change: they all got smushed together. After change: properly comma-separated. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10168 Differential Revision: https://secure.phabricator.com/D15045 --- .../editfield/PhabricatorStringListEditField.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/applications/transactions/editfield/PhabricatorStringListEditField.php b/src/applications/transactions/editfield/PhabricatorStringListEditField.php index 64cb1fe08c..74046be7ac 100644 --- a/src/applications/transactions/editfield/PhabricatorStringListEditField.php +++ b/src/applications/transactions/editfield/PhabricatorStringListEditField.php @@ -7,6 +7,11 @@ final class PhabricatorStringListEditField return new AphrontFormTextControl(); } + protected function getValueForControl() { + $value = $this->getValue(); + return implode(', ', $value); + } + protected function newConduitParameterType() { return new ConduitStringListParameterType(); } From 5d0222d532c19ac7162c38a7e8b5726dd8af2bc5 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 18 Jan 2016 08:32:36 -0800 Subject: [PATCH 23/66] Fix an issue where the profile menu could become enormous Summary: Ref T10054. Without `max-width`, Safari can make this too large with a long project name (maybe because of `table-cell`?). Test Plan: Saw normal-width menu instead of huge menu on very long project. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15046 --- resources/celerity/map.php | 6 +++--- webroot/rsrc/css/phui/phui-profile-menu.css | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 97150f6c74..10d8366cb6 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => '3a97c8b9', + 'core.pkg.css' => 'eacc9293', 'core.pkg.js' => '573e6664', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -143,7 +143,7 @@ return array( 'rsrc/css/phui/phui-object-item-list-view.css' => '26c30d3f', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', - 'rsrc/css/phui/phui-profile-menu.css' => 'e8030bb3', + 'rsrc/css/phui/phui-profile-menu.css' => 'a26fa598', 'rsrc/css/phui/phui-property-list-view.css' => '27b2849e', 'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591', 'rsrc/css/phui/phui-spacing.css' => '042804d6', @@ -822,7 +822,7 @@ return array( 'phui-object-item-list-view-css' => '26c30d3f', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', - 'phui-profile-menu-css' => 'e8030bb3', + 'phui-profile-menu-css' => 'a26fa598', 'phui-property-list-view-css' => '27b2849e', 'phui-remarkup-preview-css' => '1a8f2591', 'phui-spacing-css' => '042804d6', diff --git a/webroot/rsrc/css/phui/phui-profile-menu.css b/webroot/rsrc/css/phui/phui-profile-menu.css index 6616876077..1434475ef3 100644 --- a/webroot/rsrc/css/phui/phui-profile-menu.css +++ b/webroot/rsrc/css/phui/phui-profile-menu.css @@ -17,7 +17,9 @@ position: relative; vertical-align: top; width: 240px; + max-width: 240px; margin-top: 0; + overflow: hidden; } .device-desktop .phui-profile-menu .phabricator-nav-content { From 2144d877ee3050282369992cc5d12192c113dddd Mon Sep 17 00:00:00 2001 From: Chad Little Date: Fri, 15 Jan 2016 21:37:36 -0800 Subject: [PATCH 24/66] PHUIIconCircleView Summary: Icon in a circle. Base class, not much in the way of color choices. Test Plan: UIExamples, Chrome. {F1062027} Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D15034 --- resources/celerity/map.php | 6 +- src/__phutil_library_map__.php | 2 + .../uiexample/examples/PHUIIconExample.php | 29 ++++++++ src/view/phui/PHUIIconCircleView.php | 67 +++++++++++++++++++ webroot/rsrc/css/phui/phui-icon.css | 42 ++++++++++++ 5 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 src/view/phui/PHUIIconCircleView.php diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 10d8366cb6..7a4a3ce4eb 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => 'eacc9293', + 'core.pkg.css' => '9d3a79f4', 'core.pkg.js' => '573e6664', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -134,7 +134,7 @@ return array( 'rsrc/css/phui/phui-form.css' => '0b98e572', 'rsrc/css/phui/phui-header-view.css' => '55bb32dd', 'rsrc/css/phui/phui-icon-set-selector.css' => '1ab67aad', - 'rsrc/css/phui/phui-icon.css' => 'b0a6b1b6', + 'rsrc/css/phui/phui-icon.css' => '3f33ab57', 'rsrc/css/phui/phui-image-mask.css' => '5a8b09c8', 'rsrc/css/phui/phui-info-panel.css' => '27ea50a1', 'rsrc/css/phui/phui-info-view.css' => '6d7c3509', @@ -812,7 +812,7 @@ return array( 'phui-form-view-css' => '4a1a0f5e', 'phui-header-view-css' => '55bb32dd', 'phui-icon-set-selector-css' => '1ab67aad', - 'phui-icon-view-css' => 'b0a6b1b6', + 'phui-icon-view-css' => '3f33ab57', 'phui-image-mask-css' => '5a8b09c8', 'phui-info-panel-css' => '27ea50a1', 'phui-info-view-css' => '6d7c3509', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index c7dd1287bd..37781a12a5 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1491,6 +1491,7 @@ phutil_register_library_map(array( 'PHUIHandleTagListView' => 'applications/phid/view/PHUIHandleTagListView.php', 'PHUIHandleView' => 'applications/phid/view/PHUIHandleView.php', 'PHUIHeaderView' => 'view/phui/PHUIHeaderView.php', + 'PHUIIconCircleView' => 'view/phui/PHUIIconCircleView.php', 'PHUIIconExample' => 'applications/uiexample/examples/PHUIIconExample.php', 'PHUIIconView' => 'view/phui/PHUIIconView.php', 'PHUIImageMaskExample' => 'applications/uiexample/examples/PHUIImageMaskExample.php', @@ -5640,6 +5641,7 @@ phutil_register_library_map(array( 'PHUIHandleTagListView' => 'AphrontTagView', 'PHUIHandleView' => 'AphrontView', 'PHUIHeaderView' => 'AphrontTagView', + 'PHUIIconCircleView' => 'AphrontTagView', 'PHUIIconExample' => 'PhabricatorUIExample', 'PHUIIconView' => 'AphrontTagView', 'PHUIImageMaskExample' => 'PhabricatorUIExample', diff --git a/src/applications/uiexample/examples/PHUIIconExample.php b/src/applications/uiexample/examples/PHUIIconExample.php index 2644672a1b..3aa746b7b6 100644 --- a/src/applications/uiexample/examples/PHUIIconExample.php +++ b/src/applications/uiexample/examples/PHUIIconExample.php @@ -110,6 +110,26 @@ final class PHUIIconExample extends PhabricatorUIExample { ->addClass(PHUI::MARGIN_SMALL_RIGHT); } + $circles = array('fa-pencil', 'fa-chevron-left', 'fa-chevron-right'); + $circleview = array(); + foreach ($circles as $circle) { + $circleview[] = + id(new PHUIIconCircleView()) + ->setIcon($circle) + ->setHref('#') + ->addClass('mmr'); + } + + $circles = array('fa-plus', 'fa-bars', 'fa-paw'); + foreach ($circles as $circle) { + $circleview[] = + id(new PHUIIconCircleView()) + ->setIcon($circle) + ->setSize(PHUIIconCircleView::MEDIUM) + ->setHref('#') + ->addClass('mmr'); + } + $layout_cicons = id(new PHUIBoxView()) ->appendChild($cicons) ->addMargin(PHUI::MARGIN_LARGE); @@ -130,6 +150,10 @@ final class PHUIIconExample extends PhabricatorUIExample { ->appendChild($tokenview) ->addMargin(PHUI::MARGIN_MEDIUM); + $layout4 = id(new PHUIBoxView()) + ->appendChild($circleview) + ->addMargin(PHUI::MARGIN_MEDIUM); + $layout5 = id(new PHUIBoxView()) ->appendChild($loginview) ->addMargin(PHUI::MARGIN_MEDIUM); @@ -158,6 +182,10 @@ final class PHUIIconExample extends PhabricatorUIExample { ->setHeaderText(pht('Tokens')) ->appendChild($layout3); + $wrap4 = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Circles')) + ->appendChild($layout4); + $wrap5 = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Authentication')) ->appendChild($layout5); @@ -172,6 +200,7 @@ final class PHUIIconExample extends PhabricatorUIExample { $transforms, $wrap2, $wrap3, + $wrap4, $wrap5, )); } diff --git a/src/view/phui/PHUIIconCircleView.php b/src/view/phui/PHUIIconCircleView.php new file mode 100644 index 0000000000..63165c38be --- /dev/null +++ b/src/view/phui/PHUIIconCircleView.php @@ -0,0 +1,67 @@ +href = $href; + return $this; + } + + public function setIcon($icon) { + $this->icon = $icon; + return $this; + } + + public function setColor($color) { + $this->color = $color; + return $this; + } + + public function setSize($size) { + $this->size = $size; + return $this; + } + + protected function getTagName() { + $tag = 'span'; + if ($this->href) { + $tag = 'a'; + } + return $tag; + } + + protected function getTagAttributes() { + require_celerity_resource('phui-icon-view-css'); + + $classes = array(); + $classes[] = 'phui-icon-circle'; + + if ($this->color) { + $classes[] = 'phui-icon-circle-'.$this->color; + } + + if ($this->size) { + $classes[] = $this->size; + } + + return array( + 'href' => $this->href, + 'class' => $classes, + ); + } + + protected function getTagContent() { + return id(new PHUIIconView()) + ->setIconFont($this->icon) + ->addClass($this->color); + } + +} diff --git a/webroot/rsrc/css/phui/phui-icon.css b/webroot/rsrc/css/phui/phui-icon.css index 5df51476d1..ad789768c8 100644 --- a/webroot/rsrc/css/phui/phui-icon.css +++ b/webroot/rsrc/css/phui/phui-icon.css @@ -38,3 +38,45 @@ a.phui-icon-view:hover { text-decoration: none; color: {$sky}; } + +/* - Icon in a Circle ------------------------------------------------------- */ + +.phui-icon-circle { + border: 1px solid {$lightblueborder}; + border-radius: 24px; + height: 24px; + width: 24px; + text-align: center; + display: inline-block; + cursor: pointer; +} + +.phui-icon-circle.circle-medium { + height: 36px; + width: 36px; + border-radius: 36px; +} + +.phui-icon-circle .phui-icon-view { + height: 24px; + width: 24px; + font-size: 11px; + line-height: 24px; + color: {$lightblueborder}; + cursor: pointer; +} + +.phui-icon-circle.circle-medium .phui-icon-view { + font-size: 18px; + line-height: 36px; +} + +a.phui-icon-circle:hover { + text-decoration: none; + border-color: {$sky}; + cursor: pointer; +} + +a.phui-icon-circle:hover .phui-icon-view { + color: {$sky}; +} From 10ef973735b2369d6737d0d012ad704b3a5164d5 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 18 Jan 2016 07:36:28 -0800 Subject: [PATCH 25/66] Allow older, invalid project tags to continue to function Summary: Ref T10168. Around October 12, T9551 made project hashtags stricter and prevented them from containing characters like comma (`,`). Around December 27, D14888 changed how hashtags queries work so that the query does normalization instead of requiring the caller to normalize. After the Dec 27 change, projects from before Oct 12 with now-invalid hashtags will no longer load when queried directly by hashtag, because the page queries for `old,[silly]hash,,tag` or whatever, it gets normalized into `old_silly_hash_tag`, and then there are no hits. Instead, at least for now, query by both the exact raw text and the normalized hashtag. This should keep older stuff working until we can give users more support for migrating forward. Test Plan: - Forced a project to have a bogus hahstag. - Before patch: clicking its tag 404'd. - After patch: clicking its tag now works. - Visited a project by alternate hashtag. - Visited a project by denormalized hashtag and alternate hashtag (e.g., capital letters instead of lowercase letters), saw it redirect/normalize properly. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10168 Differential Revision: https://secure.phabricator.com/D15047 --- .../project/query/PhabricatorProjectQuery.php | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/applications/project/query/PhabricatorProjectQuery.php b/src/applications/project/query/PhabricatorProjectQuery.php index bc14e93a88..e2d678e7d7 100644 --- a/src/applications/project/query/PhabricatorProjectQuery.php +++ b/src/applications/project/query/PhabricatorProjectQuery.php @@ -9,6 +9,7 @@ final class PhabricatorProjectQuery private $slugs; private $slugNormals; private $slugMap; + private $allSlugs; private $names; private $nameTokens; private $icons; @@ -169,10 +170,19 @@ final class PhabricatorProjectQuery protected function willExecute() { $this->slugMap = array(); $this->slugNormals = array(); + $this->allSlugs = array(); if ($this->slugs) { foreach ($this->slugs as $slug) { - $normal = PhabricatorSlug::normalizeProjectSlug($slug); - $this->slugNormals[$slug] = $normal; + if (PhabricatorSlug::isValidProjectSlug($slug)) { + $normal = PhabricatorSlug::normalizeProjectSlug($slug); + $this->slugNormals[$slug] = $normal; + $this->allSlugs[$normal] = $normal; + } + + // NOTE: At least for now, we query for the normalized slugs but also + // for the slugs exactly as entered. This allows older projects with + // slugs that are no longer valid to continue to work. + $this->allSlugs[$slug] = $slug; } } } @@ -380,7 +390,7 @@ final class PhabricatorProjectQuery $where[] = qsprintf( $conn, 'slug.slug IN (%Ls)', - $this->slugNormals); + $this->allSlugs); } if ($this->names !== null) { @@ -625,13 +635,17 @@ final class PhabricatorProjectQuery // else. $unknown = $this->slugNormals; foreach ($unknown as $input => $normal) { - if (!isset($primary_map[$normal])) { + if (isset($primary_map[$input])) { + $match = $input; + } else if (isset($primary_map[$normal])) { + $match = $normal; + } else { continue; } $this->slugMap[$input] = array( - 'slug' => $normal, - 'projectPHID' => $primary_map[$normal]->getPHID(), + 'slug' => $match, + 'projectPHID' => $primary_map[$match]->getPHID(), ); unset($unknown[$input]); @@ -658,13 +672,17 @@ final class PhabricatorProjectQuery // Link up any slugs we were not able to link up earlier. $extra_map = mpull($slugs, 'getProjectPHID', 'getSlug'); foreach ($unknown as $input => $normal) { - if (!isset($extra_map[$normal])) { + if (isset($extra_map[$input])) { + $match = $input; + } else if (isset($extra_map[$normal])) { + $match = $normal; + } else { continue; } $this->slugMap[$input] = array( - 'slug' => $normal, - 'projectPHID' => $extra_map[$normal], + 'slug' => $match, + 'projectPHID' => $extra_map[$match], ); unset($unknown[$input]); From cadd3f1056205bd357a9e5d4e7e47aeb1111d5c6 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 18 Jan 2016 09:09:02 -0800 Subject: [PATCH 26/66] When removing project slugs, try to remove raw slugs too so we can remove old/invalid slugs Summary: Ref T10168. When we try to remove an additional hashtag, we remove the normalized version. Instead, remove both the literal and normalized versions. This allows us to remove old/invalid slugs. Test Plan: Removed garbage slugs like `[,*,]`. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10168 Differential Revision: https://secure.phabricator.com/D15048 --- .../editor/PhabricatorProjectTransactionEditor.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php index 54440a6ee9..c8175e6cd7 100644 --- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php +++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php @@ -756,12 +756,17 @@ final class PhabricatorProjectTransactionEditor } private function removeSlugs(PhabricatorProject $project, array $slugs) { - $slugs = $this->normalizeSlugs($slugs); - if (!$slugs) { return; } + // We're going to try to delete both the literal and normalized versions + // of all slugs. This allows us to destroy old slugs that are no longer + // valid. + foreach ($this->normalizeSlugs($slugs) as $slug) { + $slugs[] = $slug; + } + $objects = id(new PhabricatorProjectSlug())->loadAllWhere( 'projectPHID = %s AND slug IN (%Ls)', $project->getPHID(), From 155cb1d2c5a8066e843f03e4ab3f8c91171e0305 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 18 Jan 2016 09:32:54 -0800 Subject: [PATCH 27/66] Fix two issues with repository monogram regular expressions Summary: Ref T4245. Fixes T10172. These regular expressions were simply incorrect: they intend ` (form one | form two) ` but were written as `( form one) | (form two )` which allowed stuff like "R2/R13" to be interpreted as a monogram because it matches `( form one)`. Test Plan: Parsed commit `ba46ffa6169c` from RTEMS repository, see T10172. Before patch, got an identical trace; after patch, clean import. Reviewers: chad, avivey Reviewed By: avivey Maniphest Tasks: T4245, T10172 Differential Revision: https://secure.phabricator.com/D15049 --- .../repository/phid/PhabricatorRepositoryRepositoryPHIDType.php | 2 +- .../repository/query/PhabricatorRepositoryQuery.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php index 203d17c3ba..c938b31a65 100644 --- a/src/applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php +++ b/src/applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php @@ -48,7 +48,7 @@ final class PhabricatorRepositoryRepositoryPHIDType } public function canLoadNamedObject($name) { - return preg_match('/^r[A-Z]+|R[1-9]\d*\z/', $name); + return preg_match('/^(r[A-Z]+|R[1-9]\d*)\z/', $name); } public function loadNamedObjects( diff --git a/src/applications/repository/query/PhabricatorRepositoryQuery.php b/src/applications/repository/query/PhabricatorRepositoryQuery.php index 0a5e44304f..cbb2b1b3e9 100644 --- a/src/applications/repository/query/PhabricatorRepositoryQuery.php +++ b/src/applications/repository/query/PhabricatorRepositoryQuery.php @@ -65,7 +65,7 @@ final class PhabricatorRepositoryQuery continue; } - if (preg_match('/^(r[A-Z]+)|(R[1-9]\d*)\z/', $identifier)) { + if (preg_match('/^(r[A-Z]+|R[1-9]\d*)\z/', $identifier)) { $monograms[$identifier] = $identifier; continue; } From a9a5991f010ddcc07dd5697bf61b46410b4f6861 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 18 Jan 2016 12:58:19 -0800 Subject: [PATCH 28/66] Update project profile image composer for new IconSet code Summary: Fixes T6856. Fixes T10164. - Make the profile image composer code use the underlying icon name instead of the top-level icon key, so it works instead of 404'ing. - Change the button to show a preview of the profile icon instead of the text "Use Icon and Color". - When creating a new non-milestone project, automatically set the profile image to the icon + color image. Test Plan: - Created several new projects, saw appropriate default icons. - Edited projects, saw icon previews. - Clicked icon buttons to set icons. - Poked around other applications which use builtins (Pholio, user profiles) to look for anything I broke, but everything seemed fine. Reviewers: chad Reviewed By: chad Maniphest Tasks: T6856, T10164 Differential Revision: https://secure.phabricator.com/D15050 --- src/__phutil_library_map__.php | 6 + .../builtin/PhabricatorFilesBuiltinFile.php | 9 + ...PhabricatorFilesComposeIconBuiltinFile.php | 235 ++++++++++++++++++ .../PhabricatorFilesOnDiskBuiltinFile.php | 56 +++++ .../PhabricatorFileComposeController.php | 198 +++------------ .../files/storage/PhabricatorFile.php | 58 ++--- .../pholio/view/PholioMockImagesView.php | 8 +- ...habricatorProjectEditPictureController.php | 105 +++++--- .../PhabricatorProjectTransactionEditor.php | 30 +++ .../project/storage/PhabricatorProject.php | 17 ++ 10 files changed, 496 insertions(+), 226 deletions(-) create mode 100644 src/applications/files/builtin/PhabricatorFilesBuiltinFile.php create mode 100644 src/applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php create mode 100644 src/applications/files/builtin/PhabricatorFilesOnDiskBuiltinFile.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 37781a12a5..1a4684f464 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2314,6 +2314,8 @@ phutil_register_library_map(array( 'PhabricatorFileinfoSetupCheck' => 'applications/config/check/PhabricatorFileinfoSetupCheck.php', 'PhabricatorFilesApplication' => 'applications/files/application/PhabricatorFilesApplication.php', 'PhabricatorFilesApplicationStorageEnginePanel' => 'applications/files/applicationpanel/PhabricatorFilesApplicationStorageEnginePanel.php', + 'PhabricatorFilesBuiltinFile' => 'applications/files/builtin/PhabricatorFilesBuiltinFile.php', + 'PhabricatorFilesComposeIconBuiltinFile' => 'applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php', 'PhabricatorFilesConfigOptions' => 'applications/files/config/PhabricatorFilesConfigOptions.php', 'PhabricatorFilesManagementCatWorkflow' => 'applications/files/management/PhabricatorFilesManagementCatWorkflow.php', 'PhabricatorFilesManagementCompactWorkflow' => 'applications/files/management/PhabricatorFilesManagementCompactWorkflow.php', @@ -2322,6 +2324,7 @@ phutil_register_library_map(array( 'PhabricatorFilesManagementPurgeWorkflow' => 'applications/files/management/PhabricatorFilesManagementPurgeWorkflow.php', 'PhabricatorFilesManagementRebuildWorkflow' => 'applications/files/management/PhabricatorFilesManagementRebuildWorkflow.php', 'PhabricatorFilesManagementWorkflow' => 'applications/files/management/PhabricatorFilesManagementWorkflow.php', + 'PhabricatorFilesOnDiskBuiltinFile' => 'applications/files/builtin/PhabricatorFilesOnDiskBuiltinFile.php', 'PhabricatorFilesOutboundRequestAction' => 'applications/files/action/PhabricatorFilesOutboundRequestAction.php', 'PhabricatorFlag' => 'applications/flag/storage/PhabricatorFlag.php', 'PhabricatorFlagAddFlagHeraldAction' => 'applications/flag/herald/PhabricatorFlagAddFlagHeraldAction.php', @@ -6610,6 +6613,8 @@ phutil_register_library_map(array( 'PhabricatorFileinfoSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorFilesApplication' => 'PhabricatorApplication', 'PhabricatorFilesApplicationStorageEnginePanel' => 'PhabricatorApplicationConfigurationPanel', + 'PhabricatorFilesBuiltinFile' => 'Phobject', + 'PhabricatorFilesComposeIconBuiltinFile' => 'PhabricatorFilesBuiltinFile', 'PhabricatorFilesConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorFilesManagementCatWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementCompactWorkflow' => 'PhabricatorFilesManagementWorkflow', @@ -6618,6 +6623,7 @@ phutil_register_library_map(array( 'PhabricatorFilesManagementPurgeWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementRebuildWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementWorkflow' => 'PhabricatorManagementWorkflow', + 'PhabricatorFilesOnDiskBuiltinFile' => 'PhabricatorFilesBuiltinFile', 'PhabricatorFilesOutboundRequestAction' => 'PhabricatorSystemAction', 'PhabricatorFlag' => array( 'PhabricatorFlagDAO', diff --git a/src/applications/files/builtin/PhabricatorFilesBuiltinFile.php b/src/applications/files/builtin/PhabricatorFilesBuiltinFile.php new file mode 100644 index 0000000000..f1ad3da197 --- /dev/null +++ b/src/applications/files/builtin/PhabricatorFilesBuiltinFile.php @@ -0,0 +1,9 @@ +icon = $icon; + return $this; + } + + public function getIcon() { + return $this->icon; + } + + public function setColor($color) { + $this->color = $color; + return $this; + } + + public function getColor() { + return $this->color; + } + + public function getBuiltinFileKey() { + $icon = $this->getIcon(); + $color = $this->getColor(); + $desc = "compose(icon={$icon}, color={$color})"; + $hash = PhabricatorHash::digestToLength($desc, 40); + return "builtin:{$hash}"; + } + + public function getBuiltinDisplayName() { + $icon = $this->getIcon(); + $color = $this->getColor(); + return "{$icon}-{$color}.png"; + } + + public function loadBuiltinFileData() { + return $this->composeImage($this->getColor(), $this->getIcon()); + } + + public static function getAllIcons() { + $root = dirname(phutil_get_library_root('phabricator')); + $root = $root.'/resources/sprite/projects_2x/'; + + $quips = self::getIconQuips(); + + $map = array(); + $list = Filesystem::listDirectory($root, $include_hidden = false); + foreach ($list as $file) { + $short = preg_replace('/\.png$/', '', $file); + + $map[$short] = array( + 'path' => $root.$file, + 'quip' => idx($quips, $short, $short), + ); + } + + return $map; + } + + public static function getAllColors() { + $colors = id(new CelerityResourceTransformer()) + ->getCSSVariableMap(); + + $colors = array_select_keys( + $colors, + array( + 'red', + 'orange', + 'yellow', + 'green', + 'blue', + 'sky', + 'indigo', + 'violet', + 'pink', + 'charcoal', + 'backdrop', + )); + + $quips = self::getColorQuips(); + + $map = array(); + foreach ($colors as $name => $color) { + $map[$name] = array( + 'color' => $color, + 'quip' => idx($quips, $name, $name), + ); + } + + return $map; + } + + private function composeImage($color, $icon) { + $color_map = self::getAllColors(); + $color = idx($color_map, $color); + if (!$color) { + $fallback = 'backdrop'; + $color = idx($color_map, $fallback); + if (!$color) { + throw new Exception( + pht( + 'Fallback compose color ("%s") does not exist!', + $fallback)); + } + } + + $color_hex = idx($color, 'color'); + $color_const = hexdec(trim($color_hex, '#')); + + $icon_map = self::getAllIcons(); + $icon = idx($icon_map, $icon); + if (!$icon) { + $fallback = 'fa-umbrella'; + $icon = idx($icon_map, $fallback); + if (!$icon) { + throw new Exception( + pht( + 'Fallback compose icon ("%s") does not exist!', + $fallback)); + } + } + + $path = idx($icon, 'path'); + $data = Filesystem::readFile($path); + + $icon_img = imagecreatefromstring($data); + + $canvas = imagecreatetruecolor(100, 100); + imagefill($canvas, 0, 0, $color_const); + imagecopy($canvas, $icon_img, 0, 0, 0, 0, 100, 100); + + return PhabricatorImageTransformer::saveImageDataInAnyFormat( + $canvas, + 'image/png'); + } + + private static function getIconQuips() { + return array( + '8ball' => pht('Take a Risk'), + 'alien' => pht('Foreign Interface'), + 'announce' => pht('Louder is Better'), + 'art' => pht('Unique Snowflake'), + 'award' => pht('Shooting Star'), + 'bacon' => pht('Healthy Vegetables'), + 'bandaid' => pht('Durable Infrastructure'), + 'beer' => pht('Healthy Vegetable Juice'), + 'bomb' => pht('Imminent Success'), + 'briefcase' => pht('Adventure Pack'), + 'bug' => pht('Costumed Egg'), + 'calendar' => pht('Everyone Loves Meetings'), + 'cloud' => pht('Water Cycle'), + 'coffee' => pht('Half-Whip Nonfat Soy Latte'), + 'creditcard' => pht('Expense It'), + 'death' => pht('Calcium Promotes Bone Health'), + 'desktop' => pht('Magical Portal'), + 'dropbox' => pht('Cardboard Box'), + 'education' => pht('Debt'), + 'experimental' => pht('CAUTION: Dangerous Chemicals'), + 'facebook' => pht('Popular Social Network'), + 'facility' => pht('Pollution Solves Problems'), + 'film' => pht('Actual Physical Film'), + 'forked' => pht('You Can\'t Eat Soup'), + 'games' => pht('Serious Business'), + 'ghost' => pht('Haunted'), + 'gift' => pht('Surprise!'), + 'globe' => pht('Scanner Sweep'), + 'golf' => pht('Business Meeting'), + 'heart' => pht('Undergoing a Major Surgery'), + 'intergalactic' => pht('Jupiter'), + 'lock' => pht('Extremely Secret'), + 'mail' => pht('Oragami'), + 'martini' => pht('Healthy Olive Drink'), + 'medical' => pht('Medic!'), + 'mobile' => pht('Cellular Telephone'), + 'music' => pht("\xE2\x99\xAB"), + 'news' => pht('Actual Physical Newspaper'), + 'orgchart' => pht('It\'s Good to be King'), + 'peoples' => pht('Angel and Devil'), + 'piechart' => pht('Actual Physical Pie'), + 'poison' => pht('Healthy Bone Juice'), + 'putabirdonit' => pht('Put a Bird On It'), + 'radiate' => pht('Radiant Beauty'), + 'savings' => pht('Oink Oink'), + 'search' => pht('Sleuthing'), + 'shield' => pht('Royal Crest'), + 'speed' => pht('Slow and Steady'), + 'sprint' => pht('Fire Exit'), + 'star' => pht('The More You Know'), + 'storage' => pht('Stack of Pancakes'), + 'tablet' => pht('Cellular Telephone For Giants'), + 'travel' => pht('Pretty Clearly an Airplane'), + 'twitter' => pht('Bird Stencil'), + 'warning' => pht('No Caution Required, Everything Looks Safe'), + 'whale' => pht('Friendly Walrus'), + 'fa-flask' => pht('Experimental'), + 'fa-briefcase' => pht('Briefcase'), + 'fa-bug' => pht('Bug'), + 'fa-building' => pht('Company'), + 'fa-calendar' => pht('Deadline'), + 'fa-cloud' => pht('The Cloud'), + 'fa-credit-card' => pht('Accounting'), + 'fa-envelope' => pht('Communication'), + 'fa-flag-checkered' => pht('Goal'), + 'fa-folder' => pht('Folder'), + 'fa-group' => pht('Team'), + 'fa-lock' => pht('Policy'), + 'fa-tags' => pht('Tag'), + 'fa-trash-o' => pht('Garbage'), + 'fa-truck' => pht('Release'), + 'fa-umbrella' => pht('An Umbrella'), + ); + } + + private static function getColorQuips() { + return array( + 'red' => pht('Verbillion'), + 'orange' => pht('Navel Orange'), + 'yellow' => pht('Prim Goldenrod'), + 'green' => pht('Lustrous Verdant'), + 'blue' => pht('Tropical Deep'), + 'sky' => pht('Wide Open Sky'), + 'indigo' => pht('Pleated Khaki'), + 'violet' => pht('Aged Merlot'), + 'pink' => pht('Easter Bunny'), + 'charcoal' => pht('Gemstone'), + 'backdrop' => pht('Driven Snow'), + ); + } + +} diff --git a/src/applications/files/builtin/PhabricatorFilesOnDiskBuiltinFile.php b/src/applications/files/builtin/PhabricatorFilesOnDiskBuiltinFile.php new file mode 100644 index 0000000000..b32ea6d39e --- /dev/null +++ b/src/applications/files/builtin/PhabricatorFilesOnDiskBuiltinFile.php @@ -0,0 +1,56 @@ +name = $name; + return $this; + } + + public function getName() { + if ($this->name === null) { + throw new PhutilInvalidStateException('setName'); + } + + return $this->name; + } + + public function getBuiltinDisplayName() { + return $this->getName(); + } + + public function getBuiltinFileKey() { + $name = $this->getName(); + $desc = "disk(name={$name})"; + $hash = PhabricatorHash::digestToLength($desc, 40); + return "builtin:{$hash}"; + } + + public function loadBuiltinFileData() { + $name = $this->getName(); + + $available = $this->getAllBuiltinFiles(); + if (empty($available[$name])) { + throw new Exception(pht('Builtin "%s" does not exist!', $name)); + } + + return Filesystem::readFile($available[$name]); + } + + private function getAllBuiltinFiles() { + $root = dirname(phutil_get_library_root('phabricator')); + $root = $root.'/resources/builtin/'; + + $map = array(); + $list = Filesystem::listDirectory($root, $include_hidden = false); + foreach ($list as $file) { + $map[$file] = $root.$file; + } + + return $map; + } + +} diff --git a/src/applications/files/controller/PhabricatorFileComposeController.php b/src/applications/files/controller/PhabricatorFileComposeController.php index de5a6757a4..3f2667b9d1 100644 --- a/src/applications/files/controller/PhabricatorFileComposeController.php +++ b/src/applications/files/controller/PhabricatorFileComposeController.php @@ -6,21 +6,8 @@ final class PhabricatorFileComposeController public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); - $colors = array( - 'red' => pht('Verbillion'), - 'orange' => pht('Navel Orange'), - 'yellow' => pht('Prim Goldenrod'), - 'green' => pht('Lustrous Verdant'), - 'blue' => pht('Tropical Deep'), - 'sky' => pht('Wide Open Sky'), - 'indigo' => pht('Pleated Khaki'), - 'violet' => pht('Aged Merlot'), - 'pink' => pht('Easter Bunny'), - 'charcoal' => pht('Gemstone'), - 'backdrop' => pht('Driven Snow'), - ); - - $manifest = PHUIIconView::getSheetManifest(PHUIIconView::SPRITE_PROJECTS); + $color_map = PhabricatorFilesComposeIconBuiltinFile::getAllColors(); + $icon_map = $this->getIconMap(); if ($request->isFormPost()) { $project_phid = $request->getStr('projectPHID'); @@ -37,36 +24,21 @@ final class PhabricatorFileComposeController if (!$project) { return new Aphront404Response(); } - $icon = $project->getIcon(); - $color = $project->getColor(); - switch ($color) { - case 'grey': - $color = 'charcoal'; - break; - case 'checkered': - $color = 'backdrop'; - break; - } - } else { - $icon = $request->getStr('icon'); - $color = $request->getStr('color'); } - if (!isset($colors[$color]) || !isset($manifest['projects-'.$icon])) { - return new Aphront404Response(); - } + $icon = $request->getStr('icon'); + $color = $request->getStr('color'); - $root = dirname(phutil_get_library_root('phabricator')); - $icon_file = $root.'/resources/sprite/projects_2x/'.$icon.'.png'; - $icon_data = Filesystem::readFile($icon_file); + $composer = id(new PhabricatorFilesComposeIconBuiltinFile()) + ->setIcon($icon) + ->setColor($color); - - $data = $this->composeImage($color, $icon_data); + $data = $composer->loadBuiltinFileData(); $file = PhabricatorFile::buildFromFileDataOrHash( $data, array( - 'name' => 'project.png', + 'name' => $composer->getBuiltinDisplayName(), 'profile' => true, 'canCDN' => true, )); @@ -97,14 +69,15 @@ final class PhabricatorFileComposeController } } - $value_color = head_key($colors); - $value_icon = head_key($manifest); - $value_icon = substr($value_icon, strlen('projects-')); + $value_color = head_key($color_map); + $value_icon = head_key($icon_map); require_celerity_resource('people-profile-css'); $buttons = array(); - foreach ($colors as $color => $name) { + foreach ($color_map as $color => $info) { + $quip = idx($info, 'quip'); + $buttons[] = javelin_tag( 'button', array( @@ -113,116 +86,17 @@ final class PhabricatorFileComposeController 'style' => 'margin: 0 8px 8px 0', 'meta' => array( 'color' => $color, - 'tip' => $name, + 'tip' => $quip, ), ), id(new PHUIIconView()) ->addClass('compose-background-'.$color)); } - $sort_these_first = array( - 'projects-fa-briefcase', - 'projects-fa-tags', - 'projects-fa-folder', - 'projects-fa-group', - 'projects-fa-bug', - 'projects-fa-trash-o', - 'projects-fa-calendar', - 'projects-fa-flag-checkered', - 'projects-fa-envelope', - 'projects-fa-truck', - 'projects-fa-lock', - 'projects-fa-umbrella', - 'projects-fa-cloud', - 'projects-fa-building', - 'projects-fa-credit-card', - 'projects-fa-flask', - ); - - $manifest = array_select_keys( - $manifest, - $sort_these_first) - + $manifest; $icons = array(); - - $icon_quips = array( - '8ball' => pht('Take a Risk'), - 'alien' => pht('Foreign Interface'), - 'announce' => pht('Louder is Better'), - 'art' => pht('Unique Snowflake'), - 'award' => pht('Shooting Star'), - 'bacon' => pht('Healthy Vegetables'), - 'bandaid' => pht('Durable Infrastructure'), - 'beer' => pht('Healthy Vegetable Juice'), - 'bomb' => pht('Imminent Success'), - 'briefcase' => pht('Adventure Pack'), - 'bug' => pht('Costumed Egg'), - 'calendar' => pht('Everyone Loves Meetings'), - 'cloud' => pht('Water Cycle'), - 'coffee' => pht('Half-Whip Nonfat Soy Latte'), - 'creditcard' => pht('Expense It'), - 'death' => pht('Calcium Promotes Bone Health'), - 'desktop' => pht('Magical Portal'), - 'dropbox' => pht('Cardboard Box'), - 'education' => pht('Debt'), - 'experimental' => pht('CAUTION: Dangerous Chemicals'), - 'facebook' => pht('Popular Social Network'), - 'facility' => pht('Pollution Solves Problems'), - 'film' => pht('Actual Physical Film'), - 'forked' => pht('You Can\'t Eat Soup'), - 'games' => pht('Serious Business'), - 'ghost' => pht('Haunted'), - 'gift' => pht('Surprise!'), - 'globe' => pht('Scanner Sweep'), - 'golf' => pht('Business Meeting'), - 'heart' => pht('Undergoing a Major Surgery'), - 'intergalactic' => pht('Jupiter'), - 'lock' => pht('Extremely Secret'), - 'mail' => pht('Oragami'), - 'martini' => pht('Healthy Olive Drink'), - 'medical' => pht('Medic!'), - 'mobile' => pht('Cellular Telephone'), - 'music' => pht("\xE2\x99\xAB"), - 'news' => pht('Actual Physical Newspaper'), - 'orgchart' => pht('It\'s Good to be King'), - 'peoples' => pht('Angel and Devil'), - 'piechart' => pht('Actual Physical Pie'), - 'poison' => pht('Healthy Bone Juice'), - 'putabirdonit' => pht('Put a Bird On It'), - 'radiate' => pht('Radiant Beauty'), - 'savings' => pht('Oink Oink'), - 'search' => pht('Sleuthing'), - 'shield' => pht('Royal Crest'), - 'speed' => pht('Slow and Steady'), - 'sprint' => pht('Fire Exit'), - 'star' => pht('The More You Know'), - 'storage' => pht('Stack of Pancakes'), - 'tablet' => pht('Cellular Telephone For Giants'), - 'travel' => pht('Pretty Clearly an Airplane'), - 'twitter' => pht('Bird Stencil'), - 'warning' => pht('No Caution Required, Everything Looks Safe'), - 'whale' => pht('Friendly Walrus'), - 'fa-flask' => pht('Experimental'), - 'fa-briefcase' => pht('Briefcase'), - 'fa-bug' => pht('Bug'), - 'fa-building' => pht('Company'), - 'fa-calendar' => pht('Deadline'), - 'fa-cloud' => pht('The Cloud'), - 'fa-credit-card' => pht('Accounting'), - 'fa-envelope' => pht('Communication'), - 'fa-flag-checkered' => pht('Goal'), - 'fa-folder' => pht('Folder'), - 'fa-group' => pht('Team'), - 'fa-lock' => pht('Policy'), - 'fa-tags' => pht('Tag'), - 'fa-trash-o' => pht('Garbage'), - 'fa-truck' => pht('Release'), - 'fa-umbrella' => pht('An Umbrella'), - ); - - foreach ($manifest as $icon => $spec) { - $icon = substr($icon, strlen('projects-')); + foreach ($icon_map as $icon => $spec) { + $quip = idx($spec, 'quip'); $icons[] = javelin_tag( 'button', @@ -232,7 +106,7 @@ final class PhabricatorFileComposeController 'style' => 'margin: 0 8px 8px 0', 'meta' => array( 'icon' => $icon, - 'tip' => idx($icon_quips, $icon, $icon), + 'tip' => $quip, ), ), id(new PHUIIconView()) @@ -318,23 +192,31 @@ final class PhabricatorFileComposeController return id(new AphrontDialogResponse())->setDialog($dialog); } - private function composeImage($color, $icon_data) { - $icon_img = imagecreatefromstring($icon_data); + private function getIconMap() { + $icon_map = PhabricatorFilesComposeIconBuiltinFile::getAllIcons(); - $map = id(new CelerityResourceTransformer()) - ->getCSSVariableMap(); + $first = array( + 'fa-briefcase', + 'fa-tags', + 'fa-folder', + 'fa-group', + 'fa-bug', + 'fa-trash-o', + 'fa-calendar', + 'fa-flag-checkered', + 'fa-envelope', + 'fa-truck', + 'fa-lock', + 'fa-umbrella', + 'fa-cloud', + 'fa-building', + 'fa-credit-card', + 'fa-flask', + ); - $color_string = idx($map, $color, '#ff00ff'); - $color_const = hexdec(trim($color_string, '#')); + $icon_map = array_select_keys($icon_map, $first) + $icon_map; - $canvas = imagecreatetruecolor(100, 100); - imagefill($canvas, 0, 0, $color_const); - - imagecopy($canvas, $icon_img, 0, 0, 0, 0, 100, 100); - - return PhabricatorImageTransformer::saveImageDataInAnyFormat( - $canvas, - 'image/png'); + return $icon_map; } } diff --git a/src/applications/files/storage/PhabricatorFile.php b/src/applications/files/storage/PhabricatorFile.php index f0a5f228e3..92dd0bcf88 100644 --- a/src/applications/files/storage/PhabricatorFile.php +++ b/src/applications/files/storage/PhabricatorFile.php @@ -961,16 +961,18 @@ final class PhabricatorFile extends PhabricatorFileDAO * Builtins are located in `resources/builtin/` and identified by their * name. * - * @param PhabricatorUser Viewing user. - * @param list List of builtin file names. - * @return dict Dictionary of named builtins. + * @param PhabricatorUser Viewing user. + * @param list List of builtin file specs. + * @return dict Dictionary of named builtins. */ - public static function loadBuiltins(PhabricatorUser $user, array $names) { + public static function loadBuiltins(PhabricatorUser $user, array $builtins) { + $builtins = mpull($builtins, null, 'getBuiltinFileKey'); + $specs = array(); - foreach ($names as $name) { + foreach ($builtins as $key => $buitin) { $specs[] = array( 'originalPHID' => PhabricatorPHIDConstants::PHID_VOID, - 'transform' => 'builtin:'.$name, + 'transform' => $key, ); } @@ -981,41 +983,34 @@ final class PhabricatorFile extends PhabricatorFileDAO ->withTransforms($specs) ->execute(); - $files = mpull($files, null, 'getName'); - - $root = dirname(phutil_get_library_root('phabricator')); - $root = $root.'/resources/builtin/'; + $results = array(); + foreach ($files as $file) { + $builtin_key = $file->getBuiltinName(); + if ($builtin_key !== null) { + $results[$builtin_key] = $file; + } + } $build = array(); - foreach ($names as $name) { - if (isset($files[$name])) { + foreach ($builtins as $key => $builtin) { + if (isset($results[$key])) { continue; } - // This is just a sanity check to prevent loading arbitrary files. - if (basename($name) != $name) { - throw new Exception(pht("Invalid builtin name '%s'!", $name)); - } + $data = $builtin->loadBuiltinFileData(); - $path = $root.$name; - - if (!Filesystem::pathExists($path)) { - throw new Exception(pht("Builtin '%s' does not exist!", $path)); - } - - $data = Filesystem::readFile($path); $params = array( - 'name' => $name, + 'name' => $builtin->getBuiltinDisplayName(), 'ttl' => time() + (60 * 60 * 24 * 7), 'canCDN' => true, - 'builtin' => $name, + 'builtin' => $key, ); $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); $file = self::newFromFileData($data, $params); $xform = id(new PhabricatorTransformedFile()) ->setOriginalPHID(PhabricatorPHIDConstants::PHID_VOID) - ->setTransform('builtin:'.$name) + ->setTransform($key) ->setTransformedPHID($file->getPHID()) ->save(); unset($unguarded); @@ -1023,10 +1018,10 @@ final class PhabricatorFile extends PhabricatorFileDAO $file->attachObjectPHIDs(array()); $file->attachObjects(array()); - $files[$name] = $file; + $results[$key] = $file; } - return $files; + return $results; } @@ -1038,7 +1033,12 @@ final class PhabricatorFile extends PhabricatorFileDAO * @return PhabricatorFile Corresponding builtin file. */ public static function loadBuiltin(PhabricatorUser $user, $name) { - return idx(self::loadBuiltins($user, array($name)), $name); + $builtin = id(new PhabricatorFilesOnDiskBuiltinFile()) + ->setName($name); + + $key = $builtin->getBuiltinFileKey(); + + return idx(self::loadBuiltins($user, array($builtin)), $key); } public function getObjects() { diff --git a/src/applications/pholio/view/PholioMockImagesView.php b/src/applications/pholio/view/PholioMockImagesView.php index cf8d0c6143..8430ada3d4 100644 --- a/src/applications/pholio/view/PholioMockImagesView.php +++ b/src/applications/pholio/view/PholioMockImagesView.php @@ -68,11 +68,9 @@ final class PholioMockImagesView extends AphrontView { // TODO: We could maybe do a better job with tailoring this, which is the // image shown on the review stage. - $default_name = 'image-100x100.png'; - $builtins = PhabricatorFile::loadBuiltins( - $this->getUser(), - array($default_name)); - $default = $builtins[$default_name]; + $viewer = $this->getUser(); + + $default = PhabricatorFile::loadBuiltin($viewer, 'image-100x100.png'); $engine = id(new PhabricatorMarkupEngine()) ->setViewer($this->getUser()); diff --git a/src/applications/project/controller/PhabricatorProjectEditPictureController.php b/src/applications/project/controller/PhabricatorProjectEditPictureController.php index 8828bfae57..41ccb94eb3 100644 --- a/src/applications/project/controller/PhabricatorProjectEditPictureController.php +++ b/src/applications/project/controller/PhabricatorProjectEditPictureController.php @@ -123,7 +123,7 @@ final class PhabricatorProjectEditPictureController $images[PhabricatorPHIDConstants::PHID_VOID] = array( 'uri' => $default_image->getBestURI(), - 'tip' => pht('Default Picture'), + 'tip' => pht('No Picture'), ); require_celerity_resource('people-profile-css'); @@ -181,7 +181,11 @@ final class PhabricatorProjectEditPictureController $form->appendChild( id(new AphrontFormMarkupControl()) ->setLabel(pht('Use Picture')) - ->setValue($buttons)); + ->setValue( + array( + $this->renderDefaultForm($project), + $buttons, + ))); $launch_id = celerity_generate_unique_node_id(); $input_id = celerity_generate_unique_node_id(); @@ -226,38 +230,6 @@ final class PhabricatorProjectEditPictureController ->setLabel(pht('Quick Create')) ->setValue($compose_form)); - $default_button = javelin_tag( - 'button', - array( - 'class' => 'grey', - ), - pht('Use Project Icon')); - - $default_input = javelin_tag( - 'input', - array( - 'type' => 'hidden', - 'name' => 'projectPHID', - 'value' => $project->getPHID(), - )); - - $default_form = phabricator_form( - $viewer, - array( - 'class' => 'profile-image-form', - 'method' => 'POST', - 'action' => '/file/compose/', - ), - array( - $default_input, - $default_button, - )); - - $form->appendChild( - id(new AphrontFormMarkupControl()) - ->setLabel(pht('Use Default')) - ->setValue($default_form)); - $upload_form = id(new AphrontFormView()) ->setUser($viewer) ->setEncType('multipart/form-data') @@ -294,4 +266,69 @@ final class PhabricatorProjectEditPictureController $upload_box, )); } + + private function renderDefaultForm(PhabricatorProject $project) { + $viewer = $this->getViewer(); + $compose_color = $project->getDisplayIconComposeColor(); + $compose_icon = $project->getDisplayIconComposeIcon(); + + $default_builtin = id(new PhabricatorFilesComposeIconBuiltinFile()) + ->setColor($compose_color) + ->setIcon($compose_icon); + + $file_builtins = PhabricatorFile::loadBuiltins( + $viewer, + array($default_builtin)); + + $file_builtin = head($file_builtins); + + $default_button = javelin_tag( + 'button', + array( + 'class' => 'grey profile-image-button', + 'sigil' => 'has-tooltip', + 'meta' => array( + 'tip' => pht('Use Icon and Color'), + 'size' => 300, + ), + ), + phutil_tag( + 'img', + array( + 'height' => 50, + 'width' => 50, + 'src' => $file_builtin->getBestURI(), + ))); + + $inputs = array( + 'projectPHID' => $project->getPHID(), + 'icon' => $compose_icon, + 'color' => $compose_color, + ); + + foreach ($inputs as $key => $value) { + $inputs[$key] = javelin_tag( + 'input', + array( + 'type' => 'hidden', + 'name' => $key, + 'value' => $value, + )); + } + + $default_form = phabricator_form( + $viewer, + array( + 'class' => 'profile-image-form', + 'method' => 'POST', + 'action' => '/file/compose/', + ), + array( + $inputs, + $default_button, + )); + + return $default_form; + } + } diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php index c8175e6cd7..26cc3af86e 100644 --- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php +++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php @@ -713,6 +713,10 @@ final class PhabricatorProjectTransactionEditor } } + if ($this->getIsNewObject()) { + $this->setDefaultProfilePicture($object); + } + // TODO: We should dump an informational transaction onto the parent // project to show that we created the sub-thing. @@ -886,5 +890,31 @@ final class PhabricatorProjectTransactionEditor return $results; } + private function setDefaultProfilePicture(PhabricatorProject $project) { + if ($project->isMilestone()) { + return; + } + + $compose_color = $project->getDisplayIconComposeColor(); + $compose_icon = $project->getDisplayIconComposeIcon(); + + $builtin = id(new PhabricatorFilesComposeIconBuiltinFile()) + ->setColor($compose_color) + ->setIcon($compose_icon); + + $data = $builtin->loadBuiltinFileData(); + + $file = PhabricatorFile::newFromFileData( + $data, + array( + 'name' => $builtin->getBuiltinDisplayName(), + 'profile' => true, + 'canCDN' => true, + )); + + $project + ->setProfileImagePHID($file->getPHID()) + ->save(); + } } diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php index 387882df2c..ceaac1a16d 100644 --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -519,6 +519,23 @@ final class PhabricatorProject extends PhabricatorProjectDAO return $this->getColor(); } + public function getDisplayIconComposeIcon() { + $icon = $this->getDisplayIconIcon(); + return $icon; + } + + public function getDisplayIconComposeColor() { + $color = $this->getDisplayColor(); + + $map = array( + 'grey' => 'charcoal', + 'checkered' => 'backdrop', + ); + + return idx($map, $color, $color); + } + + /* -( PhabricatorSubscribableInterface )----------------------------------- */ From 550793f9a4f01a8959dd679b96aa035bc8494d7b Mon Sep 17 00:00:00 2001 From: Chad Little Date: Mon, 18 Jan 2016 20:59:06 -0800 Subject: [PATCH 29/66] Remove header gradients for flat colors Summary: Removes header gradient images for flat, CSS controlled colors. I didn't convert the "pony" colors over, going with few options for easier theme-ability. Test Plan: Test each color choice. {F1063828} Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D15052 --- resources/celerity/map.php | 19 ++--- resources/sprite/main_header/applebloom.png | Bin 174 -> 0 bytes resources/sprite/main_header/blindigo.png | Bin 1189 -> 0 bytes resources/sprite/main_header/blue.png | Bin 401 -> 0 bytes resources/sprite/main_header/dark.png | Bin 423 -> 0 bytes resources/sprite/main_header/fluttershy.png | Bin 171 -> 0 bytes resources/sprite/main_header/green.png | Bin 432 -> 0 bytes resources/sprite/main_header/indigo.png | Bin 943 -> 0 bytes resources/sprite/main_header/light.png | Bin 1033 -> 0 bytes .../sprite/main_header/nightmaremoon.png | Bin 269 -> 0 bytes resources/sprite/main_header/red.png | Bin 406 -> 0 bytes resources/sprite/main_header/scootaloo.png | Bin 153 -> 0 bytes resources/sprite/main_header/yellow.png | Bin 421 -> 0 bytes resources/sprite/manifest/main-header.json | 70 ------------------ scripts/celerity/generate_sprites.php | 1 - .../celerity/CeleritySpriteGenerator.php | 27 ------- .../option/PhabricatorUIConfigOptions.php | 15 ++-- .../page/menu/PhabricatorMainMenuView.php | 3 +- .../css/application/base/main-menu-view.css | 6 +- .../rsrc/css/application/base/phui-theme.css | 32 +++++++- webroot/rsrc/css/sprite-main-header.css | 60 --------------- webroot/rsrc/image/sprite-main-header.png | Bin 2014 -> 0 bytes 22 files changed, 50 insertions(+), 183 deletions(-) delete mode 100644 resources/sprite/main_header/applebloom.png delete mode 100644 resources/sprite/main_header/blindigo.png delete mode 100644 resources/sprite/main_header/blue.png delete mode 100644 resources/sprite/main_header/dark.png delete mode 100644 resources/sprite/main_header/fluttershy.png delete mode 100644 resources/sprite/main_header/green.png delete mode 100644 resources/sprite/main_header/indigo.png delete mode 100644 resources/sprite/main_header/light.png delete mode 100644 resources/sprite/main_header/nightmaremoon.png delete mode 100644 resources/sprite/main_header/red.png delete mode 100644 resources/sprite/main_header/scootaloo.png delete mode 100644 resources/sprite/main_header/yellow.png delete mode 100644 resources/sprite/manifest/main-header.json delete mode 100644 webroot/rsrc/css/sprite-main-header.css delete mode 100644 webroot/rsrc/image/sprite-main-header.png diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 7a4a3ce4eb..c5569127bb 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => '9d3a79f4', + 'core.pkg.css' => 'c61091b0', 'core.pkg.js' => '573e6664', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -32,10 +32,10 @@ return array( 'rsrc/css/aphront/typeahead.css' => '0e403212', 'rsrc/css/application/almanac/almanac.css' => 'dbb9b3af', 'rsrc/css/application/auth/auth.css' => '0877ed6e', - 'rsrc/css/application/base/main-menu-view.css' => '2f670a96', + 'rsrc/css/application/base/main-menu-view.css' => 'd00a795a', 'rsrc/css/application/base/notification-menu.css' => 'f31c0bde', 'rsrc/css/application/base/phabricator-application-launch-view.css' => '95351601', - 'rsrc/css/application/base/phui-theme.css' => '6b451f24', + 'rsrc/css/application/base/phui-theme.css' => '981a58f8', 'rsrc/css/application/base/standard-page-view.css' => '7b0d68d8', 'rsrc/css/application/chatlog/chatlog.css' => 'd295b020', 'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4', @@ -155,7 +155,6 @@ return array( 'rsrc/css/phui/phui-workboard-view.css' => '95a54f74', 'rsrc/css/phui/phui-workpanel-view.css' => 'adec7699', 'rsrc/css/sprite-login.css' => '60e8560e', - 'rsrc/css/sprite-main-header.css' => 'f07bbb87', 'rsrc/css/sprite-menu.css' => '9dd65b92', 'rsrc/css/sprite-projects.css' => 'e5ad842a', 'rsrc/css/sprite-tokens.css' => '4f399012', @@ -336,7 +335,6 @@ return array( 'rsrc/image/phrequent_inactive.png' => 'bfc15a69', 'rsrc/image/sprite-login-X2.png' => 'e3991e37', 'rsrc/image/sprite-login.png' => '03d5af29', - 'rsrc/image/sprite-main-header.png' => '3673af44', 'rsrc/image/sprite-menu-X2.png' => 'cfd8fca5', 'rsrc/image/sprite-menu.png' => 'd7a99faa', 'rsrc/image/sprite-projects-X2.png' => '853552c7', @@ -753,7 +751,7 @@ return array( 'phabricator-hovercard-view-css' => '1239cd52', 'phabricator-keyboard-shortcut' => '1ae869f2', 'phabricator-keyboard-shortcut-manager' => 'c1700f6f', - 'phabricator-main-menu-view' => '2f670a96', + 'phabricator-main-menu-view' => 'd00a795a', 'phabricator-nav-view-css' => 'a24cb589', 'phabricator-notification' => 'ccf1cbf8', 'phabricator-notification-css' => '9c279160', @@ -829,7 +827,7 @@ return array( 'phui-status-list-view-css' => '888cedb8', 'phui-tag-view-css' => 'e60e227b', 'phui-text-css' => 'cf019f54', - 'phui-theme-css' => '6b451f24', + 'phui-theme-css' => '981a58f8', 'phui-timeline-view-css' => '2efceff8', 'phui-two-column-view-css' => '39ecafb1', 'phui-workboard-view-css' => '95a54f74', @@ -853,7 +851,6 @@ return array( 'releeph-request-typeahead-css' => '667a48ae', 'setup-issue-css' => 'db7e9c40', 'sprite-login-css' => '60e8560e', - 'sprite-main-header-css' => 'f07bbb87', 'sprite-menu-css' => '9dd65b92', 'sprite-projects-css' => 'e5ad842a', 'sprite-tokens-css' => '4f399012', @@ -1054,9 +1051,6 @@ return array( 'javelin-install', 'javelin-event', ), - '2f670a96' => array( - 'phui-theme-css', - ), '327a00d1' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1852,6 +1846,9 @@ return array( 'javelin-workflow', 'phabricator-drag-and-drop-file-upload', ), + 'd00a795a' => array( + 'phui-theme-css', + ), 'd19198c8' => array( 'javelin-install', 'javelin-dom', diff --git a/resources/sprite/main_header/applebloom.png b/resources/sprite/main_header/applebloom.png deleted file mode 100644 index 29721ef8fd95bcd738be9dfc679a4c95456dd1b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^Y(T8T!2~2v&W!U1Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>JiUK@c978H@C9Mp+knX^$^I!4;qcF3flg|JD!b`b=I~pI_ ze?9Zdzh~8diD$x@HWS|+de-qjq{Oz;vE!d^_!U5uW<@r7Gz*#WBB{e Vz|x4FPX=f8U}fi7AzZCsS=07??FOLn2Bde0{8v^K(3-T9Ob#X~hD#969RTqa;7NqJ2 zr55Lx79|7YBTX5m85nl>EdnV7y2i>SKe;qFHLt|e#a0O@qL-4HVr61vVeV|^=ICT$ zZeVEWYT{(IVYl&B{m2**QVo82cNPd0} zEcOC2@=NlIGx7@*oSnh3rJ&)Pn4Fmh64V3*Fx0)NMVV!(DQ-pixeDMAvdYBb3Ntqg zXEzHsOD97UH?R*Z%p6?}oh&R&Obkq2jEt3_dQ-6Y9;(+7r(S)aWAs7Mixk~3Az&H; zG2w|9$bl#S)I4CCF9IfR-g3z_1_nl9PZ!6Kid!K;orOmnIGp8Hd2_E+UAwrUq9(oi z+HZ!{?EioM-TeOf!op=Kwa3`62}@o09hY6*-u3GK8dJLv&Rm!IyUw<`T{#oFgKu+9 zp0mQ4Wq#|-wU*C_esyHC#i!7PZVxX^6%IaFv15i5r zVuV42?Lr|!VyQ6gR1eXu937(y>mr7pL=*8To3^^6GZYnvBTUicZ!>$5at3jvn}TEb z>NskaW=-CPB&J-aqt?t&tis9)KOG0x-b&$c2vh}52~D`gtawh$vh2}>-+GMGaZHJh zZ8*y9h-rCIm9oo{a*4Tw#kcd6eO+QH!?Bco6&bfTCu{eZ>u%j}@t{3Y{g2trdd$-i zH?8%nZDAAIG2nqj&mxoIVLcAV_o?bVc1ImJA+bAZ9h>!NiXLA}Q@c9W3+sE_zxV7H vvB6*Xp-`$^_+F|T|0-U8)&DvIPXPu1Bl#9LOr}f}00000NkvXXu0mjfZpW@L diff --git a/resources/sprite/main_header/dark.png b/resources/sprite/main_header/dark.png deleted file mode 100644 index f676a0d1b8754fbc335ef6a760dcfc7079fcd7f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 423 zcmV;Y0a*TtP)-*h<&}idC-0 z7tujfVd{0O5D{WoH1eZRwG8>oUFnVr>d4>tAQ0lfq`Ip&L=Y_+Uqpl*I~2qi5D4R^ zsv0Lz--x#vo6f|0=RU--0VG&GiQ$<(dE7~in@S?W03G`vrV^itJ>CHm_FuWZ;_6+i zoUiQmT)lOijc}A)raCG%^2Dd8|JYuyw5A~98j4u=5ybuU2!XJ-f8$Sp0RS2)N`jg2 RYRLcq002ovPDHLkV1nFKx<~*3 diff --git a/resources/sprite/main_header/fluttershy.png b/resources/sprite/main_header/fluttershy.png deleted file mode 100644 index 796158d39b1bf0d53f0440f3ed2cc1d7561ecd6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^Y(T8T!2~2v&W!U1Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>JihMm?978H@C9Ul7OLt(^;rV~jMPi18M27%V)*t^VT2Zr( zev%LFV04x=>rJ`cv2vn^{lEYI>E#pOFZ`e4CKdL$vxo1Nny}H?LrN?H2@KDpb(R*Y S3vB`#%;4$j=d#Wzp$P!7GdRrv diff --git a/resources/sprite/main_header/green.png b/resources/sprite/main_header/green.png deleted file mode 100644 index 6c84d1deaa8e700665eb696aca98f1646f5cc700..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 432 zcmV;h0Z;ykP)vX# a0t^6V_A#{cbr?th0000 diff --git a/resources/sprite/main_header/indigo.png b/resources/sprite/main_header/indigo.png deleted file mode 100644 index ac38dfbdcd5db30ce2a871e8688432af345286f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 943 zcmaJ=-HOvd6wWHjvbf--3c`?ub%kvvN&k}2xNVch7B;nXBlb#mnoQf!O(rH&oAye) z^9jV4@C8J?UcB>4e2K+3aMEqMURV>7nK_*AJKy=4554a5{k=zf9LMc<+Gd}vciDHm zdyD-qKfQjzmWQ-8pl4)6=P1Tp!y`isIsqEvK1SZ+%_XjJ-0dUZ8PI`!s<|W(Q060~ zLB!A;S35}~jR(G`^RLRbXh#N~`0Ztk&z4=sT~1xq<4>M}TBPhoRC@Uvc`=LvQUv`#28T$JA_>1RqRa&CCP+Dz%W)-14lM;{V+2= zU7>7S>x2nKp^H1F&NCjt_dTs*DTbw3YEvp%lGG|Sl}e)}H5H{)63eDs%&{hMX8{gr zj`eP^jjh;hAcBZRHgW8~#hw+D0IU+%{Oww*Tlv;lZ@U&{D;6>_Fl+B$?aobXhO+Hu zc-dhy{y1baAG6{9`tz#IF2>`I*>KWd!{0wbT)%UA@4>keN diff --git a/resources/sprite/main_header/light.png b/resources/sprite/main_header/light.png deleted file mode 100644 index cd786082f039232153ec9f46c42f23c864c76a93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1033 zcmaJ=Pixdb6b~(k6f53Dp)jPEDorx^x5`tb2&>&)ug}+e z{M)?0#Q#^H-t6<`3G;{SkdD{{7er{sG$f##;v>>0IG(<{B3pv6e4Y%3Y}k9{L^PFg zts_@y&e4LfwO!>nIwlN+8%Vsa$bp*WvqGtcYNy!j4^WPHNaY03BKoV9G5if~o;5B&%l2Le?hG z_*sFrqCp8F$J8CDfyEB#Ng@sc^2SGE~yEj%%h} zvOf7w<5ul*FwKe5CnY^CB3_TtdIRRUyW3H%$k{miMZ$}MPdpl(rX*us&lUNN94E08 zpuh@DXh2OjRMj_a+f#!;)7#MYcl>s%v2hy~S~f!Mz=xXMsTW<(TH6)0tHqZ1ixHWVP^FU8H%;9x0Od zBn}Fif?1ZGh{XjyzLC9omvRY@ByR{g znt>o`g_dOC5tLNbvL&RMp+r=hjEL2083q;=PEn~F=SCwnBHo?#_IfP%;d-!0#;2*^ zW3%!2^H)A{YhABBsD6dhzrWX(pT7-%2p2o`d-*|FdLUdpTn0ZMvCDcmyZ)Z{W#{er EKT+mA)&Kwi diff --git a/resources/sprite/main_header/nightmaremoon.png b/resources/sprite/main_header/nightmaremoon.png deleted file mode 100644 index 2e985507955cdf356c0c9ae570794d9a4d60b771..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 269 zcmV+o0rLKdP)`vTH9&?-7t*h6|Goa(5n3zt>91J&zLR+cf_!A2MjB_N6Xs|Em!PP z)L>{$M9Z2DT1E%7j0ve#B2vm@sFX`ASs;=sMbaQ5(g~6pZ(>antsk1rM}PqU3{>zC TERKm+00000NkvXXu0mjf;ah0& diff --git a/resources/sprite/main_header/red.png b/resources/sprite/main_header/red.png deleted file mode 100644 index 2620221ec655518287de1b8f4a2868d9bb7c3e1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmV;H0crk;P)sRQ=zK03QIE;X3q;k-;LTR zs^QW8jzD8uzs~qWY%ycGU1k28SmpUG*7_4*0AD`{XX+VU761SM07*qoM6N<$g0M2T AuK)l5 diff --git a/resources/sprite/main_header/scootaloo.png b/resources/sprite/main_header/scootaloo.png deleted file mode 100644 index 32e724ec5e50eed5a07a0ee1338d0823a288e169..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^Y(T8T!2~2v&W!U1Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>JimW|d978H@C3Rl^oaDgj!z0nq`tX1Kq7cIi7j)J*NhBS~ zQn@c^vTb74vB_(@j=fuy<{+Fc#;kjmiNk<_$5hv&%&1o%Xbgj=tDnm{r-UW|4<;~# diff --git a/resources/sprite/main_header/yellow.png b/resources/sprite/main_header/yellow.png deleted file mode 100644 index a8a4d67f0ba9333444611b48287d8de0258b4a8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 421 zcmV;W0b2fvP)!b(Pd8;U3M)xpd?T$y*QgJ}hX!M5TK#cB+?A1`aPIC}_0;s(aq}3$P zPiio1Rg(B2XdK+TGlgd~;Hd6+?;C-4Z|Z^;s8nTdfp>J29#NCnx9n>wUig`X$T;0S z81W&%7K(<2rTX2Rsc6~YTxJTCSx12DEGZ>2u}%VV4sQ>*%wgwqp6g~!Kl=fmk)oAUjYUHKshK>m#Nv_ P00000NkvXXu0mjflZC*R diff --git a/resources/sprite/manifest/main-header.json b/resources/sprite/manifest/main-header.json deleted file mode 100644 index 0e3f6a4404..0000000000 --- a/resources/sprite/manifest/main-header.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "version": 1, - "sprites": { - "main-header-applebloom": { - "name": "main-header-applebloom", - "rule": ".phui-theme-applebloom .phabricator-main-menu-background", - "hash": "64822776b129e724709983db1ac5a712" - }, - "main-header-blindigo": { - "name": "main-header-blindigo", - "rule": ".phui-theme-blindigo .phabricator-main-menu-background", - "hash": "8c4f5b1f1f3faceb6ca6e8278a1b082f" - }, - "main-header-blue": { - "name": "main-header-blue", - "rule": ".phui-theme-blue .phabricator-main-menu-background", - "hash": "b5dd317b7bd35e0592b3f4b66267437c" - }, - "main-header-dark": { - "name": "main-header-dark", - "rule": ".phui-theme-dark .phabricator-main-menu-background", - "hash": "817815d84c0c935b4875f6ecc7dbb526" - }, - "main-header-fluttershy": { - "name": "main-header-fluttershy", - "rule": ".phui-theme-fluttershy .phabricator-main-menu-background", - "hash": "55d4e9f813cf354693290105cf83cf78" - }, - "main-header-green": { - "name": "main-header-green", - "rule": ".phui-theme-green .phabricator-main-menu-background", - "hash": "c230f09e307d167fab3ea0d8c3b33755" - }, - "main-header-indigo": { - "name": "main-header-indigo", - "rule": ".phui-theme-indigo .phabricator-main-menu-background", - "hash": "a27394ff1eff4d24398ec57e54d7f5fd" - }, - "main-header-light": { - "name": "main-header-light", - "rule": ".phui-theme-light .phabricator-main-menu-background", - "hash": "3c41fbfbe13cae2451467a1e307115aa" - }, - "main-header-nightmaremoon": { - "name": "main-header-nightmaremoon", - "rule": ".phui-theme-nightmaremoon .phabricator-main-menu-background", - "hash": "9e7cc7b18d2132d2dd47586ba0cd6400" - }, - "main-header-red": { - "name": "main-header-red", - "rule": ".phui-theme-red .phabricator-main-menu-background", - "hash": "3f12cc098afddb8e6c830ef761dcaa61" - }, - "main-header-scootaloo": { - "name": "main-header-scootaloo", - "rule": ".phui-theme-scootaloo .phabricator-main-menu-background", - "hash": "8cedc359dccab1bbd49cbc69940f566a" - }, - "main-header-yellow": { - "name": "main-header-yellow", - "rule": ".phui-theme-yellow .phabricator-main-menu-background", - "hash": "d920e70a6d2662cfb83e1d7e4b4000fd" - } - }, - "scales": [ - 1 - ], - "header": "\/**\n * @provides sprite-main-header-css\n * @generated\n *\/\n\n.sprite-main-header {\n background-image: url(\/rsrc\/image\/sprite-main-header.png);\n background-repeat: repeat-x;\n}\n\n\n", - "type": "repeat-x" -} diff --git a/scripts/celerity/generate_sprites.php b/scripts/celerity/generate_sprites.php index 97e3f70a19..0fbdff60ab 100755 --- a/scripts/celerity/generate_sprites.php +++ b/scripts/celerity/generate_sprites.php @@ -29,7 +29,6 @@ $generator = new CeleritySpriteGenerator(); $sheets = array( 'menu' => $generator->buildMenuSheet(), 'tokens' => $generator->buildTokenSheet(), - 'main-header' => $generator->buildMainHeaderSheet(), 'login' => $generator->buildLoginSheet(), 'projects' => $generator->buildProjectsSheet(), ); diff --git a/src/applications/celerity/CeleritySpriteGenerator.php b/src/applications/celerity/CeleritySpriteGenerator.php index b5c1ae1b9e..4825609fe6 100644 --- a/src/applications/celerity/CeleritySpriteGenerator.php +++ b/src/applications/celerity/CeleritySpriteGenerator.php @@ -150,33 +150,6 @@ final class CeleritySpriteGenerator extends Phobject { return $sheet; } - public function buildMainHeaderSheet() { - $gradients = $this->getDirectoryList('main_header'); - $template = new PhutilSprite(); - - $sprites = array(); - foreach ($gradients as $gradient) { - $path = $this->getPath('main_header/'.$gradient.'.png'); - $sprite = id(clone $template) - ->setName('main-header-'.$gradient) - ->setSourceFile($path) - ->setTargetCSS('.phui-theme-'.$gradient. - ' .phabricator-main-menu-background'); - $sprite->setSourceSize(6, 44); - $sprites[] = $sprite; - } - - $sheet = $this->buildSheet('main-header', - false, - PhutilSpriteSheet::TYPE_REPEAT_X); - - foreach ($sprites as $sprite) { - $sheet->addSprite($sprite); - } - - return $sheet; - } - private function getPath($to_path = null) { $root = dirname(phutil_get_library_root('phabricator')); return $root.'/resources/sprite/'.$to_path; diff --git a/src/applications/config/option/PhabricatorUIConfigOptions.php b/src/applications/config/option/PhabricatorUIConfigOptions.php index 84a7b4be6b..6b94cf1795 100644 --- a/src/applications/config/option/PhabricatorUIConfigOptions.php +++ b/src/applications/config/option/PhabricatorUIConfigOptions.php @@ -20,15 +20,18 @@ final class PhabricatorUIConfigOptions } public function getOptions() { - $manifest = PHUIIconView::getSheetManifest('main-header'); $custom_header_example = PhabricatorCustomHeaderConfigType::getExampleConfig(); $experimental_link = 'https://secure.phabricator.com/T4214'; - $options = array(); - foreach (array_keys($manifest) as $sprite_name) { - $key = substr($sprite_name, strlen('main-header-')); - $options[$key] = $key; - } + $options = array( + 'blindigo' => 'blindigo', + 'light' => 'light', + 'red' => 'red', + 'blue' => 'blue', + 'green' => 'green', + 'indigo' => 'indigo', + 'dark' => 'dark', + ); $example = <<user; require_celerity_resource('phabricator-main-menu-view'); - require_celerity_resource('sprite-main-header-css'); $header_id = celerity_generate_unique_node_id(); $menu_bar = array(); @@ -137,7 +136,7 @@ final class PhabricatorMainMenuView extends AphrontView { $application_menu = $this->renderApplicationMenu($bar_items); $classes = array(); - $classes[] = 'phabricator-main-menu sprite-main-header'; + $classes[] = 'phabricator-main-menu'; $classes[] = 'phabricator-main-menu-background'; return phutil_tag( diff --git a/webroot/rsrc/css/application/base/main-menu-view.css b/webroot/rsrc/css/application/base/main-menu-view.css index b70e0b7470..92385e6dc2 100644 --- a/webroot/rsrc/css/application/base/main-menu-view.css +++ b/webroot/rsrc/css/application/base/main-menu-view.css @@ -16,13 +16,11 @@ } .phabricator-main-menu-background { - min-height: 43px; - background-color: #ebecee; - border-bottom: 1px solid rgba(0,0,0,.1); + min-height: 44px; } .device-desktop .phabricator-main-menu { - height: 43px; + height: 44px; padding-right: 4px; } diff --git a/webroot/rsrc/css/application/base/phui-theme.css b/webroot/rsrc/css/application/base/phui-theme.css index 1d3d9210bd..03ccb8f38e 100644 --- a/webroot/rsrc/css/application/base/phui-theme.css +++ b/webroot/rsrc/css/application/base/phui-theme.css @@ -2,11 +2,39 @@ * @provides phui-theme-css */ - .phui-theme-light button.phabricator-main-menu-search-dropdown .caret:before { +/*--- Base Colors ------------------------------------------------------------*/ + +.phui-theme-blindigo .phabricator-main-menu-background { + background: #41506e; +} + +.phui-theme-dark .phabricator-main-menu-background { + background: #171c20; +} + +.phui-theme-indigo .phabricator-main-menu-background { + background: #4a2b85; +} + +.phui-theme-red .phabricator-main-menu-background { + background: #650404; +} + +.phui-theme-blue .phabricator-main-menu-background { + background: #004377; +} + +.phui-theme-green .phabricator-main-menu-background { + background: #124A1B; +} + +/*--- Light Colors -----------------------------------------------------------*/ + +.phui-theme-light button.phabricator-main-menu-search-dropdown .caret:before { color: {$lightbluetext}; } - .phui-theme-light .phabricator-main-menu-search +.phui-theme-light .phabricator-main-menu-search button.phabricator-main-menu-search-dropdown .phui-icon-view { color: {$lightbluetext}; text-shadow: {$whitetextshadow}; diff --git a/webroot/rsrc/css/sprite-main-header.css b/webroot/rsrc/css/sprite-main-header.css deleted file mode 100644 index de2ab7a694..0000000000 --- a/webroot/rsrc/css/sprite-main-header.css +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @provides sprite-main-header-css - * @generated - */ - -.sprite-main-header { - background-image: url(/rsrc/image/sprite-main-header.png); - background-repeat: repeat-x; -} - - - - -.phui-theme-applebloom .phabricator-main-menu-background { - background-position: 0px 0px; -} - -.phui-theme-blindigo .phabricator-main-menu-background { - background-position: 0px -45px; -} - -.phui-theme-blue .phabricator-main-menu-background { - background-position: 0px -90px; -} - -.phui-theme-dark .phabricator-main-menu-background { - background-position: 0px -135px; -} - -.phui-theme-fluttershy .phabricator-main-menu-background { - background-position: 0px -180px; -} - -.phui-theme-green .phabricator-main-menu-background { - background-position: 0px -225px; -} - -.phui-theme-indigo .phabricator-main-menu-background { - background-position: 0px -270px; -} - -.phui-theme-light .phabricator-main-menu-background { - background-position: 0px -315px; -} - -.phui-theme-nightmaremoon .phabricator-main-menu-background { - background-position: 0px -360px; -} - -.phui-theme-red .phabricator-main-menu-background { - background-position: 0px -405px; -} - -.phui-theme-scootaloo .phabricator-main-menu-background { - background-position: 0px -450px; -} - -.phui-theme-yellow .phabricator-main-menu-background { - background-position: 0px -495px; -} diff --git a/webroot/rsrc/image/sprite-main-header.png b/webroot/rsrc/image/sprite-main-header.png deleted file mode 100644 index f0211bd79ef90e5418ca9d92e2bca916a4807b5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2014 zcmV<42O;>0P)$00006bW%=J00000 z003^L2ax~(2a`!eK~#7F?ODf`?79skDJaYzIOiO<&N=(NA9&7r=d^NM`e&WCBZ(B@ z0*cepgnMqEKJ7d@YN-GgssO4d^~68C?W5uTAsQYYDV&oM)w5WSQz7W}wDcU7s$M34 zW?xS=p;zqwvMm(7df*0Ep?utk4@wUE5br{)wi)kg* zxb$GVnwrA?0FLhoketPIJ8^a^q)1v;({}d&Ku4XMV}N3l-_87jk~&I6IZgnC zN5|H)=)OCx6pp1idd~>OJ1pq%p(C%j(NVEEAff~SX~At?3m=bXJE8Es89||A+a)+^ zbClhYW_v9iC+U_o&ubpLq_xV_cXQ6oG3TilNHj-nGrA*)Q~|IVp?-_(;4`kxaoUxnxoFiQg1* zkrSV-@~h)mbh+cxNBsC_zqqdJDISI)(dTHJmSyRCQLQ)u5Q^5Y%xgakAOIYHZdbgB zlWOSuepxb30EE)_-MY+FUY89DQmbxtH|?sXbzO$O=i>lC2zy;DYmNZ!SgZN@m00M= znE-OmBGQr1Ldc22?%=5IxPqvD09aVHF6#<9C;*4IT(t|av3e1VhyWm$B9c&_sSSXv zPoG2NGGNEI>1(>gJWrqK6CffjKv)RaRMMTqpfV6bOcX3CcHqw`iYwu zQ=3@{UUBcss%&r+^)vuNbM%fI;BzFs-I}9_&=H_Hmb)1N5T5yE_1ka#>=@JW!oRJ8 z>RGI7YhCbnN6_mzqVTdARsY3(T|SUr_|PO=^f>+nZ<7nP&it}^@2juJZRkc^*KM^z z^?2D9oI^KgP_eiyEb;6p``5Z7oM|cZAR`w5=4}=r%XU)$$n*X0Opyw^<4gsF(su*u zsXdo@>?U_?hV<5i73)yd9S4L0JeOtkKIXibqjR-6YGo4v6z~xMV7TNr#A*t8wizqf zyCog-t#?RADBKDVvZG9(05o~?I_y!ZK_PjYZ&3mOU2{YLPE&xRnLpv!O`H)XbPTxB z@s^JC;z5Ok+t^RHdB!>RH<(^Vxgj41vXe}31b?@y8qzJa!FR!_zoDZUO>$#}D;QQpH~mBvDhT-q2wwChddFw0w`G3vBa09I>Fh7j=hSoRId#qv|MJ(rU)S+D^_+VC zvikJ>eBEYHDsBQ_=njqhRn6*R^@^NfALm`38)5>X5eT9EvSmBxlh>l)J$A|x6 zYmR1QU^qE~Psi1Cp+!CiZH}A~7>>3pV6_f|19yy%KG7w=tZRXSh$6)1lD|8;uF{Z) z?P@m+6iUOe(XlKm`Ub1)yV~rUf&hZDEi1%0Y(fl2b_dXAy#L93;EaPZ=$j+>_jeVl z`d~&FcQ9I4oSpPGGFnGK7IYEHzM*#liBF7iM@JCah?JD_4$3(Z6d~L<=edHVexu5Y}|3jrKG;w{$>&suxx@uq7-{=dq!gaM? zdc5lq;#cx-$ Date: Tue, 19 Jan 2016 08:43:31 -0800 Subject: [PATCH 30/66] Remove defunt project image choices Summary: These are old project image choices, remove and only go with FontAwesome related images. Test Plan: Project -> Edit Picture -> Save Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D15051 --- .../projects}/fa-briefcase.png | Bin .../projects}/fa-bug.png | Bin .../projects}/fa-building.png | Bin .../projects}/fa-calendar.png | Bin .../projects}/fa-cloud.png | Bin .../projects}/fa-credit-card.png | Bin .../projects}/fa-envelope.png | Bin .../projects}/fa-flag-checkered.png | Bin .../projects}/fa-flask.png | Bin .../projects}/fa-folder.png | Bin .../projects}/fa-lock.png | Bin .../projects}/fa-tags.png | Bin .../projects}/fa-trash-o.png | Bin .../projects}/fa-truck.png | Bin .../projects}/fa-umbrella.png | Bin .../projects}/fa-users.png | Bin resources/celerity/map.php | 22 +- resources/sprite/manifest/projects.json | 371 ------------------ resources/sprite/projects_1x/8ball.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/alien.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/announce.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/art.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/award.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/bacon.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/bandaid.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/beer.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/bomb.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/briefcase.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/bug.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/calendar.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/cloud.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/coffee.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/creditcard.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/death.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/desktop.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/dropbox.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/education.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/experimental.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/fa-briefcase.png | Bin 222 -> 0 bytes resources/sprite/projects_1x/fa-bug.png | Bin 408 -> 0 bytes resources/sprite/projects_1x/fa-building.png | Bin 369 -> 0 bytes resources/sprite/projects_1x/fa-calendar.png | Bin 228 -> 0 bytes resources/sprite/projects_1x/fa-cloud.png | Bin 314 -> 0 bytes .../sprite/projects_1x/fa-credit-card.png | Bin 220 -> 0 bytes resources/sprite/projects_1x/fa-envelope.png | Bin 442 -> 0 bytes .../sprite/projects_1x/fa-flag-checkered.png | Bin 557 -> 0 bytes resources/sprite/projects_1x/fa-flask.png | Bin 377 -> 0 bytes resources/sprite/projects_1x/fa-folder.png | Bin 236 -> 0 bytes resources/sprite/projects_1x/fa-lock.png | Bin 306 -> 0 bytes resources/sprite/projects_1x/fa-tags.png | Bin 520 -> 0 bytes resources/sprite/projects_1x/fa-trash-o.png | Bin 331 -> 0 bytes resources/sprite/projects_1x/fa-truck.png | Bin 370 -> 0 bytes resources/sprite/projects_1x/fa-umbrella.png | Bin 432 -> 0 bytes resources/sprite/projects_1x/fa-users.png | Bin 558 -> 0 bytes resources/sprite/projects_1x/facebook.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/facility.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/film.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/forked.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/games.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/ghost.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/gift.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/globe.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/golf.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/heart.png | Bin 12924 -> 0 bytes .../sprite/projects_1x/intergalactic.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/lock.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/mail.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/martini.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/medical.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/mobile.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/music.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/news.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/orgchart.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/peoples.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/piechart.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/poison.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/putabirdonit.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/radiate.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/savings.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/search.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/shield.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/speed.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/sprint.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/star.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/storage.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/tablet.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/travel.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/twitter.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/warning.png | Bin 12924 -> 0 bytes resources/sprite/projects_1x/whale.png | Bin 12924 -> 0 bytes resources/sprite/projects_2x/8ball.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/alien.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/announce.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/art.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/award.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/bacon.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/bandaid.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/beer.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/bomb.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/briefcase.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/bug.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/calendar.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/cloud.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/coffee.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/creditcard.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/death.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/desktop.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/dropbox.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/education.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/experimental.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/facebook.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/facility.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/film.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/forked.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/games.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/ghost.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/gift.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/globe.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/golf.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/heart.png | Bin 43007 -> 0 bytes .../sprite/projects_2x/intergalactic.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/lock.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/mail.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/martini.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/medical.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/mobile.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/music.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/news.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/orgchart.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/peoples.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/piechart.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/poison.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/putabirdonit.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/radiate.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/savings.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/search.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/shield.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/speed.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/sprint.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/star.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/storage.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/tablet.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/travel.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/twitter.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/warning.png | Bin 43007 -> 0 bytes resources/sprite/projects_2x/whale.png | Bin 43007 -> 0 bytes scripts/celerity/generate_sprites.php | 1 - .../celerity/CeleritySpriteGenerator.php | 32 -- ...PhabricatorFilesComposeIconBuiltinFile.php | 2 +- .../PhabricatorFileComposeController.php | 8 +- src/view/phui/PHUIIconView.php | 1 - .../css/application/people/people-profile.css | 8 + webroot/rsrc/css/sprite-projects.css | 308 --------------- webroot/rsrc/image/sprite-projects-X2.png | Bin 37963 -> 0 bytes webroot/rsrc/image/sprite-projects.png | Bin 18024 -> 0 bytes .../files/behavior-icon-composer.js | 4 +- 156 files changed, 24 insertions(+), 733 deletions(-) rename resources/{sprite/projects_2x => builtin/projects}/fa-briefcase.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-bug.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-building.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-calendar.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-cloud.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-credit-card.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-envelope.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-flag-checkered.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-flask.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-folder.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-lock.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-tags.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-trash-o.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-truck.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-umbrella.png (100%) rename resources/{sprite/projects_2x => builtin/projects}/fa-users.png (100%) delete mode 100644 resources/sprite/manifest/projects.json delete mode 100644 resources/sprite/projects_1x/8ball.png delete mode 100644 resources/sprite/projects_1x/alien.png delete mode 100644 resources/sprite/projects_1x/announce.png delete mode 100644 resources/sprite/projects_1x/art.png delete mode 100644 resources/sprite/projects_1x/award.png delete mode 100644 resources/sprite/projects_1x/bacon.png delete mode 100644 resources/sprite/projects_1x/bandaid.png delete mode 100644 resources/sprite/projects_1x/beer.png delete mode 100644 resources/sprite/projects_1x/bomb.png delete mode 100644 resources/sprite/projects_1x/briefcase.png delete mode 100644 resources/sprite/projects_1x/bug.png delete mode 100644 resources/sprite/projects_1x/calendar.png delete mode 100644 resources/sprite/projects_1x/cloud.png delete mode 100644 resources/sprite/projects_1x/coffee.png delete mode 100644 resources/sprite/projects_1x/creditcard.png delete mode 100644 resources/sprite/projects_1x/death.png delete mode 100644 resources/sprite/projects_1x/desktop.png delete mode 100644 resources/sprite/projects_1x/dropbox.png delete mode 100644 resources/sprite/projects_1x/education.png delete mode 100644 resources/sprite/projects_1x/experimental.png delete mode 100644 resources/sprite/projects_1x/fa-briefcase.png delete mode 100644 resources/sprite/projects_1x/fa-bug.png delete mode 100644 resources/sprite/projects_1x/fa-building.png delete mode 100644 resources/sprite/projects_1x/fa-calendar.png delete mode 100644 resources/sprite/projects_1x/fa-cloud.png delete mode 100644 resources/sprite/projects_1x/fa-credit-card.png delete mode 100644 resources/sprite/projects_1x/fa-envelope.png delete mode 100644 resources/sprite/projects_1x/fa-flag-checkered.png delete mode 100644 resources/sprite/projects_1x/fa-flask.png delete mode 100644 resources/sprite/projects_1x/fa-folder.png delete mode 100644 resources/sprite/projects_1x/fa-lock.png delete mode 100644 resources/sprite/projects_1x/fa-tags.png delete mode 100644 resources/sprite/projects_1x/fa-trash-o.png delete mode 100644 resources/sprite/projects_1x/fa-truck.png delete mode 100644 resources/sprite/projects_1x/fa-umbrella.png delete mode 100644 resources/sprite/projects_1x/fa-users.png delete mode 100644 resources/sprite/projects_1x/facebook.png delete mode 100644 resources/sprite/projects_1x/facility.png delete mode 100644 resources/sprite/projects_1x/film.png delete mode 100644 resources/sprite/projects_1x/forked.png delete mode 100644 resources/sprite/projects_1x/games.png delete mode 100644 resources/sprite/projects_1x/ghost.png delete mode 100644 resources/sprite/projects_1x/gift.png delete mode 100644 resources/sprite/projects_1x/globe.png delete mode 100644 resources/sprite/projects_1x/golf.png delete mode 100644 resources/sprite/projects_1x/heart.png delete mode 100644 resources/sprite/projects_1x/intergalactic.png delete mode 100644 resources/sprite/projects_1x/lock.png delete mode 100644 resources/sprite/projects_1x/mail.png delete mode 100644 resources/sprite/projects_1x/martini.png delete mode 100644 resources/sprite/projects_1x/medical.png delete mode 100644 resources/sprite/projects_1x/mobile.png delete mode 100644 resources/sprite/projects_1x/music.png delete mode 100644 resources/sprite/projects_1x/news.png delete mode 100644 resources/sprite/projects_1x/orgchart.png delete mode 100644 resources/sprite/projects_1x/peoples.png delete mode 100644 resources/sprite/projects_1x/piechart.png delete mode 100644 resources/sprite/projects_1x/poison.png delete mode 100644 resources/sprite/projects_1x/putabirdonit.png delete mode 100644 resources/sprite/projects_1x/radiate.png delete mode 100644 resources/sprite/projects_1x/savings.png delete mode 100644 resources/sprite/projects_1x/search.png delete mode 100644 resources/sprite/projects_1x/shield.png delete mode 100644 resources/sprite/projects_1x/speed.png delete mode 100644 resources/sprite/projects_1x/sprint.png delete mode 100644 resources/sprite/projects_1x/star.png delete mode 100644 resources/sprite/projects_1x/storage.png delete mode 100644 resources/sprite/projects_1x/tablet.png delete mode 100644 resources/sprite/projects_1x/travel.png delete mode 100644 resources/sprite/projects_1x/twitter.png delete mode 100644 resources/sprite/projects_1x/warning.png delete mode 100644 resources/sprite/projects_1x/whale.png delete mode 100644 resources/sprite/projects_2x/8ball.png delete mode 100644 resources/sprite/projects_2x/alien.png delete mode 100644 resources/sprite/projects_2x/announce.png delete mode 100644 resources/sprite/projects_2x/art.png delete mode 100644 resources/sprite/projects_2x/award.png delete mode 100644 resources/sprite/projects_2x/bacon.png delete mode 100644 resources/sprite/projects_2x/bandaid.png delete mode 100644 resources/sprite/projects_2x/beer.png delete mode 100644 resources/sprite/projects_2x/bomb.png delete mode 100644 resources/sprite/projects_2x/briefcase.png delete mode 100644 resources/sprite/projects_2x/bug.png delete mode 100644 resources/sprite/projects_2x/calendar.png delete mode 100644 resources/sprite/projects_2x/cloud.png delete mode 100644 resources/sprite/projects_2x/coffee.png delete mode 100644 resources/sprite/projects_2x/creditcard.png delete mode 100644 resources/sprite/projects_2x/death.png delete mode 100644 resources/sprite/projects_2x/desktop.png delete mode 100644 resources/sprite/projects_2x/dropbox.png delete mode 100644 resources/sprite/projects_2x/education.png delete mode 100644 resources/sprite/projects_2x/experimental.png delete mode 100644 resources/sprite/projects_2x/facebook.png delete mode 100644 resources/sprite/projects_2x/facility.png delete mode 100644 resources/sprite/projects_2x/film.png delete mode 100644 resources/sprite/projects_2x/forked.png delete mode 100644 resources/sprite/projects_2x/games.png delete mode 100644 resources/sprite/projects_2x/ghost.png delete mode 100644 resources/sprite/projects_2x/gift.png delete mode 100644 resources/sprite/projects_2x/globe.png delete mode 100644 resources/sprite/projects_2x/golf.png delete mode 100644 resources/sprite/projects_2x/heart.png delete mode 100644 resources/sprite/projects_2x/intergalactic.png delete mode 100644 resources/sprite/projects_2x/lock.png delete mode 100644 resources/sprite/projects_2x/mail.png delete mode 100644 resources/sprite/projects_2x/martini.png delete mode 100644 resources/sprite/projects_2x/medical.png delete mode 100644 resources/sprite/projects_2x/mobile.png delete mode 100644 resources/sprite/projects_2x/music.png delete mode 100644 resources/sprite/projects_2x/news.png delete mode 100644 resources/sprite/projects_2x/orgchart.png delete mode 100644 resources/sprite/projects_2x/peoples.png delete mode 100644 resources/sprite/projects_2x/piechart.png delete mode 100644 resources/sprite/projects_2x/poison.png delete mode 100644 resources/sprite/projects_2x/putabirdonit.png delete mode 100644 resources/sprite/projects_2x/radiate.png delete mode 100644 resources/sprite/projects_2x/savings.png delete mode 100644 resources/sprite/projects_2x/search.png delete mode 100644 resources/sprite/projects_2x/shield.png delete mode 100644 resources/sprite/projects_2x/speed.png delete mode 100644 resources/sprite/projects_2x/sprint.png delete mode 100644 resources/sprite/projects_2x/star.png delete mode 100644 resources/sprite/projects_2x/storage.png delete mode 100644 resources/sprite/projects_2x/tablet.png delete mode 100644 resources/sprite/projects_2x/travel.png delete mode 100644 resources/sprite/projects_2x/twitter.png delete mode 100644 resources/sprite/projects_2x/warning.png delete mode 100644 resources/sprite/projects_2x/whale.png delete mode 100644 webroot/rsrc/css/sprite-projects.css delete mode 100644 webroot/rsrc/image/sprite-projects-X2.png delete mode 100644 webroot/rsrc/image/sprite-projects.png diff --git a/resources/sprite/projects_2x/fa-briefcase.png b/resources/builtin/projects/fa-briefcase.png similarity index 100% rename from resources/sprite/projects_2x/fa-briefcase.png rename to resources/builtin/projects/fa-briefcase.png diff --git a/resources/sprite/projects_2x/fa-bug.png b/resources/builtin/projects/fa-bug.png similarity index 100% rename from resources/sprite/projects_2x/fa-bug.png rename to resources/builtin/projects/fa-bug.png diff --git a/resources/sprite/projects_2x/fa-building.png b/resources/builtin/projects/fa-building.png similarity index 100% rename from resources/sprite/projects_2x/fa-building.png rename to resources/builtin/projects/fa-building.png diff --git a/resources/sprite/projects_2x/fa-calendar.png b/resources/builtin/projects/fa-calendar.png similarity index 100% rename from resources/sprite/projects_2x/fa-calendar.png rename to resources/builtin/projects/fa-calendar.png diff --git a/resources/sprite/projects_2x/fa-cloud.png b/resources/builtin/projects/fa-cloud.png similarity index 100% rename from resources/sprite/projects_2x/fa-cloud.png rename to resources/builtin/projects/fa-cloud.png diff --git a/resources/sprite/projects_2x/fa-credit-card.png b/resources/builtin/projects/fa-credit-card.png similarity index 100% rename from resources/sprite/projects_2x/fa-credit-card.png rename to resources/builtin/projects/fa-credit-card.png diff --git a/resources/sprite/projects_2x/fa-envelope.png b/resources/builtin/projects/fa-envelope.png similarity index 100% rename from resources/sprite/projects_2x/fa-envelope.png rename to resources/builtin/projects/fa-envelope.png diff --git a/resources/sprite/projects_2x/fa-flag-checkered.png b/resources/builtin/projects/fa-flag-checkered.png similarity index 100% rename from resources/sprite/projects_2x/fa-flag-checkered.png rename to resources/builtin/projects/fa-flag-checkered.png diff --git a/resources/sprite/projects_2x/fa-flask.png b/resources/builtin/projects/fa-flask.png similarity index 100% rename from resources/sprite/projects_2x/fa-flask.png rename to resources/builtin/projects/fa-flask.png diff --git a/resources/sprite/projects_2x/fa-folder.png b/resources/builtin/projects/fa-folder.png similarity index 100% rename from resources/sprite/projects_2x/fa-folder.png rename to resources/builtin/projects/fa-folder.png diff --git a/resources/sprite/projects_2x/fa-lock.png b/resources/builtin/projects/fa-lock.png similarity index 100% rename from resources/sprite/projects_2x/fa-lock.png rename to resources/builtin/projects/fa-lock.png diff --git a/resources/sprite/projects_2x/fa-tags.png b/resources/builtin/projects/fa-tags.png similarity index 100% rename from resources/sprite/projects_2x/fa-tags.png rename to resources/builtin/projects/fa-tags.png diff --git a/resources/sprite/projects_2x/fa-trash-o.png b/resources/builtin/projects/fa-trash-o.png similarity index 100% rename from resources/sprite/projects_2x/fa-trash-o.png rename to resources/builtin/projects/fa-trash-o.png diff --git a/resources/sprite/projects_2x/fa-truck.png b/resources/builtin/projects/fa-truck.png similarity index 100% rename from resources/sprite/projects_2x/fa-truck.png rename to resources/builtin/projects/fa-truck.png diff --git a/resources/sprite/projects_2x/fa-umbrella.png b/resources/builtin/projects/fa-umbrella.png similarity index 100% rename from resources/sprite/projects_2x/fa-umbrella.png rename to resources/builtin/projects/fa-umbrella.png diff --git a/resources/sprite/projects_2x/fa-users.png b/resources/builtin/projects/fa-users.png similarity index 100% rename from resources/sprite/projects_2x/fa-users.png rename to resources/builtin/projects/fa-users.png diff --git a/resources/celerity/map.php b/resources/celerity/map.php index c5569127bb..9188e2343f 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -80,7 +80,7 @@ return array( 'rsrc/css/application/objectselector/object-selector.css' => '85ee8ce6', 'rsrc/css/application/owners/owners-path-editor.css' => '2f00933b', 'rsrc/css/application/paste/paste.css' => 'a5157c48', - 'rsrc/css/application/people/people-profile.css' => '25970776', + 'rsrc/css/application/people/people-profile.css' => '8f894dee', 'rsrc/css/application/phame/phame.css' => 'dac8fdf2', 'rsrc/css/application/pholio/pholio-edit.css' => '3ad9d1ee', 'rsrc/css/application/pholio/pholio-inline-comments.css' => '8e545e49', @@ -156,7 +156,6 @@ return array( 'rsrc/css/phui/phui-workpanel-view.css' => 'adec7699', 'rsrc/css/sprite-login.css' => '60e8560e', 'rsrc/css/sprite-menu.css' => '9dd65b92', - 'rsrc/css/sprite-projects.css' => 'e5ad842a', 'rsrc/css/sprite-tokens.css' => '4f399012', 'rsrc/externals/font/aleo/aleo-bold.eot' => 'd3d3bed7', 'rsrc/externals/font/aleo/aleo-bold.svg' => '45899c8e', @@ -337,8 +336,6 @@ return array( 'rsrc/image/sprite-login.png' => '03d5af29', 'rsrc/image/sprite-menu-X2.png' => 'cfd8fca5', 'rsrc/image/sprite-menu.png' => 'd7a99faa', - 'rsrc/image/sprite-projects-X2.png' => '853552c7', - 'rsrc/image/sprite-projects.png' => 'b9dd74b8', 'rsrc/image/sprite-tokens-X2.png' => '348f1745', 'rsrc/image/sprite-tokens.png' => 'ce0b62be', 'rsrc/image/texture/card-gradient.png' => '815f26e8', @@ -396,7 +393,7 @@ return array( 'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc', 'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => 'e5822781', 'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef', - 'rsrc/js/application/files/behavior-icon-composer.js' => '8ef9ab58', + 'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab', 'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888', 'rsrc/js/application/herald/HeraldRuleEditor.js' => '5bd8f385', 'rsrc/js/application/herald/PathTypeahead.js' => 'f7fc67ec', @@ -613,7 +610,7 @@ return array( 'javelin-behavior-herald-rule-editor' => '7ebaeed3', 'javelin-behavior-high-security-warning' => 'a464fe03', 'javelin-behavior-history-install' => '7ee2b591', - 'javelin-behavior-icon-composer' => '8ef9ab58', + 'javelin-behavior-icon-composer' => '8499b6ab', 'javelin-behavior-launch-icon-composer' => '48086888', 'javelin-behavior-lightbox-attachments' => 'f8ba29d7', 'javelin-behavior-line-chart' => '88f0c5b3', @@ -731,7 +728,7 @@ return array( 'owners-path-editor-css' => '2f00933b', 'paste-css' => 'a5157c48', 'path-typeahead' => 'f7fc67ec', - 'people-profile-css' => '25970776', + 'people-profile-css' => '8f894dee', 'phabricator-action-list-view-css' => 'c5eba19d', 'phabricator-application-launch-view-css' => '95351601', 'phabricator-busy' => '59a7976a', @@ -852,7 +849,6 @@ return array( 'setup-issue-css' => 'db7e9c40', 'sprite-login-css' => '60e8560e', 'sprite-menu-css' => '9dd65b92', - 'sprite-projects-css' => 'e5ad842a', 'sprite-tokens-css' => '4f399012', 'syntax-highlighting-css' => '9fd11da8', 'tokens-css' => '3d0f239e', @@ -1442,6 +1438,11 @@ return array( 'javelin-behavior', 'javelin-scrollbar', ), + '8499b6ab' => array( + 'javelin-behavior', + 'javelin-dom', + 'javelin-stratcom', + ), '85ea0626' => array( 'javelin-install', ), @@ -1508,11 +1509,6 @@ return array( 'javelin-stratcom', 'javelin-install', ), - '8ef9ab58' => array( - 'javelin-behavior', - 'javelin-dom', - 'javelin-stratcom', - ), '8fba1997' => array( 'javelin-install', 'javelin-dom', diff --git a/resources/sprite/manifest/projects.json b/resources/sprite/manifest/projects.json deleted file mode 100644 index 592583f0b1..0000000000 --- a/resources/sprite/manifest/projects.json +++ /dev/null @@ -1,371 +0,0 @@ -{ - "version": 1, - "sprites": { - "projects-8ball": { - "name": "projects-8ball", - "rule": ".projects-8ball", - "hash": "1571c4d51926d3af7711b825c5816e2e" - }, - "projects-alien": { - "name": "projects-alien", - "rule": ".projects-alien", - "hash": "384f920ae335dca04edaf29663d3a074" - }, - "projects-announce": { - "name": "projects-announce", - "rule": ".projects-announce", - "hash": "94329cedd509fc27a6fb577927581118" - }, - "projects-art": { - "name": "projects-art", - "rule": ".projects-art", - "hash": "85c545e5130f00ff1b93c0af0d540974" - }, - "projects-award": { - "name": "projects-award", - "rule": ".projects-award", - "hash": "fad6d89e4938e16f22f3c9db7cf5d696" - }, - "projects-bacon": { - "name": "projects-bacon", - "rule": ".projects-bacon", - "hash": "f6300cdfa5a96a223f53f13dd0d3acc3" - }, - "projects-bandaid": { - "name": "projects-bandaid", - "rule": ".projects-bandaid", - "hash": "c463dffa161997277fc6697155f4085b" - }, - "projects-beer": { - "name": "projects-beer", - "rule": ".projects-beer", - "hash": "81c7580f322d9fb40c77db56cd92d61d" - }, - "projects-bomb": { - "name": "projects-bomb", - "rule": ".projects-bomb", - "hash": "1123da7cc56313891c9979b004cc02f7" - }, - "projects-briefcase": { - "name": "projects-briefcase", - "rule": ".projects-briefcase", - "hash": "9b4b413ddb250ce1d3fbe18a5a5698cd" - }, - "projects-bug": { - "name": "projects-bug", - "rule": ".projects-bug", - "hash": "9678702aed00c4779759ebbdfe97fe48" - }, - "projects-calendar": { - "name": "projects-calendar", - "rule": ".projects-calendar", - "hash": "e7dc5d1b11fc55ed239fcbfe527ed0e7" - }, - "projects-cloud": { - "name": "projects-cloud", - "rule": ".projects-cloud", - "hash": "d38bf58580b3c36fbd3149a13f7d0e5e" - }, - "projects-coffee": { - "name": "projects-coffee", - "rule": ".projects-coffee", - "hash": "a9c10862139d8e7f56c9f892496f9666" - }, - "projects-creditcard": { - "name": "projects-creditcard", - "rule": ".projects-creditcard", - "hash": "db2c179cb4935da8b9950ac30da8c0d1" - }, - "projects-death": { - "name": "projects-death", - "rule": ".projects-death", - "hash": "cdea72dfdcb3fc64873b9fff78addb3c" - }, - "projects-desktop": { - "name": "projects-desktop", - "rule": ".projects-desktop", - "hash": "19d2ef34e3dd53615cdad91eb987d6fe" - }, - "projects-dropbox": { - "name": "projects-dropbox", - "rule": ".projects-dropbox", - "hash": "10231bf468769b96ed40cf983abfa269" - }, - "projects-education": { - "name": "projects-education", - "rule": ".projects-education", - "hash": "ce3d0ca75d519b2ac427a690d30475f8" - }, - "projects-experimental": { - "name": "projects-experimental", - "rule": ".projects-experimental", - "hash": "311ef712f8daca057c20c8fd78fa77ce" - }, - "projects-fa-briefcase": { - "name": "projects-fa-briefcase", - "rule": ".projects-fa-briefcase", - "hash": "f3dd4c94ce9f1cc74068af3ea9a4bc65" - }, - "projects-fa-bug": { - "name": "projects-fa-bug", - "rule": ".projects-fa-bug", - "hash": "e85895919b8fdbdbbcf43e476e70adcc" - }, - "projects-fa-building": { - "name": "projects-fa-building", - "rule": ".projects-fa-building", - "hash": "5ba0272ba1d3dee530cf72bd14b060e1" - }, - "projects-fa-calendar": { - "name": "projects-fa-calendar", - "rule": ".projects-fa-calendar", - "hash": "38b05d30e454285b56c7021d19ca7c93" - }, - "projects-fa-cloud": { - "name": "projects-fa-cloud", - "rule": ".projects-fa-cloud", - "hash": "9202ca72998bb07180464064258f43ff" - }, - "projects-fa-credit-card": { - "name": "projects-fa-credit-card", - "rule": ".projects-fa-credit-card", - "hash": "0b73456cbdb383ae2b211c7c8b90b712" - }, - "projects-fa-envelope": { - "name": "projects-fa-envelope", - "rule": ".projects-fa-envelope", - "hash": "73a2c4560e4d12125dbb3a3d1cab3f3f" - }, - "projects-fa-flag-checkered": { - "name": "projects-fa-flag-checkered", - "rule": ".projects-fa-flag-checkered", - "hash": "57b7474e5d81c84fa5020cb57f82d1ca" - }, - "projects-fa-flask": { - "name": "projects-fa-flask", - "rule": ".projects-fa-flask", - "hash": "ae9edea912a19440c15fefdbf728def4" - }, - "projects-fa-folder": { - "name": "projects-fa-folder", - "rule": ".projects-fa-folder", - "hash": "d3c6eb3334d6b6f1b8a1159d9d9e7397" - }, - "projects-fa-lock": { - "name": "projects-fa-lock", - "rule": ".projects-fa-lock", - "hash": "fa1eabe664aa26fa4732a18849a4d581" - }, - "projects-fa-tags": { - "name": "projects-fa-tags", - "rule": ".projects-fa-tags", - "hash": "f167c28072cf39a388ae0056d5f5f757" - }, - "projects-fa-trash-o": { - "name": "projects-fa-trash-o", - "rule": ".projects-fa-trash-o", - "hash": "82fb2b427b0b331652d19fd3654905a2" - }, - "projects-fa-truck": { - "name": "projects-fa-truck", - "rule": ".projects-fa-truck", - "hash": "89136aa2b52a6543b7c20dbdf0727191" - }, - "projects-fa-umbrella": { - "name": "projects-fa-umbrella", - "rule": ".projects-fa-umbrella", - "hash": "55f6a65e425c5725e953e3a59cb50f49" - }, - "projects-fa-users": { - "name": "projects-fa-users", - "rule": ".projects-fa-users", - "hash": "bd449bd0dea0d29031dc8fddad7bb66b" - }, - "projects-facebook": { - "name": "projects-facebook", - "rule": ".projects-facebook", - "hash": "16581191e4ce9e0115d447b479c886cb" - }, - "projects-facility": { - "name": "projects-facility", - "rule": ".projects-facility", - "hash": "d8893f9d2b75ec047b6f3898a386055c" - }, - "projects-film": { - "name": "projects-film", - "rule": ".projects-film", - "hash": "57497050fa09ba1533d981a9c1550ba9" - }, - "projects-forked": { - "name": "projects-forked", - "rule": ".projects-forked", - "hash": "f575428e1079981840297bd444e51c43" - }, - "projects-games": { - "name": "projects-games", - "rule": ".projects-games", - "hash": "b802cff3e76051675b37165bd9702088" - }, - "projects-ghost": { - "name": "projects-ghost", - "rule": ".projects-ghost", - "hash": "7c8622cad29bddc5179f6a6d5f15fbe9" - }, - "projects-gift": { - "name": "projects-gift", - "rule": ".projects-gift", - "hash": "f2ca678906a6806f421b60abddaa6cae" - }, - "projects-globe": { - "name": "projects-globe", - "rule": ".projects-globe", - "hash": "87515a83cc0c840804aca594677d1eae" - }, - "projects-golf": { - "name": "projects-golf", - "rule": ".projects-golf", - "hash": "1ee7556fab3d46d925deb00322dad858" - }, - "projects-heart": { - "name": "projects-heart", - "rule": ".projects-heart", - "hash": "3da64839e37ee245333017d0a310cc2e" - }, - "projects-intergalactic": { - "name": "projects-intergalactic", - "rule": ".projects-intergalactic", - "hash": "94dca756cb267bdb4e0ed58467320780" - }, - "projects-lock": { - "name": "projects-lock", - "rule": ".projects-lock", - "hash": "9d4c8ad3a4ac4163f284461da7df2763" - }, - "projects-mail": { - "name": "projects-mail", - "rule": ".projects-mail", - "hash": "963f5ce26c6caf86e72d754f7b6e8865" - }, - "projects-martini": { - "name": "projects-martini", - "rule": ".projects-martini", - "hash": "24d4d5fb5c334621ece4c35a9196471e" - }, - "projects-medical": { - "name": "projects-medical", - "rule": ".projects-medical", - "hash": "e0cb3ef5557321d166e8eb49c10d3599" - }, - "projects-mobile": { - "name": "projects-mobile", - "rule": ".projects-mobile", - "hash": "37dec95d1a4a937743d52acac319c3b6" - }, - "projects-music": { - "name": "projects-music", - "rule": ".projects-music", - "hash": "e7a814194685ac25be0db05b04074607" - }, - "projects-news": { - "name": "projects-news", - "rule": ".projects-news", - "hash": "6861f3ee827d09b0592166514f4941e8" - }, - "projects-orgchart": { - "name": "projects-orgchart", - "rule": ".projects-orgchart", - "hash": "20c51c59788fb2bc8184fdd5687d33dc" - }, - "projects-peoples": { - "name": "projects-peoples", - "rule": ".projects-peoples", - "hash": "c949ba6d09e68317a9a11482e75e5140" - }, - "projects-piechart": { - "name": "projects-piechart", - "rule": ".projects-piechart", - "hash": "051138560e30982a029aa5e4ea87bc17" - }, - "projects-poison": { - "name": "projects-poison", - "rule": ".projects-poison", - "hash": "56ddafd138e421f198b9cb38e5dc7455" - }, - "projects-putabirdonit": { - "name": "projects-putabirdonit", - "rule": ".projects-putabirdonit", - "hash": "ee298fff82c34341b986a3e1b77bea11" - }, - "projects-radiate": { - "name": "projects-radiate", - "rule": ".projects-radiate", - "hash": "9cfb918089b3de8506a5d270a119052c" - }, - "projects-savings": { - "name": "projects-savings", - "rule": ".projects-savings", - "hash": "9e92bc5e64f79d2f4842ac24a8b57fcb" - }, - "projects-search": { - "name": "projects-search", - "rule": ".projects-search", - "hash": "a42c1c31f2929838b0f181f417c0b6a4" - }, - "projects-shield": { - "name": "projects-shield", - "rule": ".projects-shield", - "hash": "40c6e1bec7c07c165668ac45c218847a" - }, - "projects-speed": { - "name": "projects-speed", - "rule": ".projects-speed", - "hash": "2b70c194d07f5a9d95abc51d84fb22ed" - }, - "projects-sprint": { - "name": "projects-sprint", - "rule": ".projects-sprint", - "hash": "655ef9a3043eab23eac1da21baeb36b3" - }, - "projects-star": { - "name": "projects-star", - "rule": ".projects-star", - "hash": "a46e3c18f68bc13a65b410496e27b5d7" - }, - "projects-storage": { - "name": "projects-storage", - "rule": ".projects-storage", - "hash": "bb19baa77bb7596f43f77e5dbbddb006" - }, - "projects-tablet": { - "name": "projects-tablet", - "rule": ".projects-tablet", - "hash": "830dcf6637288ca122c8f5034cae3769" - }, - "projects-travel": { - "name": "projects-travel", - "rule": ".projects-travel", - "hash": "86ec4dcd025879a43435b101fd542a1b" - }, - "projects-twitter": { - "name": "projects-twitter", - "rule": ".projects-twitter", - "hash": "75b8680dd1e4ecce4ca3a39c87e1ed80" - }, - "projects-warning": { - "name": "projects-warning", - "rule": ".projects-warning", - "hash": "3ac48b6f963675e1f4bb4ac75aad936f" - }, - "projects-whale": { - "name": "projects-whale", - "rule": ".projects-whale", - "hash": "569b584c7e80a0a9b965280abd27c723" - } - }, - "scales": [ - 1, - 2 - ], - "header": "\/**\n * @provides sprite-projects-css\n * @generated\n *\/\n\n.sprite-projects {\n background-image: url(\/rsrc\/image\/sprite-projects.png);\n background-repeat: no-repeat;\n}\n\n@media\nonly screen and (min-device-pixel-ratio: 1.5),\nonly screen and (-webkit-min-device-pixel-ratio: 1.5),\nonly screen and (min-resolution: 1.5dppx) {\n .sprite-projects {\n background-image: url(\/rsrc\/image\/sprite-projects-X2.png);\n background-size: {X}px {Y}px;\n }\n}\n", - "type": "standard" -} diff --git a/resources/sprite/projects_1x/8ball.png b/resources/sprite/projects_1x/8ball.png deleted file mode 100644 index 34f3a001b45cbee6636a71e8bd19c10cc886a190..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 JbXALE{|8LCCo}*6 diff --git a/resources/sprite/projects_1x/alien.png b/resources/sprite/projects_1x/alien.png deleted file mode 100644 index 4c8737432e9bfdc2db96d60d5243da0ec48a7056..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/announce.png b/resources/sprite/projects_1x/announce.png deleted file mode 100644 index 4d1bb5d7fbee8ea29b2a724e3029e502af92e285..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/award.png b/resources/sprite/projects_1x/award.png deleted file mode 100644 index 9ff2dddef3e26d9d009c6edb0bc2af544dffde88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 zcmeG?c{r47`;W-J6_TVwgk;HD%0AYJY@waXC<*06970)IPLk{qmFy}?31y2)h_Y{G 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 Ip>A{hKZXnlq5uE@ diff --git a/resources/sprite/projects_1x/beer.png b/resources/sprite/projects_1x/beer.png deleted file mode 100644 index 6a2892a4ed646d8ca633208579bbbca28ca5785a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 N4HX^bbS3jM{{?BdC$0bh diff --git a/resources/sprite/projects_1x/bomb.png b/resources/sprite/projects_1x/bomb.png deleted file mode 100644 index 85304e40c52d17ab7d995c872f152fd6de69d970..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/briefcase.png b/resources/sprite/projects_1x/briefcase.png deleted file mode 100644 index d6c6f5fb706adaf06905b7e845fdeed9204e5772..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 F{{thW;2Qt{ diff --git a/resources/sprite/projects_1x/bug.png b/resources/sprite/projects_1x/bug.png deleted file mode 100644 index 1dfb820150cf0cdd3a2efd0475c42e253efdb860..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 Vla|xIvH;afU)xA4O>^t<{{z?&P455z diff --git a/resources/sprite/projects_1x/calendar.png b/resources/sprite/projects_1x/calendar.png deleted file mode 100644 index f4b39dd6030227e827c70444d6952b24923d592a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 mea5lpaauh{`-9N(p5OC4|gV zLZV0i3{i&rJLmnM+>}cyzrNqs`o8s@wbx$rI{WN%_PzdlHI>OpHj@AV$W>JobfBvc zj6?(gAS`#?Z`d zaWeoM+hTOlDBVFismZQ!c{M-x%W5_{v_vdA@&WEN!JIs-#8i9ySmRr1wTm|>D&jL% z#`)m|2D)FM)#fETPtroz$9gT$>$>0hC(}JH*R7fgCSO(0-D#E{NFR&IsU<8TA`4Ry z))sXqOOa>Z@WQL2th}d>U)F0O5WPQDh&yOO42#2FN-G$|nL@C4_rS1g9>D!w1GyM@)OcUOr&Vb@o*Q zaF3aabU^^4%dE7BxM0At(acW)SnLMrwfoL10)riZ#$2sT9JKI(9jf}~Dj@4FD5{|% z%?3ndV28G!_cnm<0*ou!*&V^TNI;`BsxSF&dnVNY4^*khY{@(haYYX!B0f7peSLmr z?iyA4?KEO0>rA3#`AeK48H7AUC|`^{1t2b%7Rq*P*0F{nv!+HYFqh&m-_Sz>44bKG z?_7UvnyoAVJ@#&ObG!mMo85O4xLeO%+d6`8afmeT&&dGuY)aWXAa1Ztf6NxHjbi-8 zyw=wKzP^?{W%5QQPxM{q&?Se9^k9NO|TiDQ1SLfvrr{G|zyCrdONVE>I!r!kAD3o4@>}ZI8CrV~)P;=AFiq?iK}E z$D|Q1!FJa-GPo>~XYTbWtqxUIn5T=kM20EZMf z_)$-CWGaXNP>A#3$&zCnFW$skM6jiJeMd3rjIr1`d5*FYc`A95qwZTy8gEPYl;`%T z&SK&*7I-epBvPbp;S*v@!C#_xk3!0p@}mh+Y%zC%2Qj`}CDBF`);2$c>3IY8KqC4` z?%x!J;aHI_FU=dMZq#QYY7m`yNobAH2H~2zk!<6etT`_Q=+j zdQNr+nU}nC^Est!q|c7p3q}Re#YI0md3&?e1+n;nXK5CcZ9&q=iXBC-HxUY#9pAxU zUMhcU7cX(hk*Zs4>11i;o3r+%Z}?EQ$y7+t*Fc4ry@@(#qX3nQAF^yG2em&^h%4{n zI@Mb@Q1#UHO7$mn*avx2qD53TvxhuxJ8G3pD1MojWqYM}Urb+VpKu>zAM2Tm)tr}j_qOSr|K8!Coqc;lGD2$rPG-lkJ=y_v|m0WK3C_awr}!Akw2rvtG(z{ z)eY{dPcF|H+TbT7p?g9(Lm7DlP${X2sa>h0dSiN3 zsGyWXx~`c@dcwNBDa6mi()3be_P)_&)J3Q4PWDYjC)=Q8ZnzoF`V$zIs+VdZZ)nHe zI^0`O&O&;GA;*!I)rvgL=T8sOGR|Aot!Ga2S=je=GHkTpn zjj)@#Vy{U&z?~F6=61e|=IyqZ+ZYo?)bj+*4p^mzg@+lWsibMADZeQc%N$OMNi0;% zH=OpMkgM3kb%0A59aOVEWk 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 NhPtLYxiI^){|7oTi#7lN diff --git a/resources/sprite/projects_1x/creditcard.png b/resources/sprite/projects_1x/creditcard.png deleted file mode 100644 index f96103d220dd6e1bb7ac197a11355ce2b1f0d770..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 Wh-vBMO=&GCR4p}q)jYUWz<&Ws6;h)B diff --git a/resources/sprite/projects_1x/death.png b/resources/sprite/projects_1x/death.png deleted file mode 100644 index 54fb486ee900fae3c7e4e84666a54ae788b55791..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 j{}UNokNj=HXr&A(Gzqa diff --git a/resources/sprite/projects_1x/desktop.png b/resources/sprite/projects_1x/desktop.png deleted file mode 100644 index 2fb4be72f92ea16d7597dc8dd573f0aa9c41adfc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/dropbox.png b/resources/sprite/projects_1x/dropbox.png deleted file mode 100644 index e18aaf10e6c463fe7be09ee1314ec830d074ef50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/experimental.png b/resources/sprite/projects_1x/experimental.png deleted file mode 100644 index 2b4e6d4fd11ac954d38f0f001024704be8cdee0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/fa-building.png b/resources/sprite/projects_1x/fa-building.png deleted file mode 100644 index 1d3c2de98b09a6bd0dac5c9ff29b241689870082..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 369 zcmV-%0gnEOP)4cX9Eb6rSExnA)xkl8BMuP<-++Tl--&N0lo+Wf>ZAx#vRy@LoP`cqy$X(zAc%0= z<>O6-qBk^u<52(4^8%jXJAET_A<1~Ib$;I462BY%?8%Kts`P-z#;4BYb* zwP9zCAMU!J9w~(YVmr;g5_QfQ3EJtk8Je z*`T%WReEF~6yT8%PH-rML!1bg(jyOqo8Ya&RZAS(?mWgfJFWweho2dnf`y3}R%krw zY|wh@O&&fEpNGFN!+$VxppVwR*Xfbl!j?Y12t|72j zPk(dxu{dMZKYWfb5odh2iO9m9(Ww(nLge3_pqFc9j{5K1#?6r&*_^)sBEhdW1;PS? P00000NkvXXu0mjfZ33yP diff --git a/resources/sprite/projects_1x/fa-calendar.png b/resources/sprite/projects_1x/fa-calendar.png deleted file mode 100644 index 7568cac8fea243dfac9a5b18a8ab8eb0ec632a74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 228 zcmVC6<+nBJT<9ff2 zCC$S*yWNY44Q1=V9zf2NodSCR8Ecs_7Tp7g{qptzvf#*oWiKgvwhtVb`^X+Ef>=8r zxl|+BN2o@KBlh)J-tHsugcQ%^>OBh)qEA?e5dBYn77>!EE&Irp+LDj7BzoShCoy%9 ekDd@AU$`6ho6nA|i{jS+0000{s3$%6bb#{|0pKR&3*7cKlXoVbh7`if{LliP$NE9;RlPF}uJyFPnO`?z) zmqZ{l7I`7miELP-Pl!7**-_?#qS|C~MU8zr3~=>Dmlky;Ns>&7Z_WgwUFSoEfdBvi M07*qoM6N<$f_XcG3;+NC diff --git a/resources/sprite/projects_1x/fa-credit-card.png b/resources/sprite/projects_1x/fa-credit-card.png deleted file mode 100644 index eb082d0f8278d6ee4e4318071b65c05745660e00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=0wlMXIamRy#hxyXArXg@6C_v{Cy4YUe2D*2 zfA0Uj|H3EQ*8Z>Mh+O#f|I_+Y2b2Cxd-KmmdKI;Vst0L98#O8@`> diff --git a/resources/sprite/projects_1x/fa-envelope.png b/resources/sprite/projects_1x/fa-envelope.png deleted file mode 100644 index 4b744d358f147824e63ea49679f88804da915f07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 442 zcmV;r0Y(0aP)?k>@BoW zP|1l!x;q6?;Z8{I5oDSRIG4MfF8do;cHVfJWuvaHZYO8f6ECa|IaWM!T=b4DQ*$;{ ztz#ySyjG$&dE|!@{mvubmFQz0SyZC?d1T5rRcqOoN5UCxRr+I2^h3goreSND75$L? z>G{$yy>cMk&ms*+gfQZ^wn1vUV?+ptt>qDZxt89KdTYDAb1dDu>L>jWcxLk7Y}8#F z`nBPnQ6Wrv3fn_yxs+B;S(B^bbUJxai$M@rHX(#P9{XR5_6lLbG7OHe?p#_wuW4&d z7t-!o>kNy~_0U-Q7xaGCtEPl7=7BC%5cps^?OyQ}d~rFgOnVR25jqyq{%$9ouq(}O z=}-!R=MMIqJY)sRB6KX7H*Va#B^|0G)vA$l$fgo)=8?}z^eKNklk3KF5k ztQ=-B;J`2p477-fh?EvCGQ!cj7^|E3wCHRuhkNmU2t%CzZ+Cd%S)BI`$^Ms1mdqAU zWxduRRIebvhk&eYtB1S*a4_%tdIwyP(c`k?8iWGv)Tdo>#4uo9ee`9W(}2ivWrvfRlSBL^T? z8gdixhm%r5RN*a~bi#wukRh;N$Sb~nBknn;Sr81BhQyDrmG;V%{{UhqDni-}cy7sW zf}lpL+h)X(jV8)LHo0yZAVPjrr^_@#RK06vDF^u%;z(4jjJvMr^Q#<`hbW2!#{j4X z^4>F-4C>WsSM`yme#ka#=Eov)& zC&6Zi-7pMP|1qX@o3sQJM;t2epFH*%0Lwnf%3oR#G`Z*>z*MOSuwY!5-RcBEgHy)j z083`f0mvEAymI6|;7^@42(cOs`2qlD^+#8I#mG^M{&qwt(stcOO&D`WdvwD}LV_Bh v@`@tWEJ30Y+j8{?Gdi)bsgG_w?3x`PZ2s2>uZ+NLItx%wV%M8nkM%=QAQJBgzE#)y(UW)%w?Kojw2>-e z4wJY^BH*01G?5D81oP{55zFq8E*`M+O2IXab52Fvkr4R? X>2GjdRRWwj00000NkvXXu0mjfbXT5g diff --git a/resources/sprite/projects_1x/fa-folder.png b/resources/sprite/projects_1x/fa-folder.png deleted file mode 100644 index 42babc267efaac8937fa7f6875585334c06a3302..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 236 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=0wlMXIamRy&7LlfArXh)Ueo0}m*y3Dt@86)-!ky7)!sPJ{LW3x;i6?3^nZS@rpx%WiMjENbw+yurOkGTFrU z_wN@5DSz&D*oBF`D0;AYj!R!g(Xp#hTsI%R^K)j~`5;@b`N!=GWoukxxjvSsNXa*< zcmLpsS$WhwA&hm?Dke{nKo>#RI^jwd<S3b@s06Fuj9_}Lz5=e k7S5g{Yr8meme_vrn`Mi2J}lz+4smdKI;Vst0GO{^VE_OC diff --git a/resources/sprite/projects_1x/fa-lock.png b/resources/sprite/projects_1x/fa-lock.png deleted file mode 100644 index b87caf3aa0b3d0a854f1fe25bb6a2f75b5d020c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 306 zcmV-20nPr2P)SB9&`5zOEZZDnAA?57S*Ai%6u<5OQM1CZZ{!4b*Cc+Cclwz0 zi}W+4k-um}BN}ON_rZu?WXU=6#0JJO5`G%dh(1z-|Wgp|)6bN~PV07*qoM6N<$ Ef`Y_`0{{R3 diff --git a/resources/sprite/projects_1x/fa-tags.png b/resources/sprite/projects_1x/fa-tags.png deleted file mode 100644 index eb2bbe4963fde3a6021fb6d5a150553b221243ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 520 zcmV+j0{8uiP)glt3W_Z5OkBvO<@9ML9ZGQbM@Bb|?k2-f)B3Yk#4q!AmMUM`%Y{C4O znB3*pwWwii1z^C*aAb+!^^Q8m8?7^;2%v^^8Lds7DzCN9vW#$qd(<#yXp`(cMuk^e zb7BIJAyw@?jJ6h|%uB6vVlpFLw5c%KhnQK-3+?k1LJ*kIKFGK_tixEvbL|ThLXb9l zS;HavjPE1sF;?_h~IG5#FU z7w9KK5HZ(*(=lOeV-e`HAM+vpD`V)0Xi&ubNciPQj^xO{g8T$5Y$r0vw(=PO0000< KMNUMnLSTXzW9uXU diff --git a/resources/sprite/projects_1x/fa-trash-o.png b/resources/sprite/projects_1x/fa-trash-o.png deleted file mode 100644 index 89fa0daab4ab50a036d94925b90a2b84c2b30399..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 331 zcmV-R0kr;!P)B`?5@)Yt-_Bp2@I zBC95#D;oQVXRB959((JJp3w2id%Hq-?t^iA$Ow#tE|>@bQbj6Kk&2WcPyP1GKzQK0 zKMsU2$7%iQR~>;T8OUecmLVf>+(`5+k;;&cukyE3hJ>-Dyj_b@Bn-`5HIy8>Q;w8Y dk&0BLpueyZy2 zH}&Y$%v)D8I&R)l&hy*7{p#s--o*(F!!W+W3TH&BT(C}%On@$LfS%EGlAkgDA0=HB z*`+G+CCPAv!;hqwQ}8S4;~e3h(AQ4-sUh4k>}&DeLfS9mt z=a>n%H`mcg26!ULrnaM(1cY4E;+>5Y9py%V^8!czUn z0x~Oqe)})+x_;y;n6=R+x51VAkx_m5`bI-+*O&}IW~(I33a2Jbn>HzxghKKYk%&Yj a!2AGX^n%0J8Ya;I0000f#Gy?GTWE8MTyimgm)0YFm&bkQCinZsmybW>-IGjOnG89~tPrqB0SB>+ zLxDvCRw#2Q{x|W9W7LV5BA+ZW&rV+A2+Svo)Yz$^h}6Wau_+P~`^f^d)$9_xgx;Zb5ZHu5~}#h*vGMw4yoK097l#5BnpBx4hbSV(Jf?>PyGG;^rdb#p0dVIZXyWhm}8X|RpuB&7~v7i z+~Y8VECKMFWu7srdGX_fYwIKegEPi%!pIQldj8u;7Re%i0O#pJU07DT761SM07*qoM6N<$g3g)y=Kufz diff --git a/resources/sprite/projects_1x/facebook.png b/resources/sprite/projects_1x/facebook.png deleted file mode 100644 index 029c12eed98de6e805b4b0ca7b8668277b8923e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/facility.png b/resources/sprite/projects_1x/facility.png deleted file mode 100644 index 044e9a106bcb078a83b59d338ad056d6d2436d25..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/forked.png b/resources/sprite/projects_1x/forked.png deleted file mode 100644 index 28d898e8e6a8e88a9b661c639fbc53dff4372071..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/ghost.png b/resources/sprite/projects_1x/ghost.png deleted file mode 100644 index af601a754223a6304e69d3362ee634eb1b4491e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/globe.png b/resources/sprite/projects_1x/globe.png deleted file mode 100644 index f78741bb055a61fe85e212c1e7b1359380872460..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 Ay8r+H diff --git a/resources/sprite/projects_1x/golf.png b/resources/sprite/projects_1x/golf.png deleted file mode 100644 index 0a7cf98cb4530ceb5328dd5c3afbf74b6052cd48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 F{U5EU>)!wX diff --git a/resources/sprite/projects_1x/heart.png b/resources/sprite/projects_1x/heart.png deleted file mode 100644 index bfd83aa1f4fb3afe7c15d0f14dd27e136374f286..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 zcmeHM2{@Ho_unG(lnhB+A|yk`BJ(k3$`sOo${`8mMnoi2x+Iw+Dw$Oj31tcqq9}72 zl8U|zaTDji-~Mq=r*lrI?){$cx$AkBckea))>?af&ntMFz9t>@YH9!gowk;m5qwG@ zOi2y^iT&o=0Lw(M$7z)##rhZ1z&vPl%?{d)T+UXabmmOM*Ctudj-g>Gym^GG=*GN%HNgJgl zX(;VOo36^W;<;aSWz~y*QDt9hK4-v4nYWMU$P6zDnDUmF->|ln;w~U@e@sIOO7-GP zH?9f9FuYcc-AUqeilo#ve6tRv4>M5q2vxlblr>0v5@Ps`K@u6Ts@rSR2eyd-D}fU) z9|NC+saQ`EV0oU0g(N8)aIf4Sqz3G^fUL&tr`3V^M!;;VQz;9ciGYpTX0}@3dI2bH zV5G?fl(b-@VUYiNK;{XoYIu3w!KqlltTAdP|9(Rb5i+~oG)ccthS=sZDBl7}L+xf`&dAuP zC!Z~BYa8hAf3~$!)zZ4w%xe~1zNge|=HQ>+@}DLrp5N`|^Oe};t4TKXy!_#~Zpxa* zb5y5nI$wrqek!2BeByk(wo==s&|HYQ&ydL_R4wkzm_*9jVAXT$@2_jd?Cb3jo+ef7 zkp|ZfD3W-Fi=^$^OZq`afYIEww09DK(ITg^CxVouK6ZXD8r?AOlx8%O)&U<|?Q<>w z>{jCwHL1;0s-^@$Ey-8tx(dg5*(%{u@-=14JIiQ3S;?GI<*O`LWmKi!=d{j6%H?x4cw`5Cwxl{kU04%pjcD< zyl<|d!V}tCsKT^Ot50cMqItB>RXi??H7Wkl;hU=!&d4MWKFYLXXb)3FRc|bPwTeQr z^590%stVN`n}w+&_SW54n?;*hwfg$@EYhOjiM@?C+{l=G)k~>l$lO%9t+`aR%yrH6 zpJ}CWui=wg(N49Aiu9CWxxm_pG@YCLcUJsaxynXDJkVTAn75TFY^4~ZXAr7#6CYDB zN@w{eS4^6jnl+ja8SxGYr^icat>%q*(7w+hmqPZuF!zQU|Neyjihjv{j((m| zOX>t0WtS^c#=U|@wFkDc4=@f$4Uq4Tkx((c9B0&(mTa;@I&6n(c5=SaHN(KPl~TXQ z$=3U^YU`wAUy6LZ+K$a`(*D{j*E=h^BDwUVADK1R4QalLenmR&MoSmK;#VDn7G#fK zMX?Ia?zZY$jP6zT$06+1CL1@2zlj-)Wr%e$H5bYkI?fVaOC7m2l0T9|NX#TX<7!5C z294>MX`M+}`fg*d91T-RArW}wrYOq8y8Tg(KLTU6*) z7@)2gCf(T6S6szSvzI;3U6{v#E;HbFU+GHz8})6+j|vsV%y1TkC}gB3%c3N=N}A;v zjh(kuqUeipnY!SrPc%SEY0d#rN-Y$cT!LGSAe?G|bd|QzDZy zoSJa8M7_vj+LvCXdaJ-r0ZnvR!}5ed<2K{2RO(b#Jq5Xm9MKGi6prK~HMe_*Qb%GE z@9y?V)OAYjK2|dLagCSQjLD4S$J7Z;T66L|T0Zg)+J;r~_oZE&iUQEm+D(%rQ;REpGpkI55_-@?r~&R&>Sn_xTU<(+k+I4?H99$jNui_p(OYu%Qd?=TwYD zltg&l@%m#%fr2iujXsle2dDRun}?a@w##+LHCz}`^144BH6(^MZ)9wICfS$2vTl8) zeS&fPV@)(0y6}kKSWrl?&dEB_XhqR@j;gMjlK!o(6E3@6cr;HW#OKAA52tlp8<82Y z9|`Qd_)zNN`a}!KBabR-P|pnqnv`fRMs9TI$?`Tp8Tg`a4f2ZZ6$>}ZetNwi#Vupf z`W>6%2gSn|`xN`+H+4&NTkLtbskES`pw6JeDRGZ~59$OjW*^1_(*#m|){&q|gMC$e zEtgGCc^v1t7pf%JvHwGE+px-+q(T)Im9Uf9CkM*1dF*Q5p3UZ&9E@oQZ?LEL-{$?Q z^$~^jOY4vdZ(0HWK!39UrBLS}^VLn_(b8^Bov0%{Y9H02)Vkx*;s&zUM7Bx`DQ1Ws zkZ<2~N9vAJm8h-7!xr-dbM1pVYh*=*a%2u2yxa3>cr36tp_iu5lPyN9W|#A^HyEPagczGRBQN4Xs(6y!?8{mzA-by3aW(Tm7Ozec~b zJzAHw-#>Tu{-KZpF|J682M&2>vzA+kQ0J>&ePyyk@Tm|*E_%P2?Y;WoTG^<~#0~Ys z5A$j}&ThK!?jmNGshsJ>x%`v>9WxP5^Oq%A2V`^QU5<57_pvPB5U`y*OaAuhd?Cjc zgUn&G=p647eh)nd-`!=kC(CY;IJ}`Tr5^D2deixIc$a~>m_^Sm>yH5m9EvQ#r*oJ) z*rHiZJQM76AK(ads=XK6dH!a4W@X{NM%!lFp_knviI((H8PPAJ=?~Ghwcn)c*?x0) z;)8mJSaiK$N0DDXs_^nX`P;?&Qy((L`pXx$Bno)2TyEBOIQ^AEe&4 zbXXQo&L}>(+hIy#s@G!MvVU58I&V@bCpcqhDr(wsSGK;R%WySmGwBQkFMa;g!Y3`9 z%?c()VXYh9Xwp~zc6T=6otp@q44vs87pi)Boz;%@4^2|_Omfl5wI4m>ne~F=@oz^t z(VSujRO3eDG~$iprY&tO?-)E(Y-)Yo?eR&o<2Qy2Qt}qZwvL%Rux}qa`8WbS+IS`* zGQrDR^v_PKj!XHTgL@l#4lp>qyTj=EqFEgiGPtF9OT*65+peRz9Rn-PZkxqjliTC? z+V!>kY{X-O>Y@upaXE!M9STQ0N^W`DP7ZM-ZffWnFFE#}71P?1D67y_GUnkld4F=E zhqcT5u)s`1T~V8xz({tnLGhk(?4{Yd95z-l@2QqIPaB$Inv$bO zqa*G)9#5HhUHXRoT1QoR71!Md?vmoW$G1-pm$`MialX6U!(h;Vocn|z#_rD>6UL8H zrz6-SA~0m6F=L=%ZQc}jq-uart(RBsUl z!b?vG$pHhdfo+6~n#=if0oZ@YzI1TMf`p*QoPq=k=5u=v3Xx+g!JG${!+aAau1Hcg zOSJfTW1I#qF7`z1hPK%Kd0XsA|A9sfIH0)Q&y~!3LoFlZL|iMZ{$Hif%`BcL6k&w$ z$N}~sVu5~c{)LRI@mh9r2D>m^J>EWcQFsk-g+Jtw1JST21h@S;7wc&P!V>`gTI9G9@Hru}`TB4jkX#XiZlnR}8vyK4`hSz}{KXf6sLP@qKrtC=deM0i z&4GY&@u?92A|@sl#1lH=E?#3SFnIZVrH4OY@$YJU!$kv)$FaZ`+k6ilkOOL-@CBKM zT4LwSyfcx;SBnzgaQP5%UXlu5B?u6_{6X%L5bHB9q< z_zr$NG72ceN0CrC_l`mENl-z=IS%SbiRizrB(2g8|>8!w?(t@P) z&}t0Z65quCNB{);Ds}**jc+p|?6EXIs_fRo9A~8AjsaOX7CgJ?7mmb zLhg|PxL{W=e$oC^k5>?l=-ydKAxnL`|EZNgF#I3WzC>BbsfC;_|1{nEUIGi55iSUV z{CfcT#Q0AT@&%a(GP1-8(n4mW7kYC*en$}H*C~+CBAk$k7J-CcNFj(F@@0q#av;+A zo9GOTvl24)S1H1wzjv(R(IY>yEJwf`H3* zXZuZCHX^j^S(G`^!n}35YEONamSKSR2}5TyZbkt!t;612L370gnK+jO2%dS$ZJIwt zM~9BDG$w%d=uz(@+@=z&hnSx*Gzp$Py8m3jp*wvqJkB{j%ISGkK6vG^T1!f2R7NF3 z9wTdrzP#xIZ`MSu*;AhHFDWX1(Ilne!z|*0I2kiG2<{jVra`@4Dk}4Z@)&L)nqBu< z7*XER$UK=@{zDvZw8B@>cpsq2a}8Q#$mq?5Gkm-mVcX zlSJ!8_rAK1yrX)E;i zO1`;CKO|&l*ErZ*ne3v0&Ajr>&(3M5b6CR?^Lx)>`*aSCD=4P* znN_C?j*ZTlV_8q1Ha9grSyH66()Ny(=OD3QZJyP@mXBU4{XN~!Z@d)okz4JfN7wtj z;BJ>u?5xV;Ob6_0Uj^#*Uu7BU=f5vhWMG$NEzZ?wI(6Go?T90taa$39Qz3f4#BilLuffysLx5NGym2N}t)Ccrp z<{)o-gX7x}TB9u@WpO7%y@U}V?HC{Ni<*30`7*l5G(-QM5zsN7XPWpicze1j=gI}-T z1)l}b*d4MKKFY`w?%OMvuTMAiu!z9z04`G@!=MHFvSx=Y1T6LWJ5;w%Qu1G=dp&4z zDU#dQ@0X(|d%`E(RP_Pt6+%|R!kGtj&$8Ux;3^vtI6Wrv-uBBgRgWm1X}Oo|!0{|l zjZh+!_j(3{e9;yesp3MdON%6!g4dT_5=voBE}nUDc?xaz!S3~ym)z*4`sm~_Dbl%V z3E0lo)VDUWHh!X?ATUcrVahY6g-o;uObbMXf)flc&%Hk7W6=ydIaz;eeF@=5Qv;_- zb9w|2iWZ7YJxGuf%{n&8;L>@E>Z#Sb)mzPkTO|@B74&Bc2j70S!7-gd>4b#9{8Hbh zsHVau`6j+5!H$*8QFa>J&i9(X6f?WCc?oYbXR|^x{l+jkP0Mo;W_1Z?ET$|7T%nbE zCe!SKsei&Wh2JBT%J)wO&4CfUY}BTa<*~kJ*(=nR=wAuuW7s7 zSlRrz_m>0^#dsrUFw7wGy3M!{W)#PJ|1fWfh0H?Pw_z>e9O2HE*5aAsd$@z{FrQp< za_&h!acPUhq`0K|Bo@m~%QB0=#5LxgX}Xs3=8cI=4?>bHlcJWrHRm%YCN56!Pa-Bb zTd1G+vKcr?Z&PSgXhJw|8gprFV@|OE%X;37T@r$hY{`DV`z$D$d#U{Co}J>^VFUcx zhgFjj&nOY(m&jXXn0218S7&Gp+tz!^)tIS8EIzc;>rg${yLm6?@x>_^Wyx+_<(L!_ z8e*NSpKO|}_cm8Ctt~z(E>|bprq736vt)_rDp5URV8!I97W1d(b@9yc)0e6$cc)1u zImYsx$<}texi!8$Ec(V8?`R|E_#`I$fn{|jUtUs#ZJZN=F-mP=v!z*a^Wqj8EjB7CzgvE`{89LVNLAU#axIZ9k&h!AuC80LYlTE+LguxN2I);J z;%wS8bGG`fP_l`&wp_6~LpL=lb{v@ma>f#>vr-h=mv5XWq_CyvlpA`3ZeZ zTBcK`r!CQrhj{f?T48%|Zm{Qd&p!rK8QA=vvM2Me;P={bc{`W#a^?Dnic{_Cp0~O} zTBV8Bm7JAN>1Lc3!7rgs0@({~k4&x^K^-*K<7lOof{73D zN{g`cdg&mm)W;XE#=0f-*uLXY`=GY{bfa3M%EEfNdYiR(7v^0py;^2c=p4P)w}G%% zcxc1W?x89a?>&cxNPEyn(`V(RzTVw?1aBTySFYLkA^mBa=8>2zO>WJ=eX0AJ^HT*K zO8-2TD%jH!RuNROiQRXZ*Xu|37;InJ9xn7^74`M^wenLx>Jnf*vr0B}fm>BAVMl}Z zC+!gJ`beUziP8nhB@4vWlB71PJX?5O;ktUUl)cT}ht^Tn23rhgDM^W^DQ?|zqoKd8 z)Bk1EOO{3to-pas)h_O5Dhj%MCmVB&4bJhXT#A7)|Y({mF%F)v!b_zJj zsVe8n?mr%MY@1e+;L_ks;v3>C`<-Pe8-3FUZ*4t%ReJVGhTD!A$5JNSNHS+?#l5yz zA@*3DA)UC<%Km2g!8=MJ$t|>s$#4BCH)XR@ zy2>{98sxWMtZs4M zqRZlwg<^Yk-4)x%y<4l=`8;wyDE#@bW@S##fZFXFHI_7%OCQ=l+}LN(m(io1b}*^6 zH>A&Lb*iz`wzd-5YT5w?VfM_&Sq~oaSF2i>1wNYpR*${pw;O{|@7yHW6xl5QI92>o z*hSmDskMixp=UOm^0S>sJW^gT-2ZJSKapR0vsOe$gl?pHMBhrgmDf$~s#QIDQ@^`k zujV(7Qwl0J?n^o?Zf|uSzsdbF&sXxPl*{O&rZ>x*ig zp~EeUa~4;u>bU0GkzUh0&FY#}#0BNGPH$Y_s0;?*Hz~(ytlj;YKjYrXWzKJOI~(O z*Ydu$e79OR{&(jZI82)M2<#Oba`q45TvaL{Vs#hn{@~&hatq{e0=RKU4%sA4YV~acF~|Rq%cG?Gz3klU=kJi zu$a6u9VA!{rai7DuLQF`;~&F0Jmv@?8M4P8fMMC!8w9FB#|5;Ex>Mw4eYOc_$ScSl znMblS>|Z7he^y{yNfkKV2kgQ^OsWo$k1=X+C_q0on*2ekeaE&ZFOR2}yxpigrA{Qr z$#CdAKb$EhCtzH~4Y8Y+|m55{#6AY&^Jm~0; zBT#$=jQA|Zy?`VQ8z5gjQuct9gwLjb&Oi+VkQOLMY6WQlki5;Ph4p#V@iISt;!qA9 zp>M(~a6Fr-)lJwJYKq2_|5Sr0gQes<6DglV<^kSY@U;w1M`P^b8B-?hS|I*QkS{_4 zw8krYST^3o&j)iJj5g^nOOv669k3G^Pijs2B9h8DWd~XV6>;GUu@l<82TB0{{iP*! zCb=|{;_w)f$sqe5cn1=9Aa3gjYz1QM0g{L8bAD{N>`8-DNV!0U@7d%j)G>hU69xIO zXzU==+I^G!r~00JlP9Q-N$A6`m`x~#|2wn)|K~{&%rxmiLY~5F(=ce^6K+(8IpISp zehT4}?s&KXm5CG@{Ci8LwtbGsA^9TMLaWbPFXTz*vSHbH6YojEI%=Y5vI--z{BU-> zZ3V}EB7mO(5Fbzocox_T90sMwBd(DBSM`KGmq2U$?2Q9{9sp~gG>8?*IdJ6{0X5@c_m^(lUqa7?7`*q#Ejsh zz#(7>@Es7JMFxQI+X>18dIRy@&3DE3*naVwi9gU4IQAU#SH@xogMkG=e5AxLDwKeO z@d{W4Y@*cQTOEl5rTAR?J#Z0}_yN0s__U6V$3epPfir*tKpZGscNRDbU+V}LXu-!> z&QaRFy?}ow69nRv94t`4ZyI#KH$d$4D15CWFF?!eQJTJA0l$rijHtsiph;H7%PMoE zZd8IjoG9>_{zo~1Z4n0A0r9NhnaAh`W&k^IffByd5eDc?0L}ucQBw3BWcZr&Jg^Li z?ZQqp0&{^>uTY_G7=N|2@GUg{trxFR47@(^0Fk)x9qeQb0;kOX`ihJQ1_*9tr&;Yf-fpx6og{g@D_IkE<{ z-~n;e@DBAF_yLFwq6Omb433@&5bx{Q07~l^w}F2~4F7V8jUNxOP`PTn2IJLHa|HL9 z3B=b>yue97O2F5J*a`eZCIS_Jc(%S2I8aA`?m+yM|7wiq$k!^BgpT;(r2)jVfj0*n z2)tY#1M`4Mz&h9BX`cQbAxil{A_iRkz#+WvCnrYSulQzEF6=EhE`p@ VDA@R0avQeDK*v}+O>5o0e*z{^?DPNt diff --git a/resources/sprite/projects_1x/lock.png b/resources/sprite/projects_1x/lock.png deleted file mode 100644 index fdb14fe429925d52837be9b13acb696b1e7cddce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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ǃPMg9M$=*AoIZW=JHLaXu#mqax;cK02vAna>t+UI+D>5A!vK zxF(65-;&P1PDtv?kCqGibM>5a9^NqU`Tt`u-w`^?Gn_qci48=LV65%$3gB2?i&dH( z;Y$Vv_|loz&X4R9xHQuclHt_`{*nQgYyd)bJl>q;_j&s$zmc~YaH;42+ zCs^Sr>|`P1e5WLQ9m4-lfq@4?Lf7LA6NmS|b3I}sCu#iAo?wl_Z{hG|1HX~~Fp%ox z?yTiwKkNY(oM$7!8x0>$Km=Ha7!b5aY9<7~QhYBfQk{Iy9zp(m#|p`>CXfe$Zy>)V zllgW$!Ket<<2%IPlF6Ur1SBrs^>)5T>^tTD|Hb|-efb?J|C`9~s4^)&7Na99PyntF z!q@0q2;t)#MtBa>U>+>#R=acV(7(E%M0uEHtt2sA$p z;SC78X6f)tDD?jn0R4ss(9hD~p$9@<2tUD#1p`#VpRGnFUK{Lwz~(+Y9oWWC#qqNp z!F~(E7P1$b;C2Q}Cp5yH;KX6Tw%|@K2!3|6Gvj%MH}sDJzAW^Uv4z9WCbDqPzgTl2 zkJduoju#R(N$;+IOhr9f zwkWWei6}u4-@}O-p2M_7fyGQ@Q357r^xxx`SY`gN==1$Cg;-1^T~x%3{A&6ivq%0- lYXf diff --git a/resources/sprite/projects_1x/mail.png b/resources/sprite/projects_1x/mail.png deleted file mode 100644 index d10d0098aa6d850712f069ee019d744e9cc13ffc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 H6QBPB=(Y_T diff --git a/resources/sprite/projects_1x/music.png b/resources/sprite/projects_1x/music.png deleted file mode 100644 index daf0d3e1f77d661a1ff625db65081bbfd768ef96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/news.png b/resources/sprite/projects_1x/news.png deleted file mode 100644 index d50cf67aacf65a1683293956449016d15ea7b820..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/orgchart.png b/resources/sprite/projects_1x/orgchart.png deleted file mode 100644 index cb9e799290c5729137b66ee458a28031265a0525..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 NsJl`pUEBWP{{pg#e3k$J diff --git a/resources/sprite/projects_1x/piechart.png b/resources/sprite/projects_1x/piechart.png deleted file mode 100644 index ac74091bf99a86142eb412227de4c31dee96de1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/putabirdonit.png b/resources/sprite/projects_1x/putabirdonit.png deleted file mode 100644 index 68b7e3ae91dc2e6db8ee7bb71d499b7539e9a196..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 IRV`2b8-NQ0LI3~& diff --git a/resources/sprite/projects_1x/radiate.png b/resources/sprite/projects_1x/radiate.png deleted file mode 100644 index 634707e1abf420a9a0f0384845e4bff680f6571c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 zcmeHNc|28J_dg=@R2h==5JfU%j?7o)AyY^LDpyHViYSpx)srNdB28v0ii9$S5<)Ul zA*qMn4DlrHZ*T9tKG$`xdzJV30gU{8$)t7~FJijv)xs3aC^_%=MKB!f0{;h1#~w$<^KUn3Jm;za9$3 z?{?JH@xY<|2;$iqXO6Zo@8?n(>m1QE2=={d;A+N6&u^xA!IvX!y{G^KyMD01%@$76 z;$>U6((qO$1XEwS4Zkz^zOEw}a2WoOthj+xcz5*vIOrM@_1I>BDi^ zwRA=F%-3{fOyzu;Q#98sd*@$KR{p+6Lfwy1$PHnq&)z3+Y*LU48TV0E-nh1i?kPg$ z*}z1P6dA=9ZCV|KVf(BZy_3rK995Bf*k%KIUk*gw>yl<7qOMKl8yB_S97&)-?5g%U zbR*lu5j){C9~%(gxbbLjD#Z4x04G&K7{b3|f3Ozfv;|48-F|*6V!a9Ba5N}WM4H8s zO?p<2y2$-pq^O3SDGQ-zMmCuS2W&uSyb-%fK|xRCTr|R=J!GZ)ZDS^TpD0+V=q%+t zA;qnJw)Emh=&YE#OG|H0PqTiRrmg);tJ72Hl08LMlZXEHQT{nL`tIomAwTI| zemXSc?@C^c7~Wl7dxhbgL;J^2ou9c(n4f$NYs>T;@~lNUx=oiKxug|yaaj89+7Qhv z8=kML$L#yiB{o5=+9ikFKd4IO9VVWJ9znDc{6z0-@QxI(6f2@#UA(ltnCYjT{5egb zvJy>pO~!q`tB=}kNI$D75?FnoPt;EGjXIxfk*QN)xErfPiREKf6*smY_Vn?^A_aa7 zG#ZukE9?bYgQ*w4OK-|Y%2P+l1`@V&?brUQq2dO#Tdf(Ry|mo&YV`h>i+h0>im$=y|oWKXqNkJ zEn<+T@zCVAU!$RGZD?)WteecgT1a+TD}w?9^*PfL;kDt(1`pRiS@w6?N(X7FAZuMQ z!MDppS4gsZ2cyaqgqDY(q=oY?FVTB&$D)3Dy>|U!Gr@kblvr8aRf6F!TK73;(J5XP z1~-Yg1}iYJ$3Bn($yxcR@Kn(_WrzPcZ>!mbAd*esX2&A5^!TIw6`L zHOZHMK_xZirXos4U&boiZ1}398eMnPk@4&9#teNTNs+@o=Q}yRZuqc)H&NCwPip^8 z=hSPF*R0cY(@fKJz7)!54kX1T7H-YAneb!PsL&VQDXfDItyvn^XWnAok;It9Wu&4s znkkX$e3$oTzLv+c!%2ft@lSXA#v8gOb)GEj`?318cPYQUo_4*! zdIO`+MuRbCMtO-F61Ny`F|4S5Reh`aZM0mhid2(yUu<7&Q*2kR-44$kVmZk8F3lw-sWfICoN0LGY&USi+_tQz5gxeMNUdC&;8zJ z+P2Ibmz>k~Xa{a|?(@vj!SKTH(@#$SIjKU&64b()#AqRLQ{wMY53VLnHcvvCGhN$no`^T?^!Ja8W$7tG&nUv&t{zMEzS^d zs{HG6hQL@~R83gT0oH(RKA+ycrnCQOf1%WeSvVjlz$#Gfl3TF#syeAiIgh$_)UhtD zA6nP6I%CmNCW`mO_2ooWQzZ^6w<*yR2~i>kZ7n@{;B6ujJefG_Vrqv;J6^eo!$> z`N+vO#%|7~8w0n~rYk=_pCjthXp%Ny6`AQ%xZcai*>898%d^FgsGPqrSu*wpoc_|@ zG_cFWTGFQLk^PUrI9^rGkn@=wZQPNZXPQOYJ$reBTwgwmZom34C9N!PU#(-kWBDvBqVD$UeHp$3pk+yvQ98})zXUdNY_9wllsotVyamQlB z;)jL&V136U`=;^3b%VU#1>a@=YHYJD7@Jgm@wCm7%F?LOv2p)|-bD78T4qRU|M;~D zmt7ggE=L9`sOzaG=>%DGn)2Q>^3|(Yn1#OG_(g}c;*Y0OabG>eS>#zP|GZxQLC{U> zWKaJXL)X|E7Nyn`7roQp(>45Yf)C9nc~CQEC`LQhJZ8ey!S;#CE7iKUpF6#N>a_jA zc3oE4=A{0x#ft;2{bw7((L=Qt<09ft`$+uVZr64z$GdNDP1iv-*RN05-QU-5#a!sy zQn00F=g?#Kp{%yv6;_X}V(uyJarx~2S$QhF!K5PpdVWl1-cIMdL9fC`-i~AayzvS( z9V3M&zj0ySHpVNebQBJIxsE*_8|~ui@Hr|xSyPqY;vqbkQD9QAXGDEKqXpFw)Tm}V z)!zKI{mj84kA&g6cAYWW0RP&lu+dO9)Y8!C(5gU|z%TKeRTULKs2!c`|CxlU-B-Il zo_p%nR8=N7m!!{l84--r-w#I3Unfn3^Mr?EXsDxxf9{nLZv)Sp{CjoHj1a_Y9fJ7! zBgo$vVEYl|_$CDTY=X#hq{8|TTw2%%&(qW5gtZ7^Bo4<}FqeDCHqw*A zPmYV3wm1hYKFT&W5;5NGk%3Wq^U zxNi791UbFr?Bs%L#9xWo=}7c`I{?mFkRUn4j^Z% zG2RSDY=jvn(MACcYGT2|5Y0peTzF|@5)yNh8)O6obrTE3!&uaMwCm>K8{ccy^{LK2}A0|0Wz@Eq%~ z7#=j!?8o}1^W)#SxOJR$Ti`&fZ2?vi+wQ^I`S{Zmau*((XU0r|mN8IIpoudmnFgiz z2{*{|iAb(tfUy$6XF-(AWG{#yHULb-0+etUg7_?^A}Pl^XmK71ayva^8* z5|Pibyrsa(VB54LxDcL|cUA{D;juOlIXJJRUtr{~pe~=s^nj zY(6cAz)#%!4;Gqh7P3Jyfbj3w6m`IY7jnvEA%jqskqB!cd)GY>50?{sWu=AiVN%wH)PFD1)GCIxx-f6pMu%@w=<`bRDd z`BnXW#y@ghe!ooe8U8mB@@w?ZGJfZZ2!c|d0<~U*l3@;*OX!z#k=v$;_}u|UC;<%Yf?JU%5&SOcki(>S@CeLJ}Mb}sM+ECu}0 zd19ciY#u)`7pwukiIWyGGp(d#xv(7gF1rygpAKmEVSUiRwjNO2%0e!w_g~>N7>ARzykla4eHf){(1G!5gA$AdAH3ao`>y@YS1gqIHYM@~YVT>s-d1biQSWrOvm9FRJ-ZO$5H`kCCW!J|Bq?@-Vqwi+qN;3~d0x?-lS{ zA2EeK$XQfb?1>x$)#Xu8A>=^r;>mnF!2*3Z0Dqx!0|b!Vi5B8pjC%xLRrsMo?iZK0 z3dC&&I{hCdznFvUzl>0lw-%5n{%%Ji;cI|Pk?>IjFUA$YA4mjr;NR@v*G>tbJV4oi zLV+L2`heC0g`fJefHnhN6j|(vEJ{(ol4P-WtzW5OQDXi#kwsa?MN9(zLXW|qD%*>u SSY#i;yn0)WwK6sB&i)?*G8w-B diff --git a/resources/sprite/projects_1x/savings.png b/resources/sprite/projects_1x/savings.png deleted file mode 100644 index 39ffc216a166ca098e81ac44642212ff4ac6bd7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 JkcKij{eMjz)zkn0 diff --git a/resources/sprite/projects_1x/search.png b/resources/sprite/projects_1x/search.png deleted file mode 100644 index 85018f5c6519e836918de918878ff7c98fddd7f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 E1LK2^c>n+a diff --git a/resources/sprite/projects_1x/shield.png b/resources/sprite/projects_1x/shield.png deleted file mode 100644 index 78a6e7494e824ca7c2ed398d99ef0811effb3fa8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/speed.png b/resources/sprite/projects_1x/speed.png deleted file mode 100644 index 8f2c9430833de2db877b027ab8e71da0b3ba5826..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 O@HI2CG|V*Ebm-roFOZr5 diff --git a/resources/sprite/projects_1x/sprint.png b/resources/sprite/projects_1x/sprint.png deleted file mode 100644 index 1e6acc7399a4cf33f444d6527cf4006a6f15dfaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 diff --git a/resources/sprite/projects_1x/storage.png b/resources/sprite/projects_1x/storage.png deleted file mode 100644 index ede9d46c5abf7a6facf7955fbc54c4515fa44e6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 zcmeHN2|Sfs*WV)ZR2f3LL`a6rnTKP{lqsYE#ZeN<%@mPL>5^oQsLVq}DWOcEgedcr zIlA;_h!W@9Pha_TZs&yW-ro1uYyEzI&)#dTz1Ci9J$pa5T~WlqH9){zvG zQbwqY=!tnzrYUV+_sXZTyrQRHK*5`w(*e+u<{oB0ImbZ&W;|tNwr?pWc?bwxUQm#N zV(r-C9h>|yG$TsU`v|O+=&U^hQ7 z=RPy|0(iyEM7t9Jv&-!C1PP&lZG%;SGO&>bnRR>4s{oT7fX-U8ToSbKgB=>i*6QHa zJy2XrOOXReDZviC0N-tZ$Q_thad5bRbJ2iKb=+9y-S%wSAzqlN=p31RPDvGSGg5v> z5@Tb5%{;XljN9qNE!J4XC*x6dbD6!QiM{ORuWcP8vN=GJ@cVR-bqJmO^XSrp#l~~TK6uJ}nx1;~u$R+Yc)zzA(afvTXOmh< zo9Zr+owMv13{m@Zj{@_F^~IKQ4aHF&8F;lePpZUE20|YXjzRZ#Um8 zp4w4HoQe0R)!k zO*n!{8KZq?*h|!j)(3I2Jqe)G+oBmNrY@v^-jK~mopoIH#2QKeeX0*arK^DO*-w6j zYC@O2bM$0iQr<=7r%EuNQ@uv<{IHWyObA0l?DG?Mm}M`BCk{Q&u%T%SkwaDPD1N<> zM5O%K4uOg?rQ19C$ifa)-`%CQq$;64AmDnscE2^7l zndr2rr?PG06kXRwCP7AcPOp@EOIWJr9j*uKK9p~?6c+L~QRm}mS|74Okk&l_RW8A~ zJ`g3$oqutS#_b!14eJ|J8;Aw|ld`UbzhJguw3$9~^R?51b)Dgxbt0b|H&hR+y^efMIO$ADXj5*778MQI0cLoOH;Bcv2!KJkNL0z1`NkjU`!BD__WJpKW?XWQ0kEdWK$x+M6Qr z?9r6CAch74K_I#b9~7_?=jrm_XnZIf6M3zVH79ZwmH zihp>(D_+Y!rOUNw=;J02!8yY@yN@YTYLq6#xs;s5?Uc0}Wgd$;+RLyCR<^&>L+vk9 zKqXm(TSWGp3(c>Wx!$Pyhbqm5BNhAlIQ#4>>?*Ev5p%I~X=;yXkHzR~=O=GVme!Ki zs;qfdbFHQ+S}ayps9AU@b||(vw)>v>UYEUmd8v8#tu%7__a>W;)@A97HrQKt?HPAxbo}Fix=V5`iWJKS4oLx2+ zRuty(z~hfOSrRJ$R_YAay{w)m@0_5M+9TB!Q+s7h-sACP#IPXRq>i?(MWiopL-n@u zBXI_?FVxVC==_sD69GYinrEv8BIN{PSt>fKiu!jsO*!uGach{0i_MKK9ZhY&IVL`K zWX!+g>NC-++u}_{PChTILcP)(sF$a>8otA}JJVAarR$BpJH#P)NHEkmtNGTwBX4D?p? zHd`}0<93?;QLwyJyVd)g)=|X^3HgfjiXmsS&JL7hvD;Mrc`=K9dMK(kwDt(K?{3f6 zP0vXz1}%chJSn+-{e6x7)rv^6wJkl}i^m zD$^$MK=grpg@Co`vqqCR6OChBerAW)0%5Y)p_y*^#!Q`%`tflBJg7xC{0WGL~yqk5#)p@nu zF8vu=DCWxfSR{#WApab9+QmXGDy_~~sd$E%Q*3s^vQkAtK9@o-Ix3~JYlr2bN6>@T zr>Zlpd~@a>9}l`GxH+8UiEZx1%(bTcqMTskKuVO~mm#*)*l$YeEY0S@RGFX&(R5C}#(Y2ktkACfTzdgj6GWXBt@!B=& zW{es~W_uQKxoO*aA1HZxw&X5>?HdXs@&R9uHyzER`*lqOO}p<}eDsTBk)sbhpH0`! z7)gJog{Q-1fW_bb>7(e5%XiW;%JUD`SvOb@4|eg#n^8xkM-E0(AE#<oHYDsC_dKEdDo(O=6L-Wi+kaF(LWp8 z%?hXIdN09&d0rV=BE;;GWz36MK6bgvTOhFG+FobW-6(+Qy1Jbdq`gVc8V3v zDtJ^WW;{kU)*xoq%+lJVd(L?3vuCb z9-aapI?UUz<+%?Xs_i~XWB>L6ty52f3MObsx=^}y-}rr}@tpR74aWD4V{S?vv>S06 zk(m#Bp<7vSr649df1hpsm|M|ZckAh4mUxNU&dDOzcMO=O#&}8D&Y}r7`{~EiQ{4=m zo+r5HYO4!cow>)d3Uvz)PAZHlwxT-y8|BUBJ6hg$oH<(ToG?+}p*BtI>r*!$Iu$~L zS{o7_Qte0O_a=U)oTOy0{E4~YPbsLn!*yKojPuv#tFsvy1U+XO-!#|ON7W}rjz@+) zvOAqLH&XnD>1KOHX~pJ;Ph3QV4ovQu9W8P0aAtjby_-h2|1{ef9*oV0+fxS5Q)a`M z!on~_gi#Zp4vFx$!}BKFA$5Ii0Nl0$;N=6r2MoLp1MvF}07lFKkct9;(f-oG$EpBu zr)VfE8oCgGY9NXsz+j*%4qAhQ|Czm5$Ot)z8Fgd+fLDljw$KEO z9qJ`FO7@8nig=i1mdj;C1D(=Ik7HV0Z^0!e!5I*#oeH z!IkTUAhA6l0)L2^FF@K0%CP;HTWdug{Gg$UFF@MAyayN~e!{K;er-frNQ9bQ_8s_R zvwziC{?z_zD>mz!&33&qHz)r|t4k7yAwe?-*7iGl32!#HZJ}zBE zj_4uuU7hbTzbGev9=7y9Nh@)Jm|uf{8h_ZMfzMAwbR{TL5uP#0(Y|t<=J5z{U z2>33xKu8dV4FWe|ZCZ;rG-SVzh1iHk2azE<2rVA_P5a+olW$(FaOdK)1g|c> znjq(JB;N)QSr8)-UkPa=JVb`*V4v9`YZ2keC6edWnk>o{{x_`EntYQgq=WAk#(VE$ zS;DJ}&&l6b6MWkW)?`=S#TUuStzwP*b)1024F~@GDTTpG;Xl&-DRucrW{zcaH4vKomo~hWP&xp3}-V zr@%#e$cL0y5dQ=rc5!~Ffihfk`pZ|&rDO&9=)Lf(#8L(ZiY&F-KUHrfPxhZW!KFG|4P>dA`dNCvOhw>H6N6EnIOXEx SLEr!WXHz^0L$+9Gj_y+z)98k5&%S$$c_c#?;HexP{$4eIdQ_)(Z%tSt)mm88U(`V zbkWhq?z}YsZoP^6FsS|{jr7vsf`Ue{&utAyJ!*VLJ%vyost7hNCIWKxV5XEFYTe2M zN=i8N^~u55VPQTusCBuCuM>9TjWOK|^S>W_yC*eA^`~7j6FKvV1ub|L z_{7nwLb@V8#F+|54!rZPtEn9x;`gfiLq?@AQ=akH(FVaf)hNz zoc-$icHon^9OsDzOm8z$V1Jb`&V3yT}L76+)5=M1I(IF?5~!G%C7E?=scRb0u}6raZ# z&(M(f2uHIT?J+7*i+vXHa=caUadd*d!esB}UjvXFL5+xZe$B0!G_Sc?G^~*H49`?K zE}YrYa&Î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 ajz*(tqVuk;Kd=%3S5sHhP$L&%bK<|A0PXDn diff --git a/resources/sprite/projects_1x/warning.png b/resources/sprite/projects_1x/warning.png deleted file mode 100644 index 18757ecc5cc668fd766eb2a8f732600a8555ccc8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 Q3}I8%m9>>p70pil7bHeCIsgCw diff --git a/resources/sprite/projects_1x/whale.png b/resources/sprite/projects_1x/whale.png deleted file mode 100644 index df2039235a1a12d606c06d0eba20bcb700c3adbc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 bPnek@I@11m*rCJ)$)}Q>nry0!q5FRT@Y5hl diff --git a/resources/sprite/projects_2x/8ball.png b/resources/sprite/projects_2x/8ball.png deleted file mode 100644 index 8a40ad6c3a2b4aa908aaeaca0ede203e94678cae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 Uwc8-q18o~Q+{QB6e8#%}0{!>xf&c&j diff --git a/resources/sprite/projects_2x/alien.png b/resources/sprite/projects_2x/alien.png deleted file mode 100644 index 7956705045ad48c03b1c928dd2db0afa5d396045..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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

?uQ~Zfph{(oIhA2uRu;9qgtkB zjZ7WY`tTiuhHs**g&IaE8<9p@)G$ILmnbuf20|Hbw9`Tvp&hoASwj8KLf?X-RyMi3jzw2a^8%#n74kFVw5XL^kgfiS{riBth zGiWI@j1oc_ZZy+E385LZlo>_|p$s>gX`zJB3|h(zql8d~8_l#(LTCmpWrk5gD8r3r zS|}kjgO)PGq`dD-ndRS43x41NzT2+`L>0&aAR<5r6ICxjpoIMYoAMF>RR}ar;QMpn z58%c>{qBU2I;+PY`C&%GX&_&9dw1z86nhM7~(=9{Q3h2Xix+K?}oyQ zKzIQt1_VtcAVAH9A?~~V@B$HD9Fm&6K*tawo#DT(F%zl()vBnvFr;Re^*?|V6mrNI z30xo02!p{F_`^&sAl^WdfHVO4t9P?*rw_Fp7q1TMZe z5nFA9I&gQ0JCnriD#v8CQFE3>=p?CS_=UF&QajV2AN)TQ_@yAaOw^oZQ5sMtPz<0{ znMyr)f`Fyc22Ir`Vuj!bWCsfH140@=XmJe!uWc%ToCgvEq!$QXr->$nuECiI=O$v8 zH4$2-IAt)hqh5((pgRT&i5IRGE&fGy)2ucW@AwXyDpeqC=gw7D4Gk4Gx lf)YY!2+)~3;Dv(0LEFi4Snn1+_=85o)X>r(U4Ql7{{xfRW~=}J diff --git a/resources/sprite/projects_2x/art.png b/resources/sprite/projects_2x/art.png deleted file mode 100644 index c6450ed9bcb936f3c4227175319b714cea517fd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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

  • GxpB8zYHpe_X5$eeX6@ zTwUDepZysx`nwvgDK4uNDXi=(KIX})?dxKn3*Gx;m8_Gj>LUH%kHO$ig1@6lS)nwjEe(W}= z{CJ9a%Ir_N@AMuU6!_%oOs~y<^ge&XqExr=itK!&Nfw|qC*_lFB5&5Qq*+n`vt;M=LsR(B(-0(u1m)Cuqh zRaDO%IW!OUn{soFEhiDg+5rUNv56qQ)j?QB5PuCLh}ZT6F(!y0dbsSGeRVuRgesXB z>RGSmBTjWNtKqAwgRCr42Nv_!XKzWN?~N5VF4VZKu&X9u*WHjB7vh6tEa*rJOCfXt zG$b?x9e}8=8sI}G4b;*vgz`*AY0ONH&BW$5p~ih`l7XIpV};y7J860hN&ZKr%=+{r zQ)8x8%_G)#*vR^*Ww|Pj7uZGX{SVX8s{uzSIZE#XkC}fA2Szr=0!V=X{(6r5VKf36 zjZQ{2puPr8AuFKQ2QrOr$dLlr6w-_s{z0uufEuCkKTJp`jbOP+M2dhx6*E)OtEE*k z)|=L}n%t(Mh7x)P!yKfA8|G#lYn;D<(HZpwGm#ldo*I(Xkuo8gfQ*yr^&z85$V^xW z30q2?Y4t+*`J0x8S0OSlnfAYs$)uupIe_f-6bio|0QB-Sk+o)Yk@jcY^8fXro@>rr zjk32c`ukMEXr3^$ON)I$D)}kqA__$MeQC`QBU{nIx1E9PHK$jTxgv>l0m{5Q>O;AlH zKo|qS3UG8WtN_xW-wo}`C_WwXeE~QEkjRix{s!^}5h%R9Ggr!fj>&#P*LfY`kdbGD9$ch!+11yQIWh$* z!LuHmCfphR30MsH(gNk-O!Kg?y(xygNXr0CwmmG$o}nTjW_te3QCBylnSAv+m?>hE zc8^v=U`r~Xlc$zeo}PXjAtXryLoW|qSxc^qjXgS)CWwa+$9FowjwYiQl+Y1+fUGw~ zE&_Z$Esnz&PLi-jt?39^gBgtpfDjw|65vUbkpUz99+06FAOYA0K*AN2x;v>Cw)CeZ zlf9+77DC3ofKLE8=kw(JPDQ4Uau42?K5j7V*ikhevl z7=tTVo=3RC4U|UkJVG%BSFnt>5Up*T7!-ulG=w%_FaS=~G@!c>dkVM-xJU~jV4v8z zj^J4s+%IvGntl4is4{js!boSk$a#~!UChp;(%;4-g#Mrlk9ZS>iL2Ws>9-kQypFWX z_+e5h&m&BX!%C7SWVT_Y0HeI^z5J37v)I0&Z_lB%k!Ib-+hj&YXDV-rN9>tuXno=V zD2h+?oLis*AK6DU%h!^Q;K7;e%#^fo+6T~&M_-syONQ1B(4b7wg5#MT;B!=@L;xc_ z%j<#z%v$tWWoIoY`lkR}Jf!+@>s1eE>J z5ae4!xWynFwH5g8jgQF34kpkEy|V>C`@){6Y$jW{}AHeD9XPA zkMHUJ0dxZ_0&E1ZP3+7OdX-m!5FcS~0pMfB9sq18PU6!5Bpik!fEj=Y0B5K*OIBc>uhRPXplX?`HsKh@IO@DEkKhpV6{Q?x29JTVHnWN6@*B3iY@3k73V0sjutC{Y$MXo=CgiY!-^L?^rP=XQzs<#j!(MJT zb-&N>YBv*dwql+`IBQR~wecLnwh1|_faeg-+LLW5T2bbA>aY9Rw$4h!*Is?)i2(ewB&{Y+IE1Vm|HcD;e@i{pgnwcrnat46A)e>K)3_vIyRdz%(l{tU z&Mqwb7N8H{%*icw-$>9YuK+Ug&kO-uPpjdVtv4TRmS6X8GwOe<;a9O0`mhgF!aibO zIodCdDr?j@{H)GYD4zq{&1G z(YdQB@pfUk#UW(paY><$dc1({0F;p#=!BC%hBsu)2tSkv0pL9nIs#`GN$3P>ous^7 zLT+;iX#{&RUo`+9E&dilbi@r>oa=*M%^{>g@lb9mK!y}F3QHi4*A={m{8IF* zIs}a@2cUP6$25Gh`wW?1jmTZhuh#D0w!J)uaG7g)4&gb3%PhcU&Ed@uo^zAqPKPatjhyVZp diff --git a/resources/sprite/projects_2x/medical.png b/resources/sprite/projects_2x/medical.png deleted file mode 100644 index aec84f070bce287677fbf88811a706b630aaa328..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/mobile.png b/resources/sprite/projects_2x/mobile.png deleted file mode 100644 index 68bb17cc1b0f2f4cd8e90e98f0c216151048fa19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 O>YB~5FiJLDvHSms>3i}3 diff --git a/resources/sprite/projects_2x/news.png b/resources/sprite/projects_2x/news.png deleted file mode 100644 index 8285a7c02ddfece133d82fe6dba248e983b0af92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/piechart.png b/resources/sprite/projects_2x/piechart.png deleted file mode 100644 index 2c403ed33e659d2b7c69094ef1865a680a751495..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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

    >+Xkz1(j+mGu{vR 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 m+L?0$Lc7mcIs#rq=y diff --git a/resources/sprite/projects_2x/radiate.png b/resources/sprite/projects_2x/radiate.png deleted file mode 100644 index 2195a8f8f3cfa8790feab32a1a58d56e0b735be4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 ZuFkB*{gpO8dq$yc)+234B$&Ca`X2)75nuoS diff --git a/resources/sprite/projects_2x/savings.png b/resources/sprite/projects_2x/savings.png deleted file mode 100644 index 8499c023a6d6ff1fcec0a87ca0560fc01b290f46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 M3`^r=!zJ7Q3)?TnZvX%Q diff --git a/resources/sprite/projects_2x/search.png b/resources/sprite/projects_2x/search.png deleted file mode 100644 index 3b196295061e68664fb8b71b8ac10deb7bd5c0aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/shield.png b/resources/sprite/projects_2x/shield.png deleted file mode 100644 index 73b96ae8929d535add2cfbf61a79e2c08d36993c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/speed.png b/resources/sprite/projects_2x/speed.png deleted file mode 100644 index b986e9fdd80327eb8a2ce1809272c4d1e3f62aff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/sprint.png b/resources/sprite/projects_2x/sprint.png deleted file mode 100644 index feb29ef0fcda77b1bf8c4f71a1f7340af094b045..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/scripts/celerity/generate_sprites.php b/scripts/celerity/generate_sprites.php index 0fbdff60ab..61f63d155d 100755 --- a/scripts/celerity/generate_sprites.php +++ b/scripts/celerity/generate_sprites.php @@ -30,7 +30,6 @@ $sheets = array( 'menu' => $generator->buildMenuSheet(), 'tokens' => $generator->buildTokenSheet(), 'login' => $generator->buildLoginSheet(), - 'projects' => $generator->buildProjectsSheet(), ); list($err) = exec_manual('optipng'); diff --git a/src/applications/celerity/CeleritySpriteGenerator.php b/src/applications/celerity/CeleritySpriteGenerator.php index 4825609fe6..55346c915c 100644 --- a/src/applications/celerity/CeleritySpriteGenerator.php +++ b/src/applications/celerity/CeleritySpriteGenerator.php @@ -86,38 +86,6 @@ final class CeleritySpriteGenerator extends Phobject { return $sheet; } - public function buildProjectsSheet() { - $icons = $this->getDirectoryList('projects_1x'); - $scales = array( - '1x' => 1, - '2x' => 2, - ); - $template = id(new PhutilSprite()) - ->setSourceSize(50, 50); - - $sprites = array(); - $prefix = 'projects-'; - foreach ($icons as $icon) { - $sprite = id(clone $template) - ->setName($prefix.$icon) - ->setTargetCSS('.'.$prefix.$icon); - - foreach ($scales as $scale_key => $scale) { - $path = $this->getPath('projects_'.$scale_key.'/'.$icon.'.png'); - $sprite->setSourceFile($path, $scale); - } - $sprites[] = $sprite; - } - - $sheet = $this->buildSheet('projects', true); - $sheet->setScales($scales); - foreach ($sprites as $sprite) { - $sheet->addSprite($sprite); - } - - return $sheet; - } - public function buildLoginSheet() { $icons = $this->getDirectoryList('login_1x'); $scales = array( diff --git a/src/applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php b/src/applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php index 581f1ed5f9..5e12832cac 100644 --- a/src/applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php +++ b/src/applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php @@ -44,7 +44,7 @@ final class PhabricatorFilesComposeIconBuiltinFile public static function getAllIcons() { $root = dirname(phutil_get_library_root('phabricator')); - $root = $root.'/resources/sprite/projects_2x/'; + $root = $root.'/resources/builtin/projects/'; $quips = self::getIconQuips(); diff --git a/src/applications/files/controller/PhabricatorFileComposeController.php b/src/applications/files/controller/PhabricatorFileComposeController.php index 3f2667b9d1..17e605f3a9 100644 --- a/src/applications/files/controller/PhabricatorFileComposeController.php +++ b/src/applications/files/controller/PhabricatorFileComposeController.php @@ -110,8 +110,8 @@ final class PhabricatorFileComposeController ), ), id(new PHUIIconView()) - ->setSpriteIcon($icon) - ->setSpriteSheet(PHUIIconView::SPRITE_PROJECTS)); + ->setIconFont($icon) + ->addClass('compose-icon-bg')); } $dialog_id = celerity_generate_unique_node_id(); @@ -122,8 +122,8 @@ final class PhabricatorFileComposeController $preview = id(new PHUIIconView()) ->setID($preview_id) ->addClass('compose-background-'.$value_color) - ->setSpriteIcon($value_icon) - ->setSpriteSheet(PHUIIconView::SPRITE_PROJECTS); + ->setIconFont($value_icon) + ->addClass('compose-icon-bg'); $color_input = javelin_tag( 'input', diff --git a/src/view/phui/PHUIIconView.php b/src/view/phui/PHUIIconView.php index c9d8a0808e..c383aff30b 100644 --- a/src/view/phui/PHUIIconView.php +++ b/src/view/phui/PHUIIconView.php @@ -4,7 +4,6 @@ final class PHUIIconView extends AphrontTagView { const SPRITE_TOKENS = 'tokens'; const SPRITE_LOGIN = 'login'; - const SPRITE_PROJECTS = 'projects'; const HEAD_SMALL = 'phuihead-small'; const HEAD_MEDIUM = 'phuihead-medium'; diff --git a/webroot/rsrc/css/application/people/people-profile.css b/webroot/rsrc/css/application/people/people-profile.css index 089402b4d7..c22cceb8e5 100644 --- a/webroot/rsrc/css/application/people/people-profile.css +++ b/webroot/rsrc/css/application/people/people-profile.css @@ -37,6 +37,14 @@ form.compose-dialog { background-color: {$darkgreytext}; } +.compose-dialog .compose-icon-bg { + color: #fff; + line-height: 50px; + width: 50px; + text-align: center; + font-size: 32px; +} + .compose-dialog .compose-background-red { background-color: {$red}; } diff --git a/webroot/rsrc/css/sprite-projects.css b/webroot/rsrc/css/sprite-projects.css deleted file mode 100644 index 16abde0551..0000000000 --- a/webroot/rsrc/css/sprite-projects.css +++ /dev/null @@ -1,308 +0,0 @@ -/** - * @provides sprite-projects-css - * @generated - */ - -.sprite-projects { - background-image: url(/rsrc/image/sprite-projects.png); - background-repeat: no-repeat; -} - -@media -only screen and (min-device-pixel-ratio: 1.5), -only screen and (-webkit-min-device-pixel-ratio: 1.5), -only screen and (min-resolution: 1.5dppx) { - .sprite-projects { - background-image: url(/rsrc/image/sprite-projects-X2.png); - background-size: 408px 459px; - } -} - - -.projects-8ball { - background-position: 0px 0px; -} - -.projects-alien { - background-position: -51px 0px; -} - -.projects-announce { - background-position: -102px 0px; -} - -.projects-art { - background-position: -153px 0px; -} - -.projects-award { - background-position: -204px 0px; -} - -.projects-bacon { - background-position: -255px 0px; -} - -.projects-bandaid { - background-position: -306px 0px; -} - -.projects-beer { - background-position: -357px 0px; -} - -.projects-bomb { - background-position: 0px -51px; -} - -.projects-briefcase { - background-position: -51px -51px; -} - -.projects-bug { - background-position: -102px -51px; -} - -.projects-calendar { - background-position: -153px -51px; -} - -.projects-cloud { - background-position: -204px -51px; -} - -.projects-coffee { - background-position: -255px -51px; -} - -.projects-creditcard { - background-position: -306px -51px; -} - -.projects-death { - background-position: -357px -51px; -} - -.projects-desktop { - background-position: 0px -102px; -} - -.projects-dropbox { - background-position: -51px -102px; -} - -.projects-education { - background-position: -102px -102px; -} - -.projects-experimental { - background-position: -153px -102px; -} - -.projects-fa-briefcase { - background-position: -204px -102px; -} - -.projects-fa-bug { - background-position: -255px -102px; -} - -.projects-fa-building { - background-position: -306px -102px; -} - -.projects-fa-calendar { - background-position: -357px -102px; -} - -.projects-fa-cloud { - background-position: 0px -153px; -} - -.projects-fa-credit-card { - background-position: -51px -153px; -} - -.projects-fa-envelope { - background-position: -102px -153px; -} - -.projects-fa-flag-checkered { - background-position: -153px -153px; -} - -.projects-fa-flask { - background-position: -204px -153px; -} - -.projects-fa-folder { - background-position: -255px -153px; -} - -.projects-fa-lock { - background-position: -306px -153px; -} - -.projects-fa-tags { - background-position: -357px -153px; -} - -.projects-fa-trash-o { - background-position: 0px -204px; -} - -.projects-fa-truck { - background-position: -51px -204px; -} - -.projects-fa-umbrella { - background-position: -102px -204px; -} - -.projects-fa-users { - background-position: -153px -204px; -} - -.projects-facebook { - background-position: -204px -204px; -} - -.projects-facility { - background-position: -255px -204px; -} - -.projects-film { - background-position: -306px -204px; -} - -.projects-forked { - background-position: -357px -204px; -} - -.projects-games { - background-position: 0px -255px; -} - -.projects-ghost { - background-position: -51px -255px; -} - -.projects-gift { - background-position: -102px -255px; -} - -.projects-globe { - background-position: -153px -255px; -} - -.projects-golf { - background-position: -204px -255px; -} - -.projects-heart { - background-position: -255px -255px; -} - -.projects-intergalactic { - background-position: -306px -255px; -} - -.projects-lock { - background-position: -357px -255px; -} - -.projects-mail { - background-position: 0px -306px; -} - -.projects-martini { - background-position: -51px -306px; -} - -.projects-medical { - background-position: -102px -306px; -} - -.projects-mobile { - background-position: -153px -306px; -} - -.projects-music { - background-position: -204px -306px; -} - -.projects-news { - background-position: -255px -306px; -} - -.projects-orgchart { - background-position: -306px -306px; -} - -.projects-peoples { - background-position: -357px -306px; -} - -.projects-piechart { - background-position: 0px -357px; -} - -.projects-poison { - background-position: -51px -357px; -} - -.projects-putabirdonit { - background-position: -102px -357px; -} - -.projects-radiate { - background-position: -153px -357px; -} - -.projects-savings { - background-position: -204px -357px; -} - -.projects-search { - background-position: -255px -357px; -} - -.projects-shield { - background-position: -306px -357px; -} - -.projects-speed { - background-position: -357px -357px; -} - -.projects-sprint { - background-position: 0px -408px; -} - -.projects-star { - background-position: -51px -408px; -} - -.projects-storage { - background-position: -102px -408px; -} - -.projects-tablet { - background-position: -153px -408px; -} - -.projects-travel { - background-position: -204px -408px; -} - -.projects-twitter { - background-position: -255px -408px; -} - -.projects-warning { - background-position: -306px -408px; -} - -.projects-whale { - background-position: -357px -408px; -} diff --git a/webroot/rsrc/image/sprite-projects-X2.png b/webroot/rsrc/image/sprite-projects-X2.png deleted file mode 100644 index 3b3525417a082414bbd172a3b6d4eba464ef2560..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37963 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 diff --git a/webroot/rsrc/image/sprite-projects.png b/webroot/rsrc/image/sprite-projects.png deleted file mode 100644 index 8c85c59e1bca5b23d1d5877413c04db60eac3058..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18024 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 os3 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 Date: Tue, 19 Jan 2016 07:28:10 -0800 Subject: [PATCH 31/66] Add a missing transaction query class for panel transactions Summary: Ref T10054. The daemons look for this but currently can't find it. Test Plan: Ran daemons, clean exit on profile menu edits instead of permanent failure. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15053 --- src/__phutil_library_map__.php | 2 ++ ...icatorProfilePanelConfigurationTransactionQuery.php | 10 ++++++++++ 2 files changed, 12 insertions(+) create mode 100644 src/applications/search/query/PhabricatorProfilePanelConfigurationTransactionQuery.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 1a4684f464..ff47a4e360 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2841,6 +2841,7 @@ phutil_register_library_map(array( 'PhabricatorProfilePanelConfiguration' => 'applications/search/storage/PhabricatorProfilePanelConfiguration.php', 'PhabricatorProfilePanelConfigurationQuery' => 'applications/search/query/PhabricatorProfilePanelConfigurationQuery.php', 'PhabricatorProfilePanelConfigurationTransaction' => 'applications/search/storage/PhabricatorProfilePanelConfigurationTransaction.php', + 'PhabricatorProfilePanelConfigurationTransactionQuery' => 'applications/search/query/PhabricatorProfilePanelConfigurationTransactionQuery.php', 'PhabricatorProfilePanelEditEngine' => 'applications/search/editor/PhabricatorProfilePanelEditEngine.php', 'PhabricatorProfilePanelEditor' => 'applications/search/editor/PhabricatorProfilePanelEditor.php', 'PhabricatorProfilePanelEngine' => 'applications/search/engine/PhabricatorProfilePanelEngine.php', @@ -7216,6 +7217,7 @@ phutil_register_library_map(array( ), 'PhabricatorProfilePanelConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorProfilePanelConfigurationTransaction' => 'PhabricatorApplicationTransaction', + 'PhabricatorProfilePanelConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorProfilePanelEditEngine' => 'PhabricatorEditEngine', 'PhabricatorProfilePanelEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorProfilePanelEngine' => 'Phobject', diff --git a/src/applications/search/query/PhabricatorProfilePanelConfigurationTransactionQuery.php b/src/applications/search/query/PhabricatorProfilePanelConfigurationTransactionQuery.php new file mode 100644 index 0000000000..dba7120d1d --- /dev/null +++ b/src/applications/search/query/PhabricatorProfilePanelConfigurationTransactionQuery.php @@ -0,0 +1,10 @@ + Date: Tue, 19 Jan 2016 09:36:40 -0800 Subject: [PATCH 32/66] When publishing project transactions, load ancestor members Summary: Ref T10010. Fixes T10107. When we publish a transaction about a project, we perform visibility checks for many different users. We need to know all of the ancestors' members to perform these checks. Test Plan: - Before patch: when updating a subproject, daemons fatal trying to publish things because they can not test visibility of parent projects. - After patch: daemons successfully publish subproject updates. - Also added a unit test. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10010, T10107 Differential Revision: https://secure.phabricator.com/D15054 --- .../PhabricatorProjectCoreTestCase.php | 69 ++++++++++++++----- .../PhabricatorProjectTransactionEditor.php | 2 +- .../project/query/PhabricatorProjectQuery.php | 40 ++++++++--- 3 files changed, 83 insertions(+), 28 deletions(-) diff --git a/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php b/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php index 36c78386f3..3bd38353f6 100644 --- a/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php +++ b/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php @@ -113,6 +113,38 @@ final class PhabricatorProjectCoreTestCase extends PhabricatorTestCase { $this->assertTrue($caught instanceof Exception); } + public function testAncestorMembers() { + $user1 = $this->createUser(); + $user1->save(); + + $user2 = $this->createUser(); + $user2->save(); + + $parent = $this->createProject($user1); + $child = $this->createProject($user1, $parent); + + $this->joinProject($child, $user1); + $this->joinProject($child, $user2); + + $project = id(new PhabricatorProjectQuery()) + ->setViewer($user1) + ->withPHIDs(array($child->getPHID())) + ->needAncestorMembers(true) + ->executeOne(); + + $members = array_fuse($project->getParentProject()->getMemberPHIDs()); + ksort($members); + + $expect = array_fuse( + array( + $user1->getPHID(), + $user2->getPHID(), + )); + ksort($expect); + + $this->assertEqual($expect, $members); + } + public function testAncestryQueries() { $user = $this->createUser(); $user->save(); @@ -577,24 +609,6 @@ final class PhabricatorProjectCoreTestCase extends PhabricatorTestCase { $this->assertEqual($expect, $actual); } - private function attemptProjectEdit( - PhabricatorProject $proj, - PhabricatorUser $user, - $skip_refresh = false) { - - $proj = $this->refreshProject($proj, $user, true); - - $new_name = $proj->getName().' '.mt_rand(); - - $xaction = new PhabricatorProjectTransaction(); - $xaction->setTransactionType(PhabricatorProjectTransaction::TYPE_NAME); - $xaction->setNewValue($new_name); - - $this->applyTransactions($proj, $user, array($xaction)); - - return true; - } - public function testJoinLeaveProject() { $user = $this->createUser(); $user->save(); @@ -794,6 +808,25 @@ final class PhabricatorProjectCoreTestCase extends PhabricatorTestCase { pht('Engineering + Scan')); } + private function attemptProjectEdit( + PhabricatorProject $proj, + PhabricatorUser $user, + $skip_refresh = false) { + + $proj = $this->refreshProject($proj, $user, true); + + $new_name = $proj->getName().' '.mt_rand(); + + $xaction = new PhabricatorProjectTransaction(); + $xaction->setTransactionType(PhabricatorProjectTransaction::TYPE_NAME); + $xaction->setNewValue($new_name); + + $this->applyTransactions($proj, $user, array($xaction)); + + return true; + } + + private function newTask( PhabricatorUser $viewer, array $projects, diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php index 26cc3af86e..6db9b774e6 100644 --- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php +++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php @@ -582,7 +582,7 @@ final class PhabricatorProjectTransactionEditor return id(new PhabricatorProjectQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withPHIDs(array($object->getPHID())) - ->needMembers(true) + ->needAncestorMembers(true) ->executeOne(); } diff --git a/src/applications/project/query/PhabricatorProjectQuery.php b/src/applications/project/query/PhabricatorProjectQuery.php index e2d678e7d7..304dd956e1 100644 --- a/src/applications/project/query/PhabricatorProjectQuery.php +++ b/src/applications/project/query/PhabricatorProjectQuery.php @@ -30,6 +30,7 @@ final class PhabricatorProjectQuery private $needSlugs; private $needMembers; + private $needAncestorMembers; private $needWatchers; private $needImages; @@ -109,6 +110,11 @@ final class PhabricatorProjectQuery return $this; } + public function needAncestorMembers($need_ancestor_members) { + $this->needAncestorMembers = $need_ancestor_members; + return $this; + } + public function needWatchers($need_watchers) { $this->needWatchers = $need_watchers; return $this; @@ -220,8 +226,16 @@ final class PhabricatorProjectQuery $types[] = $watcher_type; } + $all_graph = $this->getAllReachableAncestors($projects); + + if ($this->needAncestorMembers) { + $src_projects = $all_graph; + } else { + $src_projects = $projects; + } + $all_sources = array(); - foreach ($projects as $project) { + foreach ($src_projects as $project) { if ($project->isMilestone()) { $phid = $project->getParentProjectPHID(); } else { @@ -234,10 +248,15 @@ final class PhabricatorProjectQuery ->withSourcePHIDs($all_sources) ->withEdgeTypes($types); + $need_all_edges = + $this->needMembers || + $this->needWatchers || + $this->needAncestorMembers; + // If we only need to know if the viewer is a member, we can restrict // the query to just their PHID. $any_edges = true; - if (!$this->needMembers && !$this->needWatchers) { + if (!$need_all_edges) { if ($viewer_phid) { $edge_query->withDestinationPHIDs(array($viewer_phid)); } else { @@ -253,7 +272,7 @@ final class PhabricatorProjectQuery } $membership_projects = array(); - foreach ($projects as $project) { + foreach ($src_projects as $project) { $project_phid = $project->getPHID(); if ($project->isMilestone()) { @@ -274,7 +293,7 @@ final class PhabricatorProjectQuery $membership_projects[$project_phid] = $project; } - if ($this->needMembers) { + if ($this->needMembers || $this->needAncestorMembers) { $project->attachMemberPHIDs($member_phids); } @@ -289,12 +308,15 @@ final class PhabricatorProjectQuery } } - $all_graph = $this->getAllReachableAncestors($projects); - $member_graph = $this->getAllReachableAncestors($membership_projects); + // If we loaded ancestor members, we've already populated membership + // lists above, so we can skip this step. + if (!$this->needAncestorMembers) { + $member_graph = $this->getAllReachableAncestors($membership_projects); - foreach ($all_graph as $phid => $project) { - $is_member = isset($member_graph[$phid]); - $project->setIsUserMember($viewer_phid, $is_member); + foreach ($all_graph as $phid => $project) { + $is_member = isset($member_graph[$phid]); + $project->setIsUserMember($viewer_phid, $is_member); + } } return $projects; From bf18b59f5fdc4981a27c1a3e4cc221901d6cd13e Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 19 Jan 2016 09:56:48 -0800 Subject: [PATCH 33/66] Update quickstart template Summary: This hasn't been updated in about 6 months, and keeping it fresh makes tests and instance launches a little faster. Test Plan: Ran `storage upgrade` on clean namespaces before and after patch, got ~5.6s before and ~4.2s after. Reviewers: chad Reviewed By: chad Differential Revision: https://secure.phabricator.com/D15055 --- resources/sql/quickstart.sql | 307 ++++++++++++++++++++++++++++++----- 1 file changed, 263 insertions(+), 44 deletions(-) diff --git a/resources/sql/quickstart.sql b/resources/sql/quickstart.sql index fdc1e673c7..1d1defd6de 100644 --- a/resources/sql/quickstart.sql +++ b/resources/sql/quickstart.sql @@ -342,10 +342,8 @@ CREATE TABLE `daemon_log` ( `explicitArgv` longtext COLLATE {$COLLATE_TEXT} NOT NULL, `dateCreated` int(10) unsigned NOT NULL, `dateModified` int(10) unsigned NOT NULL, - `envHash` binary(40) NOT NULL, `status` varchar(8) COLLATE {$COLLATE_TEXT} NOT NULL, `runningAsUser` varchar(255) COLLATE {$COLLATE_TEXT} DEFAULT NULL, - `envInfo` longtext COLLATE {$COLLATE_TEXT} NOT NULL, `daemonID` varchar(64) COLLATE {$COLLATE_TEXT} NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `key_daemonID` (`daemonID`), @@ -668,10 +666,38 @@ CREATE TABLE `draft` ( UNIQUE KEY `authorPHID` (`authorPHID`,`draftKey`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; +CREATE TABLE `draft_versioneddraft` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `objectPHID` varbinary(64) NOT NULL, + `authorPHID` varbinary(64) NOT NULL, + `version` int(10) unsigned NOT NULL, + `properties` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `dateCreated` int(10) unsigned NOT NULL, + `dateModified` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `key_object` (`objectPHID`,`authorPHID`,`version`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + CREATE DATABASE /*!32312 IF NOT EXISTS*/ `{$NAMESPACE}_drydock` /*!40100 DEFAULT CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} */; USE `{$NAMESPACE}_drydock`; +CREATE TABLE `drydock_authorization` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `phid` varbinary(64) NOT NULL, + `blueprintPHID` varbinary(64) NOT NULL, + `blueprintAuthorizationState` varchar(32) COLLATE {$COLLATE_TEXT} NOT NULL, + `objectPHID` varbinary(64) NOT NULL, + `objectAuthorizationState` varchar(32) COLLATE {$COLLATE_TEXT} NOT NULL, + `dateCreated` int(10) unsigned NOT NULL, + `dateModified` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `key_phid` (`phid`), + UNIQUE KEY `key_unique` (`objectPHID`,`blueprintPHID`), + KEY `key_blueprint` (`blueprintPHID`,`blueprintAuthorizationState`), + KEY `key_object` (`objectPHID`,`objectAuthorizationState`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + CREATE TABLE `drydock_blueprint` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `phid` varbinary(64) NOT NULL, @@ -731,6 +757,7 @@ CREATE TABLE `drydock_lease` ( `dateModified` int(10) unsigned NOT NULL, `resourceType` varchar(128) COLLATE {$COLLATE_TEXT} NOT NULL, `resourcePHID` varbinary(64) DEFAULT NULL, + `authorizingPHID` varbinary(64) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `key_phid` (`phid`), KEY `key_resource` (`resourcePHID`,`status`) @@ -738,20 +765,41 @@ CREATE TABLE `drydock_lease` ( CREATE TABLE `drydock_log` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `resourceID` int(10) unsigned DEFAULT NULL, - `leaseID` int(10) unsigned DEFAULT NULL, `epoch` int(10) unsigned NOT NULL, - `message` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `blueprintPHID` varbinary(64) DEFAULT NULL, + `resourcePHID` varbinary(64) DEFAULT NULL, + `leasePHID` varbinary(64) DEFAULT NULL, + `type` varchar(64) COLLATE {$COLLATE_TEXT} NOT NULL, + `data` longtext COLLATE {$COLLATE_TEXT} NOT NULL, PRIMARY KEY (`id`), - KEY `resourceID` (`resourceID`,`epoch`), - KEY `leaseID` (`leaseID`,`epoch`), - KEY `epoch` (`epoch`) + KEY `epoch` (`epoch`), + KEY `key_blueprint` (`blueprintPHID`,`type`), + KEY `key_resource` (`resourcePHID`,`type`), + KEY `key_lease` (`leasePHID`,`type`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + +CREATE TABLE `drydock_repositoryoperation` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `phid` varbinary(64) NOT NULL, + `authorPHID` varbinary(64) NOT NULL, + `objectPHID` varbinary(64) NOT NULL, + `repositoryPHID` varbinary(64) NOT NULL, + `repositoryTarget` longblob NOT NULL, + `operationType` varchar(32) COLLATE {$COLLATE_TEXT} NOT NULL, + `operationState` varchar(32) COLLATE {$COLLATE_TEXT} NOT NULL, + `properties` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `dateCreated` int(10) unsigned NOT NULL, + `dateModified` int(10) unsigned NOT NULL, + `isDismissed` tinyint(1) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `key_phid` (`phid`), + KEY `key_object` (`objectPHID`), + KEY `key_repository` (`repositoryPHID`,`operationState`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; CREATE TABLE `drydock_resource` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `phid` varbinary(64) NOT NULL, - `name` varchar(255) COLLATE {$COLLATE_TEXT} NOT NULL, `ownerPHID` varbinary(64) DEFAULT NULL, `status` varchar(32) COLLATE {$COLLATE_TEXT} NOT NULL, `type` varchar(64) COLLATE {$COLLATE_TEXT} NOT NULL, @@ -1044,6 +1092,8 @@ CREATE TABLE `harbormaster_build` ( `dateModified` int(10) unsigned NOT NULL, `buildGeneration` int(10) unsigned NOT NULL DEFAULT '0', `planAutoKey` varchar(32) COLLATE {$COLLATE_TEXT} DEFAULT NULL, + `buildParameters` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `initiatorPHID` varbinary(64) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `key_phid` (`phid`), UNIQUE KEY `key_planautokey` (`buildablePHID`,`planAutoKey`), @@ -1177,6 +1227,8 @@ CREATE TABLE `harbormaster_buildplan` ( `dateCreated` int(10) unsigned NOT NULL, `dateModified` int(10) unsigned NOT NULL, `planAutoKey` varchar(32) COLLATE {$COLLATE_TEXT} DEFAULT NULL, + `viewPolicy` varbinary(64) NOT NULL, + `editPolicy` varbinary(64) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `key_phid` (`phid`), UNIQUE KEY `key_planautokey` (`planAutoKey`), @@ -1331,6 +1383,24 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `{$NAMESPACE}_herald` /*!40100 DEFAULT USE `{$NAMESPACE}_herald`; +CREATE TABLE `edge` ( + `src` varbinary(64) NOT NULL, + `type` int(10) unsigned NOT NULL, + `dst` varbinary(64) NOT NULL, + `dateCreated` int(10) unsigned NOT NULL, + `seq` int(10) unsigned NOT NULL, + `dataID` int(10) unsigned DEFAULT NULL, + PRIMARY KEY (`src`,`type`,`dst`), + UNIQUE KEY `key_dst` (`dst`,`type`,`src`), + KEY `src` (`src`,`type`,`dateCreated`,`seq`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + +CREATE TABLE `edgedata` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `data` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + CREATE TABLE `herald_action` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `ruleID` int(10) unsigned NOT NULL, @@ -1583,10 +1653,11 @@ USE `{$NAMESPACE}_meta_data`; CREATE TABLE `patch_status` ( `patch` varchar(128) COLLATE {$COLLATE_TEXT} NOT NULL, `applied` int(10) unsigned NOT NULL, + `duration` bigint(20) unsigned DEFAULT NULL, PRIMARY KEY (`patch`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; -INSERT INTO `patch_status` VALUES ('phabricator:000.project.sql',1443545049),('phabricator:0000.legacy.sql',1443545049),('phabricator:001.maniphest_projects.sql',1443545049),('phabricator:002.oauth.sql',1443545049),('phabricator:003.more_oauth.sql',1443545049),('phabricator:004.daemonrepos.sql',1443545049),('phabricator:005.workers.sql',1443545049),('phabricator:006.repository.sql',1443545049),('phabricator:007.daemonlog.sql',1443545049),('phabricator:008.repoopt.sql',1443545049),('phabricator:009.repo_summary.sql',1443545049),('phabricator:010.herald.sql',1443545049),('phabricator:011.badcommit.sql',1443545049),('phabricator:012.dropphidtype.sql',1443545049),('phabricator:013.commitdetail.sql',1443545049),('phabricator:014.shortcuts.sql',1443545049),('phabricator:015.preferences.sql',1443545049),('phabricator:016.userrealnameindex.sql',1443545049),('phabricator:017.sessionkeys.sql',1443545049),('phabricator:018.owners.sql',1443545049),('phabricator:019.arcprojects.sql',1443545049),('phabricator:020.pathcapital.sql',1443545049),('phabricator:021.xhpastview.sql',1443545049),('phabricator:022.differentialcommit.sql',1443545049),('phabricator:023.dxkeys.sql',1443545049),('phabricator:024.mlistkeys.sql',1443545049),('phabricator:025.commentopt.sql',1443545049),('phabricator:026.diffpropkey.sql',1443545049),('phabricator:027.metamtakeys.sql',1443545049),('phabricator:028.systemagent.sql',1443545049),('phabricator:029.cursors.sql',1443545049),('phabricator:030.imagemacro.sql',1443545049),('phabricator:031.workerrace.sql',1443545049),('phabricator:032.viewtime.sql',1443545049),('phabricator:033.privtest.sql',1443545049),('phabricator:034.savedheader.sql',1443545049),('phabricator:035.proxyimage.sql',1443545049),('phabricator:036.mailkey.sql',1443545049),('phabricator:037.setuptest.sql',1443545049),('phabricator:038.admin.sql',1443545049),('phabricator:039.userlog.sql',1443545050),('phabricator:040.transform.sql',1443545050),('phabricator:041.heraldrepetition.sql',1443545050),('phabricator:042.commentmetadata.sql',1443545050),('phabricator:043.pastebin.sql',1443545050),('phabricator:044.countdown.sql',1443545050),('phabricator:045.timezone.sql',1443545050),('phabricator:046.conduittoken.sql',1443545050),('phabricator:047.projectstatus.sql',1443545050),('phabricator:048.relationshipkeys.sql',1443545050),('phabricator:049.projectowner.sql',1443545050),('phabricator:050.taskdenormal.sql',1443545050),('phabricator:051.projectfilter.sql',1443545050),('phabricator:052.pastelanguage.sql',1443545050),('phabricator:053.feed.sql',1443545050),('phabricator:054.subscribers.sql',1443545050),('phabricator:055.add_author_to_files.sql',1443545050),('phabricator:056.slowvote.sql',1443545050),('phabricator:057.parsecache.sql',1443545050),('phabricator:058.missingkeys.sql',1443545050),('phabricator:059.engines.php',1443545050),('phabricator:060.phriction.sql',1443545050),('phabricator:061.phrictioncontent.sql',1443545050),('phabricator:062.phrictionmenu.sql',1443545050),('phabricator:063.pasteforks.sql',1443545050),('phabricator:064.subprojects.sql',1443545050),('phabricator:065.sshkeys.sql',1443545050),('phabricator:066.phrictioncontent.sql',1443545050),('phabricator:067.preferences.sql',1443545050),('phabricator:068.maniphestauxiliarystorage.sql',1443545050),('phabricator:069.heraldxscript.sql',1443545050),('phabricator:070.differentialaux.sql',1443545050),('phabricator:071.contentsource.sql',1443545050),('phabricator:072.blamerevert.sql',1443545050),('phabricator:073.reposymbols.sql',1443545050),('phabricator:074.affectedpath.sql',1443545050),('phabricator:075.revisionhash.sql',1443545050),('phabricator:076.indexedlanguages.sql',1443545050),('phabricator:077.originalemail.sql',1443545050),('phabricator:078.nametoken.sql',1443545050),('phabricator:079.nametokenindex.php',1443545050),('phabricator:080.filekeys.sql',1443545050),('phabricator:081.filekeys.php',1443545050),('phabricator:082.xactionkey.sql',1443545050),('phabricator:083.dxviewtime.sql',1443545051),('phabricator:084.pasteauthorkey.sql',1443545051),('phabricator:085.packagecommitrelationship.sql',1443545051),('phabricator:086.formeraffil.sql',1443545051),('phabricator:087.phrictiondelete.sql',1443545051),('phabricator:088.audit.sql',1443545051),('phabricator:089.projectwiki.sql',1443545051),('phabricator:090.forceuniqueprojectnames.php',1443545051),('phabricator:091.uniqueslugkey.sql',1443545051),('phabricator:092.dropgithubnotification.sql',1443545051),('phabricator:093.gitremotes.php',1443545051),('phabricator:094.phrictioncolumn.sql',1443545051),('phabricator:095.directory.sql',1443545051),('phabricator:096.filename.sql',1443545051),('phabricator:097.heraldruletypes.sql',1443545051),('phabricator:098.heraldruletypemigration.php',1443545051),('phabricator:099.drydock.sql',1443545051),('phabricator:100.projectxaction.sql',1443545051),('phabricator:101.heraldruleapplied.sql',1443545051),('phabricator:102.heraldcleanup.php',1443545051),('phabricator:103.heraldedithistory.sql',1443545051),('phabricator:104.searchkey.sql',1443545051),('phabricator:105.mimetype.sql',1443545051),('phabricator:106.chatlog.sql',1443545051),('phabricator:107.oauthserver.sql',1443545051),('phabricator:108.oauthscope.sql',1443545051),('phabricator:109.oauthclientphidkey.sql',1443545051),('phabricator:110.commitaudit.sql',1443545051),('phabricator:111.commitauditmigration.php',1443545051),('phabricator:112.oauthaccesscoderedirecturi.sql',1443545051),('phabricator:113.lastreviewer.sql',1443545051),('phabricator:114.auditrequest.sql',1443545051),('phabricator:115.prepareutf8.sql',1443545051),('phabricator:116.utf8-backup-first-expect-wait.sql',1443545053),('phabricator:117.repositorydescription.php',1443545053),('phabricator:118.auditinline.sql',1443545053),('phabricator:119.filehash.sql',1443545053),('phabricator:120.noop.sql',1443545053),('phabricator:121.drydocklog.sql',1443545053),('phabricator:122.flag.sql',1443545053),('phabricator:123.heraldrulelog.sql',1443545053),('phabricator:124.subpriority.sql',1443545053),('phabricator:125.ipv6.sql',1443545053),('phabricator:126.edges.sql',1443545053),('phabricator:127.userkeybody.sql',1443545053),('phabricator:128.phabricatorcom.sql',1443545053),('phabricator:129.savedquery.sql',1443545053),('phabricator:130.denormalrevisionquery.sql',1443545053),('phabricator:131.migraterevisionquery.php',1443545053),('phabricator:132.phame.sql',1443545053),('phabricator:133.imagemacro.sql',1443545053),('phabricator:134.emptysearch.sql',1443545053),('phabricator:135.datecommitted.sql',1443545053),('phabricator:136.sex.sql',1443545053),('phabricator:137.auditmetadata.sql',1443545053),('phabricator:138.notification.sql',1443545053),('phabricator:20121209.pholioxactions.sql',1443545054),('phabricator:20121209.xmacroadd.sql',1443545054),('phabricator:20121209.xmacromigrate.php',1443545054),('phabricator:20121209.xmacromigratekey.sql',1443545054),('phabricator:20121220.generalcache.sql',1443545054),('phabricator:20121226.config.sql',1443545054),('phabricator:20130101.confxaction.sql',1443545054),('phabricator:20130102.metamtareceivedmailmessageidhash.sql',1443545054),('phabricator:20130103.filemetadata.sql',1443545054),('phabricator:20130111.conpherence.sql',1443545054),('phabricator:20130127.altheraldtranscript.sql',1443545054),('phabricator:20130131.conpherencepics.sql',1443545054),('phabricator:20130201.revisionunsubscribed.php',1443545054),('phabricator:20130201.revisionunsubscribed.sql',1443545054),('phabricator:20130214.chatlogchannel.sql',1443545054),('phabricator:20130214.chatlogchannelid.sql',1443545054),('phabricator:20130214.token.sql',1443545054),('phabricator:20130215.phabricatorfileaddttl.sql',1443545054),('phabricator:20130217.cachettl.sql',1443545054),('phabricator:20130218.longdaemon.sql',1443545054),('phabricator:20130218.updatechannelid.php',1443545054),('phabricator:20130219.commitsummary.sql',1443545054),('phabricator:20130219.commitsummarymig.php',1443545054),('phabricator:20130222.dropchannel.sql',1443545054),('phabricator:20130226.commitkey.sql',1443545054),('phabricator:20130304.lintauthor.sql',1443545054),('phabricator:20130310.xactionmeta.sql',1443545055),('phabricator:20130317.phrictionedge.sql',1443545055),('phabricator:20130319.conpherence.sql',1443545054),('phabricator:20130319.phabricatorfileexplicitupload.sql',1443545054),('phabricator:20130320.phlux.sql',1443545055),('phabricator:20130321.token.sql',1443545055),('phabricator:20130322.phortune.sql',1443545055),('phabricator:20130323.phortunepayment.sql',1443545055),('phabricator:20130324.phortuneproduct.sql',1443545055),('phabricator:20130330.phrequent.sql',1443545055),('phabricator:20130403.conpherencecache.sql',1443545055),('phabricator:20130403.conpherencecachemig.php',1443545055),('phabricator:20130409.commitdrev.php',1443545055),('phabricator:20130417.externalaccount.sql',1443545055),('phabricator:20130423.conpherenceindices.sql',1443545055),('phabricator:20130423.phortunepaymentrevised.sql',1443545055),('phabricator:20130423.updateexternalaccount.sql',1443545055),('phabricator:20130426.search_savedquery.sql',1443545055),('phabricator:20130502.countdownrevamp1.sql',1443545055),('phabricator:20130502.countdownrevamp2.php',1443545055),('phabricator:20130502.countdownrevamp3.sql',1443545055),('phabricator:20130507.releephrqmailkey.sql',1443545055),('phabricator:20130507.releephrqmailkeypop.php',1443545055),('phabricator:20130507.releephrqsimplifycols.sql',1443545055),('phabricator:20130508.releephtransactions.sql',1443545055),('phabricator:20130508.releephtransactionsmig.php',1443545055),('phabricator:20130508.search_namedquery.sql',1443545055),('phabricator:20130513.receviedmailstatus.sql',1443545055),('phabricator:20130519.diviner.sql',1443545055),('phabricator:20130521.dropconphimages.sql',1443545055),('phabricator:20130523.maniphest_owners.sql',1443545055),('phabricator:20130524.repoxactions.sql',1443545055),('phabricator:20130529.macroauthor.sql',1443545055),('phabricator:20130529.macroauthormig.php',1443545055),('phabricator:20130530.macrodatekey.sql',1443545055),('phabricator:20130530.pastekeys.sql',1443545055),('phabricator:20130530.sessionhash.php',1443545055),('phabricator:20130531.filekeys.sql',1443545055),('phabricator:20130602.morediviner.sql',1443545055),('phabricator:20130602.namedqueries.sql',1443545055),('phabricator:20130606.userxactions.sql',1443545055),('phabricator:20130607.xaccount.sql',1443545055),('phabricator:20130611.migrateoauth.php',1443545055),('phabricator:20130611.nukeldap.php',1443545055),('phabricator:20130613.authdb.sql',1443545055),('phabricator:20130619.authconf.php',1443545055),('phabricator:20130620.diffxactions.sql',1443545055),('phabricator:20130621.diffcommentphid.sql',1443545055),('phabricator:20130621.diffcommentphidmig.php',1443545055),('phabricator:20130621.diffcommentunphid.sql',1443545056),('phabricator:20130622.doorkeeper.sql',1443545056),('phabricator:20130628.legalpadv0.sql',1443545056),('phabricator:20130701.conduitlog.sql',1443545056),('phabricator:20130703.legalpaddocdenorm.php',1443545056),('phabricator:20130703.legalpaddocdenorm.sql',1443545056),('phabricator:20130709.droptimeline.sql',1443545056),('phabricator:20130709.legalpadsignature.sql',1443545056),('phabricator:20130711.pholioimageobsolete.php',1443545056),('phabricator:20130711.pholioimageobsolete.sql',1443545056),('phabricator:20130711.pholioimageobsolete2.sql',1443545056),('phabricator:20130711.trimrealnames.php',1443545056),('phabricator:20130714.votexactions.sql',1443545056),('phabricator:20130715.votecomments.php',1443545056),('phabricator:20130715.voteedges.sql',1443545056),('phabricator:20130716.archivememberlessprojects.php',1443545056),('phabricator:20130722.pholioreplace.sql',1443545056),('phabricator:20130723.taskstarttime.sql',1443545056),('phabricator:20130726.ponderxactions.sql',1443545056),('phabricator:20130727.ponderquestionstatus.sql',1443545056),('phabricator:20130728.ponderunique.php',1443545056),('phabricator:20130728.ponderuniquekey.sql',1443545056),('phabricator:20130728.ponderxcomment.php',1443545056),('phabricator:20130731.releephcutpointidentifier.sql',1443545056),('phabricator:20130731.releephproject.sql',1443545056),('phabricator:20130731.releephrepoid.sql',1443545056),('phabricator:20130801.pastexactions.php',1443545056),('phabricator:20130801.pastexactions.sql',1443545056),('phabricator:20130802.heraldphid.sql',1443545056),('phabricator:20130802.heraldphids.php',1443545056),('phabricator:20130802.heraldphidukey.sql',1443545056),('phabricator:20130802.heraldxactions.sql',1443545056),('phabricator:20130805.pasteedges.sql',1443545056),('phabricator:20130805.pastemailkey.sql',1443545056),('phabricator:20130805.pastemailkeypop.php',1443545056),('phabricator:20130814.usercustom.sql',1443545056),('phabricator:20130820.file-mailkey-populate.php',1443545056),('phabricator:20130820.filemailkey.sql',1443545056),('phabricator:20130820.filexactions.sql',1443545056),('phabricator:20130820.releephxactions.sql',1443545056),('phabricator:20130826.divinernode.sql',1443545056),('phabricator:20130912.maniphest.1.touch.sql',1443545056),('phabricator:20130912.maniphest.2.created.sql',1443545056),('phabricator:20130912.maniphest.3.nameindex.sql',1443545056),('phabricator:20130912.maniphest.4.fillindex.php',1443545056),('phabricator:20130913.maniphest.1.migratesearch.php',1443545056),('phabricator:20130914.usercustom.sql',1443545056),('phabricator:20130915.maniphestcustom.sql',1443545056),('phabricator:20130915.maniphestmigrate.php',1443545056),('phabricator:20130915.maniphestqdrop.sql',1443545057),('phabricator:20130919.mfieldconf.php',1443545056),('phabricator:20130920.repokeyspolicy.sql',1443545056),('phabricator:20130921.mtransactions.sql',1443545056),('phabricator:20130921.xmigratemaniphest.php',1443545056),('phabricator:20130923.mrename.sql',1443545056),('phabricator:20130924.mdraftkey.sql',1443545056),('phabricator:20130925.mpolicy.sql',1443545056),('phabricator:20130925.xpolicy.sql',1443545057),('phabricator:20130926.dcustom.sql',1443545057),('phabricator:20130926.dinkeys.sql',1443545057),('phabricator:20130926.dinline.php',1443545057),('phabricator:20130927.audiomacro.sql',1443545057),('phabricator:20130929.filepolicy.sql',1443545057),('phabricator:20131004.dxedgekey.sql',1443545057),('phabricator:20131004.dxreviewers.php',1443545057),('phabricator:20131006.hdisable.sql',1443545057),('phabricator:20131010.pstorage.sql',1443545057),('phabricator:20131015.cpolicy.sql',1443545057),('phabricator:20131020.col1.sql',1443545057),('phabricator:20131020.harbormaster.sql',1443545057),('phabricator:20131020.pcustom.sql',1443545057),('phabricator:20131020.pxaction.sql',1443545057),('phabricator:20131020.pxactionmig.php',1443545057),('phabricator:20131025.repopush.sql',1443545057),('phabricator:20131026.commitstatus.sql',1443545057),('phabricator:20131030.repostatusmessage.sql',1443545057),('phabricator:20131031.vcspassword.sql',1443545057),('phabricator:20131105.buildstep.sql',1443545057),('phabricator:20131106.diffphid.1.col.sql',1443545057),('phabricator:20131106.diffphid.2.mig.php',1443545057),('phabricator:20131106.diffphid.3.key.sql',1443545057),('phabricator:20131106.nuance-v0.sql',1443545057),('phabricator:20131107.buildlog.sql',1443545057),('phabricator:20131112.userverified.1.col.sql',1443545057),('phabricator:20131112.userverified.2.mig.php',1443545057),('phabricator:20131118.ownerorder.php',1443545057),('phabricator:20131119.passphrase.sql',1443545057),('phabricator:20131120.nuancesourcetype.sql',1443545057),('phabricator:20131121.passphraseedge.sql',1443545057),('phabricator:20131121.repocredentials.1.col.sql',1443545057),('phabricator:20131121.repocredentials.2.mig.php',1443545057),('phabricator:20131122.repomirror.sql',1443545057),('phabricator:20131123.drydockblueprintpolicy.sql',1443545057),('phabricator:20131129.drydockresourceblueprint.sql',1443545057),('phabricator:20131204.pushlog.sql',1443545057),('phabricator:20131205.buildsteporder.sql',1443545058),('phabricator:20131205.buildstepordermig.php',1443545058),('phabricator:20131205.buildtargets.sql',1443545057),('phabricator:20131206.phragment.sql',1443545058),('phabricator:20131206.phragmentnull.sql',1443545058),('phabricator:20131208.phragmentsnapshot.sql',1443545058),('phabricator:20131211.phragmentedges.sql',1443545058),('phabricator:20131217.pushlogphid.1.col.sql',1443545058),('phabricator:20131217.pushlogphid.2.mig.php',1443545058),('phabricator:20131217.pushlogphid.3.key.sql',1443545058),('phabricator:20131219.pxdrop.sql',1443545058),('phabricator:20131224.harbormanual.sql',1443545058),('phabricator:20131227.heraldobject.sql',1443545058),('phabricator:20131231.dropshortcut.sql',1443545058),('phabricator:20131302.maniphestvalue.sql',1443545054),('phabricator:20140104.harbormastercmd.sql',1443545058),('phabricator:20140106.macromailkey.1.sql',1443545058),('phabricator:20140106.macromailkey.2.php',1443545058),('phabricator:20140108.ddbpname.1.sql',1443545058),('phabricator:20140108.ddbpname.2.php',1443545058),('phabricator:20140109.ddxactions.sql',1443545058),('phabricator:20140109.projectcolumnsdates.sql',1443545058),('phabricator:20140113.legalpadsig.1.sql',1443545058),('phabricator:20140113.legalpadsig.2.php',1443545058),('phabricator:20140115.auth.1.id.sql',1443545058),('phabricator:20140115.auth.2.expires.sql',1443545058),('phabricator:20140115.auth.3.unlimit.php',1443545058),('phabricator:20140115.legalpadsigkey.sql',1443545058),('phabricator:20140116.reporefcursor.sql',1443545058),('phabricator:20140126.diff.1.parentrevisionid.sql',1443545058),('phabricator:20140126.diff.2.repositoryphid.sql',1443545058),('phabricator:20140130.dash.1.board.sql',1443545058),('phabricator:20140130.dash.2.panel.sql',1443545058),('phabricator:20140130.dash.3.boardxaction.sql',1443545058),('phabricator:20140130.dash.4.panelxaction.sql',1443545058),('phabricator:20140130.mail.1.retry.sql',1443545058),('phabricator:20140130.mail.2.next.sql',1443545058),('phabricator:20140201.gc.1.mailsent.sql',1443545058),('phabricator:20140201.gc.2.mailreceived.sql',1443545058),('phabricator:20140205.cal.1.rename.sql',1443545058),('phabricator:20140205.cal.2.phid-col.sql',1443545058),('phabricator:20140205.cal.3.phid-mig.php',1443545058),('phabricator:20140205.cal.4.phid-key.sql',1443545058),('phabricator:20140210.herald.rule-condition-mig.php',1443545058),('phabricator:20140210.projcfield.1.blurb.php',1443545058),('phabricator:20140210.projcfield.2.piccol.sql',1443545058),('phabricator:20140210.projcfield.3.picmig.sql',1443545058),('phabricator:20140210.projcfield.4.memmig.sql',1443545058),('phabricator:20140210.projcfield.5.dropprofile.sql',1443545058),('phabricator:20140211.dx.1.nullablechangesetid.sql',1443545058),('phabricator:20140211.dx.2.migcommenttext.php',1443545058),('phabricator:20140211.dx.3.migsubscriptions.sql',1443545058),('phabricator:20140211.dx.999.drop.relationships.sql',1443545058),('phabricator:20140212.dx.1.armageddon.php',1443545058),('phabricator:20140214.clean.1.legacycommentid.sql',1443545058),('phabricator:20140214.clean.2.dropcomment.sql',1443545058),('phabricator:20140214.clean.3.dropinline.sql',1443545058),('phabricator:20140218.differentialdraft.sql',1443545058),('phabricator:20140218.passwords.1.extend.sql',1443545058),('phabricator:20140218.passwords.2.prefix.sql',1443545058),('phabricator:20140218.passwords.3.vcsextend.sql',1443545058),('phabricator:20140218.passwords.4.vcs.php',1443545058),('phabricator:20140223.bigutf8scratch.sql',1443545058),('phabricator:20140224.dxclean.1.datecommitted.sql',1443545058),('phabricator:20140226.dxcustom.1.fielddata.php',1443545058),('phabricator:20140226.dxcustom.99.drop.sql',1443545058),('phabricator:20140228.dxcomment.1.sql',1443545058),('phabricator:20140305.diviner.1.slugcol.sql',1443545058),('phabricator:20140305.diviner.2.slugkey.sql',1443545058),('phabricator:20140311.mdroplegacy.sql',1443545058),('phabricator:20140314.projectcolumn.1.statuscol.sql',1443545058),('phabricator:20140314.projectcolumn.2.statuskey.sql',1443545058),('phabricator:20140317.mupdatedkey.sql',1443545058),('phabricator:20140321.harbor.1.bxaction.sql',1443545058),('phabricator:20140321.mstatus.1.col.sql',1443545058),('phabricator:20140321.mstatus.2.mig.php',1443545058),('phabricator:20140323.harbor.1.renames.php',1443545058),('phabricator:20140323.harbor.2.message.sql',1443545058),('phabricator:20140325.push.1.event.sql',1443545058),('phabricator:20140325.push.2.eventphid.sql',1443545059),('phabricator:20140325.push.3.groups.php',1443545059),('phabricator:20140325.push.4.prune.sql',1443545059),('phabricator:20140326.project.1.colxaction.sql',1443545059),('phabricator:20140328.releeph.1.productxaction.sql',1443545059),('phabricator:20140330.flagtext.sql',1443545059),('phabricator:20140402.actionlog.sql',1443545059),('phabricator:20140410.accountsecret.1.sql',1443545059),('phabricator:20140410.accountsecret.2.php',1443545059),('phabricator:20140416.harbor.1.sql',1443545059),('phabricator:20140420.rel.1.objectphid.sql',1443545059),('phabricator:20140420.rel.2.objectmig.php',1443545059),('phabricator:20140421.slowvotecolumnsisclosed.sql',1443545059),('phabricator:20140423.session.1.hisec.sql',1443545059),('phabricator:20140427.mfactor.1.sql',1443545059),('phabricator:20140430.auth.1.partial.sql',1443545059),('phabricator:20140430.dash.1.paneltype.sql',1443545059),('phabricator:20140430.dash.2.edge.sql',1443545059),('phabricator:20140501.passphraselockcredential.sql',1443545059),('phabricator:20140501.remove.1.dlog.sql',1443545059),('phabricator:20140507.smstable.sql',1443545059),('phabricator:20140509.coverage.1.sql',1443545059),('phabricator:20140509.dashboardlayoutconfig.sql',1443545059),('phabricator:20140512.dparents.1.sql',1443545059),('phabricator:20140514.harbormasterbuildabletransaction.sql',1443545059),('phabricator:20140514.pholiomockclose.sql',1443545059),('phabricator:20140515.trust-emails.sql',1443545059),('phabricator:20140517.dxbinarycache.sql',1443545059),('phabricator:20140518.dxmorebinarycache.sql',1443545059),('phabricator:20140519.dashboardinstall.sql',1443545059),('phabricator:20140520.authtemptoken.sql',1443545059),('phabricator:20140521.projectslug.1.create.sql',1443545059),('phabricator:20140521.projectslug.2.mig.php',1443545059),('phabricator:20140522.projecticon.sql',1443545059),('phabricator:20140524.auth.mfa.cache.sql',1443545059),('phabricator:20140525.hunkmodern.sql',1443545059),('phabricator:20140615.pholioedit.1.sql',1443545059),('phabricator:20140615.pholioedit.2.sql',1443545059),('phabricator:20140617.daemon.explicit-argv.sql',1443545059),('phabricator:20140617.daemonlog.sql',1443545059),('phabricator:20140624.projcolor.1.sql',1443545059),('phabricator:20140624.projcolor.2.sql',1443545059),('phabricator:20140629.dasharchive.1.sql',1443545059),('phabricator:20140629.legalsig.1.sql',1443545059),('phabricator:20140629.legalsig.2.php',1443545059),('phabricator:20140701.legalexemption.1.sql',1443545059),('phabricator:20140701.legalexemption.2.sql',1443545059),('phabricator:20140703.legalcorp.1.sql',1443545059),('phabricator:20140703.legalcorp.2.sql',1443545059),('phabricator:20140703.legalcorp.3.sql',1443545059),('phabricator:20140703.legalcorp.4.sql',1443545059),('phabricator:20140703.legalcorp.5.sql',1443545059),('phabricator:20140704.harbormasterstep.1.sql',1443545059),('phabricator:20140704.harbormasterstep.2.sql',1443545059),('phabricator:20140704.legalpreamble.1.sql',1443545059),('phabricator:20140706.harbormasterdepend.1.php',1443545059),('phabricator:20140706.pedge.1.sql',1443545059),('phabricator:20140711.pnames.1.sql',1443545059),('phabricator:20140711.pnames.2.php',1443545059),('phabricator:20140711.workerpriority.sql',1443545059),('phabricator:20140712.projcoluniq.sql',1443545059),('phabricator:20140721.phortune.1.cart.sql',1443545059),('phabricator:20140721.phortune.2.purchase.sql',1443545059),('phabricator:20140721.phortune.3.charge.sql',1443545059),('phabricator:20140721.phortune.4.cartstatus.sql',1443545059),('phabricator:20140721.phortune.5.cstatusdefault.sql',1443545059),('phabricator:20140721.phortune.6.onetimecharge.sql',1443545060),('phabricator:20140721.phortune.7.nullmethod.sql',1443545060),('phabricator:20140722.appname.php',1443545060),('phabricator:20140722.audit.1.xactions.sql',1443545060),('phabricator:20140722.audit.2.comments.sql',1443545060),('phabricator:20140722.audit.3.miginlines.php',1443545060),('phabricator:20140722.audit.4.migtext.php',1443545060),('phabricator:20140722.renameauth.php',1443545060),('phabricator:20140723.apprenamexaction.sql',1443545060),('phabricator:20140725.audit.1.migxactions.php',1443545060),('phabricator:20140731.audit.1.subscribers.php',1443545060),('phabricator:20140731.cancdn.php',1443545060),('phabricator:20140731.harbormasterstepdesc.sql',1443545060),('phabricator:20140805.boardcol.1.sql',1443545060),('phabricator:20140805.boardcol.2.php',1443545060),('phabricator:20140807.harbormastertargettime.sql',1443545060),('phabricator:20140808.boardprop.1.sql',1443545060),('phabricator:20140808.boardprop.2.sql',1443545060),('phabricator:20140808.boardprop.3.php',1443545060),('phabricator:20140811.blob.1.sql',1443545060),('phabricator:20140811.blob.2.sql',1443545060),('phabricator:20140812.projkey.1.sql',1443545060),('phabricator:20140812.projkey.2.sql',1443545060),('phabricator:20140814.passphrasecredentialconduit.sql',1443545060),('phabricator:20140815.cancdncase.php',1443545060),('phabricator:20140818.harbormasterindex.1.sql',1443545060),('phabricator:20140821.harbormasterbuildgen.1.sql',1443545060),('phabricator:20140822.daemonenvhash.sql',1443545060),('phabricator:20140902.almanacdevice.1.sql',1443545060),('phabricator:20140904.macroattach.php',1443545060),('phabricator:20140911.fund.1.initiative.sql',1443545060),('phabricator:20140911.fund.2.xaction.sql',1443545060),('phabricator:20140911.fund.3.edge.sql',1443545060),('phabricator:20140911.fund.4.backer.sql',1443545060),('phabricator:20140911.fund.5.backxaction.sql',1443545060),('phabricator:20140914.betaproto.php',1443545060),('phabricator:20140917.project.canlock.sql',1443545060),('phabricator:20140918.schema.1.dropaudit.sql',1443545060),('phabricator:20140918.schema.2.dropauditinline.sql',1443545060),('phabricator:20140918.schema.3.wipecache.sql',1443545060),('phabricator:20140918.schema.4.cachetype.sql',1443545060),('phabricator:20140918.schema.5.slowvote.sql',1443545060),('phabricator:20140919.schema.01.calstatus.sql',1443545060),('phabricator:20140919.schema.02.calname.sql',1443545060),('phabricator:20140919.schema.03.dropaux.sql',1443545060),('phabricator:20140919.schema.04.droptaskproj.sql',1443545060),('phabricator:20140926.schema.01.droprelev.sql',1443545060),('phabricator:20140926.schema.02.droprelreqev.sql',1443545060),('phabricator:20140926.schema.03.dropldapinfo.sql',1443545060),('phabricator:20140926.schema.04.dropoauthinfo.sql',1443545060),('phabricator:20140926.schema.05.dropprojaffil.sql',1443545060),('phabricator:20140926.schema.06.dropsubproject.sql',1443545060),('phabricator:20140926.schema.07.droppondcom.sql',1443545060),('phabricator:20140927.schema.01.dropsearchq.sql',1443545060),('phabricator:20140927.schema.02.pholio1.sql',1443545060),('phabricator:20140927.schema.03.pholio2.sql',1443545060),('phabricator:20140927.schema.04.pholio3.sql',1443545060),('phabricator:20140927.schema.05.phragment1.sql',1443545060),('phabricator:20140927.schema.06.releeph1.sql',1443545060),('phabricator:20141001.schema.01.version.sql',1443545060),('phabricator:20141001.schema.02.taskmail.sql',1443545060),('phabricator:20141002.schema.01.liskcounter.sql',1443545060),('phabricator:20141002.schema.02.draftnull.sql',1443545060),('phabricator:20141004.currency.01.sql',1443545060),('phabricator:20141004.currency.02.sql',1443545060),('phabricator:20141004.currency.03.sql',1443545060),('phabricator:20141004.currency.04.sql',1443545060),('phabricator:20141004.currency.05.sql',1443545060),('phabricator:20141004.currency.06.sql',1443545060),('phabricator:20141004.harborliskcounter.sql',1443545060),('phabricator:20141005.phortuneproduct.sql',1443545060),('phabricator:20141006.phortunecart.sql',1443545060),('phabricator:20141006.phortunemerchant.sql',1443545060),('phabricator:20141006.phortunemerchantx.sql',1443545060),('phabricator:20141007.fundmerchant.sql',1443545060),('phabricator:20141007.fundrisks.sql',1443545060),('phabricator:20141007.fundtotal.sql',1443545060),('phabricator:20141007.phortunecartmerchant.sql',1443545060),('phabricator:20141007.phortunecharge.sql',1443545061),('phabricator:20141007.phortunepayment.sql',1443545061),('phabricator:20141007.phortuneprovider.sql',1443545061),('phabricator:20141007.phortuneproviderx.sql',1443545061),('phabricator:20141008.phortunemerchdesc.sql',1443545061),('phabricator:20141008.phortuneprovdis.sql',1443545061),('phabricator:20141008.phortunerefund.sql',1443545061),('phabricator:20141010.fundmailkey.sql',1443545061),('phabricator:20141011.phortunemerchedit.sql',1443545061),('phabricator:20141012.phortunecartxaction.sql',1443545061),('phabricator:20141013.phortunecartkey.sql',1443545061),('phabricator:20141016.almanac.device.sql',1443545061),('phabricator:20141016.almanac.dxaction.sql',1443545061),('phabricator:20141016.almanac.interface.sql',1443545061),('phabricator:20141016.almanac.network.sql',1443545061),('phabricator:20141016.almanac.nxaction.sql',1443545061),('phabricator:20141016.almanac.service.sql',1443545061),('phabricator:20141016.almanac.sxaction.sql',1443545061),('phabricator:20141017.almanac.binding.sql',1443545061),('phabricator:20141017.almanac.bxaction.sql',1443545061),('phabricator:20141025.phriction.1.xaction.sql',1443545061),('phabricator:20141025.phriction.2.xaction.sql',1443545061),('phabricator:20141025.phriction.mailkey.sql',1443545061),('phabricator:20141103.almanac.1.delprop.sql',1443545061),('phabricator:20141103.almanac.2.addprop.sql',1443545061),('phabricator:20141104.almanac.3.edge.sql',1443545061),('phabricator:20141105.ssh.1.rename.sql',1443545061),('phabricator:20141106.dropold.sql',1443545061),('phabricator:20141106.uniqdrafts.php',1443545061),('phabricator:20141107.phriction.policy.1.sql',1443545061),('phabricator:20141107.phriction.policy.2.php',1443545061),('phabricator:20141107.phriction.popkeys.php',1443545061),('phabricator:20141107.ssh.1.colname.sql',1443545061),('phabricator:20141107.ssh.2.keyhash.sql',1443545061),('phabricator:20141107.ssh.3.keyindex.sql',1443545061),('phabricator:20141107.ssh.4.keymig.php',1443545061),('phabricator:20141107.ssh.5.indexnull.sql',1443545061),('phabricator:20141107.ssh.6.indexkey.sql',1443545061),('phabricator:20141107.ssh.7.colnull.sql',1443545061),('phabricator:20141113.auditdupes.php',1443545061),('phabricator:20141118.diffxaction.sql',1443545061),('phabricator:20141119.commitpedge.sql',1443545061),('phabricator:20141119.differential.diff.policy.sql',1443545061),('phabricator:20141119.sshtrust.sql',1443545061),('phabricator:20141123.taskpriority.1.sql',1443545061),('phabricator:20141123.taskpriority.2.sql',1443545061),('phabricator:20141210.maniphestsubscribersmig.1.sql',1443545061),('phabricator:20141210.maniphestsubscribersmig.2.sql',1443545061),('phabricator:20141210.reposervice.sql',1443545061),('phabricator:20141212.conduittoken.sql',1443545061),('phabricator:20141215.almanacservicetype.sql',1443545061),('phabricator:20141217.almanacdevicelock.sql',1443545061),('phabricator:20141217.almanaclock.sql',1443545061),('phabricator:20141218.maniphestcctxn.php',1443545061),('phabricator:20141222.maniphestprojtxn.php',1443545061),('phabricator:20141223.daemonloguser.sql',1443545061),('phabricator:20141223.daemonobjectphid.sql',1443545061),('phabricator:20141230.pasteeditpolicycolumn.sql',1443545061),('phabricator:20141230.pasteeditpolicyexisting.sql',1443545061),('phabricator:20150102.policyname.php',1443545061),('phabricator:20150102.tasksubscriber.sql',1443545061),('phabricator:20150105.conpsearch.sql',1443545061),('phabricator:20150114.oauthserver.client.policy.sql',1443545062),('phabricator:20150115.applicationemails.sql',1443545062),('phabricator:20150115.trigger.1.sql',1443545062),('phabricator:20150115.trigger.2.sql',1443545062),('phabricator:20150116.maniphestapplicationemails.php',1443545062),('phabricator:20150120.maniphestdefaultauthor.php',1443545062),('phabricator:20150124.subs.1.sql',1443545062),('phabricator:20150129.pastefileapplicationemails.php',1443545062),('phabricator:20150130.phortune.1.subphid.sql',1443545062),('phabricator:20150130.phortune.2.subkey.sql',1443545062),('phabricator:20150131.phortune.1.defaultpayment.sql',1443545062),('phabricator:20150205.authprovider.autologin.sql',1443545062),('phabricator:20150205.daemonenv.sql',1443545062),('phabricator:20150209.invite.sql',1443545062),('phabricator:20150209.oauthclient.trust.sql',1443545062),('phabricator:20150210.invitephid.sql',1443545062),('phabricator:20150212.legalpad.session.1.sql',1443545062),('phabricator:20150212.legalpad.session.2.sql',1443545062),('phabricator:20150219.scratch.nonmutable.sql',1443545062),('phabricator:20150223.daemon.1.id.sql',1443545062),('phabricator:20150223.daemon.2.idlegacy.sql',1443545062),('phabricator:20150223.daemon.3.idkey.sql',1443545062),('phabricator:20150312.filechunk.1.sql',1443545062),('phabricator:20150312.filechunk.2.sql',1443545062),('phabricator:20150312.filechunk.3.sql',1443545062),('phabricator:20150317.conpherence.isroom.1.sql',1443545062),('phabricator:20150317.conpherence.isroom.2.sql',1443545062),('phabricator:20150317.conpherence.policy.sql',1443545062),('phabricator:20150410.nukeruleedit.sql',1443545062),('phabricator:20150420.invoice.1.sql',1443545062),('phabricator:20150420.invoice.2.sql',1443545062),('phabricator:20150425.isclosed.sql',1443545062),('phabricator:20150427.calendar.1.edge.sql',1443545062),('phabricator:20150427.calendar.1.xaction.sql',1443545062),('phabricator:20150427.calendar.2.xaction.sql',1443545062),('phabricator:20150428.calendar.1.iscancelled.sql',1443545062),('phabricator:20150428.calendar.1.name.sql',1443545062),('phabricator:20150429.calendar.1.invitee.sql',1443545062),('phabricator:20150430.calendar.1.policies.sql',1443545062),('phabricator:20150430.multimeter.1.sql',1443545062),('phabricator:20150430.multimeter.2.host.sql',1443545062),('phabricator:20150430.multimeter.3.viewer.sql',1443545062),('phabricator:20150430.multimeter.4.context.sql',1443545062),('phabricator:20150430.multimeter.5.label.sql',1443545062),('phabricator:20150501.calendar.1.reply.sql',1443545062),('phabricator:20150501.calendar.2.reply.php',1443545062),('phabricator:20150501.conpherencepics.sql',1443545062),('phabricator:20150503.repositorysymbols.1.sql',1443545062),('phabricator:20150503.repositorysymbols.2.php',1443545062),('phabricator:20150503.repositorysymbols.3.sql',1443545062),('phabricator:20150504.symbolsproject.1.php',1443545062),('phabricator:20150504.symbolsproject.2.sql',1443545062),('phabricator:20150506.calendarunnamedevents.1.php',1443545062),('phabricator:20150507.calendar.1.isallday.sql',1443545062),('phabricator:20150513.user.cache.1.sql',1443545062),('phabricator:20150514.calendar.status.sql',1443545062),('phabricator:20150514.phame.blog.xaction.sql',1443545062),('phabricator:20150514.user.cache.2.sql',1443545062),('phabricator:20150515.phame.post.xaction.sql',1443545062),('phabricator:20150515.project.mailkey.1.sql',1443545062),('phabricator:20150515.project.mailkey.2.php',1443545062),('phabricator:20150519.calendar.calendaricon.sql',1443545062),('phabricator:20150521.releephrepository.sql',1443545062),('phabricator:20150525.diff.hidden.1.sql',1443545062),('phabricator:20150526.owners.mailkey.1.sql',1443545062),('phabricator:20150526.owners.mailkey.2.php',1443545062),('phabricator:20150526.owners.xaction.sql',1443545062),('phabricator:20150527.calendar.recurringevents.sql',1443545062),('phabricator:20150601.spaces.1.namespace.sql',1443545063),('phabricator:20150601.spaces.2.xaction.sql',1443545063),('phabricator:20150602.mlist.1.sql',1443545063),('phabricator:20150602.mlist.2.php',1443545063),('phabricator:20150604.spaces.1.sql',1443545063),('phabricator:20150605.diviner.edges.sql',1443545063),('phabricator:20150605.diviner.editPolicy.sql',1443545063),('phabricator:20150605.diviner.xaction.sql',1443545063),('phabricator:20150606.mlist.1.php',1443545063),('phabricator:20150609.inline.sql',1443545063),('phabricator:20150609.spaces.1.pholio.sql',1443545063),('phabricator:20150609.spaces.2.maniphest.sql',1443545063),('phabricator:20150610.spaces.1.desc.sql',1443545063),('phabricator:20150610.spaces.2.edge.sql',1443545063),('phabricator:20150610.spaces.3.archive.sql',1443545063),('phabricator:20150611.spaces.1.mailxaction.sql',1443545063),('phabricator:20150611.spaces.2.appmail.sql',1443545063),('phabricator:20150616.divinerrepository.sql',1443545063),('phabricator:20150617.harbor.1.lint.sql',1443545063),('phabricator:20150617.harbor.2.unit.sql',1443545063),('phabricator:20150618.harbor.1.planauto.sql',1443545063),('phabricator:20150618.harbor.2.stepauto.sql',1443545063),('phabricator:20150618.harbor.3.buildauto.sql',1443545063),('phabricator:20150619.conpherencerooms.1.sql',1443545063),('phabricator:20150619.conpherencerooms.2.sql',1443545063),('phabricator:20150619.conpherencerooms.3.sql',1443545063),('phabricator:20150621.phrase.1.sql',1443545063),('phabricator:20150621.phrase.2.sql',1443545063),('phabricator:20150622.bulk.1.job.sql',1443545063),('phabricator:20150622.bulk.2.task.sql',1443545063),('phabricator:20150622.bulk.3.xaction.sql',1443545063),('phabricator:20150622.bulk.4.edge.sql',1443545063),('phabricator:20150622.metamta.1.phid-col.sql',1443545063),('phabricator:20150622.metamta.2.phid-mig.php',1443545063),('phabricator:20150622.metamta.3.phid-key.sql',1443545063),('phabricator:20150622.metamta.4.actor-phid-col.sql',1443545063),('phabricator:20150622.metamta.5.actor-phid-mig.php',1443545063),('phabricator:20150622.metamta.6.actor-phid-key.sql',1443545063),('phabricator:20150624.spaces.1.repo.sql',1443545063),('phabricator:20150626.spaces.1.calendar.sql',1443545063),('phabricator:20150630.herald.1.sql',1443545063),('phabricator:20150630.herald.2.sql',1443545063),('phabricator:20150701.herald.1.sql',1443545063),('phabricator:20150701.herald.2.sql',1443545063),('phabricator:20150702.spaces.1.slowvote.sql',1443545063),('phabricator:20150706.herald.1.sql',1443545063),('phabricator:20150707.herald.1.sql',1443545063),('phabricator:20150708.arcanistproject.sql',1443545063),('phabricator:20150708.herald.1.sql',1443545063),('phabricator:20150708.herald.2.sql',1443545063),('phabricator:20150708.herald.3.sql',1443545063),('phabricator:20150712.badges.1.sql',1443545063),('phabricator:20150714.spaces.countdown.1.sql',1443545063),('phabricator:20150717.herald.1.sql',1443545063),('phabricator:20150719.countdown.1.sql',1443545063),('phabricator:20150719.countdown.2.sql',1443545063),('phabricator:20150719.countdown.3.sql',1443545063),('phabricator:20150721.phurl.1.url.sql',1443545063),('phabricator:20150721.phurl.2.xaction.sql',1443545063),('phabricator:20150721.phurl.3.xactioncomment.sql',1443545063),('phabricator:20150721.phurl.4.url.sql',1443545063),('phabricator:20150721.phurl.5.edge.sql',1443545063),('phabricator:20150721.phurl.6.alias.sql',1443545063),('phabricator:20150721.phurl.7.authorphid.sql',1443545063),('phabricator:20150722.dashboard.1.sql',1443545063),('phabricator:20150722.dashboard.2.sql',1443545063),('phabricator:20150723.countdown.1.sql',1443545063),('phabricator:20150724.badges.comments.1.sql',1443545063),('phabricator:20150724.countdown.comments.1.sql',1443545063),('phabricator:20150725.badges.mailkey.1.sql',1443545063),('phabricator:20150725.badges.mailkey.2.php',1443545063),('phabricator:20150725.badges.viewpolicy.3.sql',1443545063),('phabricator:20150725.countdown.mailkey.1.sql',1443545063),('phabricator:20150725.countdown.mailkey.2.php',1443545063),('phabricator:20150725.slowvote.mailkey.1.sql',1443545063),('phabricator:20150725.slowvote.mailkey.2.php',1443545063),('phabricator:20150727.heraldaction.1.sql',1443545063),('phabricator:20150730.herald.1.sql',1443545063),('phabricator:20150730.herald.2.sql',1443545063),('phabricator:20150730.herald.3.sql',1443545063),('phabricator:20150730.herald.4.sql',1443545063),('phabricator:20150730.herald.5.sql',1443545063),('phabricator:20150730.herald.6.sql',1443545063),('phabricator:20150730.herald.7.sql',1443545063),('phabricator:20150803.herald.1.sql',1443545063),('phabricator:20150803.herald.2.sql',1443545063),('phabricator:20150804.ponder.answer.mailkey.1.sql',1443545063),('phabricator:20150804.ponder.answer.mailkey.2.php',1443545063),('phabricator:20150804.ponder.question.1.sql',1443545064),('phabricator:20150804.ponder.question.2.sql',1443545064),('phabricator:20150804.ponder.question.3.sql',1443545064),('phabricator:20150804.ponder.spaces.4.sql',1443545064),('phabricator:20150805.paste.status.1.sql',1443545064),('phabricator:20150805.paste.status.2.sql',1443545064),('phabricator:20150806.ponder.answer.1.sql',1443545064),('phabricator:20150806.ponder.editpolicy.2.sql',1443545064),('phabricator:20150806.ponder.status.1.sql',1443545064),('phabricator:20150806.ponder.status.2.sql',1443545064),('phabricator:20150806.ponder.status.3.sql',1443545064),('phabricator:20150808.ponder.vote.1.sql',1443545064),('phabricator:20150808.ponder.vote.2.sql',1443545064),('phabricator:20150812.ponder.answer.1.sql',1443545064),('phabricator:20150812.ponder.answer.2.sql',1443545064),('phabricator:20150814.harbormater.artifact.phid.sql',1443545064),('phabricator:20150815.owners.status.1.sql',1443545064),('phabricator:20150815.owners.status.2.sql',1443545064),('phabricator:20150823.nuance.queue.1.sql',1443545064),('phabricator:20150823.nuance.queue.2.sql',1443545064),('phabricator:20150823.nuance.queue.3.sql',1443545064),('phabricator:20150823.nuance.queue.4.sql',1443545064),('phabricator:20150828.ponder.wiki.1.sql',1443545064),('phabricator:20150829.ponder.dupe.1.sql',1443545064),('phabricator:20150904.herald.1.sql',1443545064),('phabricator:20150910.owners.custom.1.sql',1443545064),('phabricator:20150916.drydock.slotlocks.1.sql',1443545064),('phabricator:20150922.drydock.commands.1.sql',1443545064),('phabricator:20150923.drydock.resourceid.1.sql',1443545064),('phabricator:20150923.drydock.resourceid.2.sql',1443545064),('phabricator:20150923.drydock.resourceid.3.sql',1443545064),('phabricator:20150923.drydock.taskid.1.sql',1443545064),('phabricator:20150924.drydock.disable.1.sql',1443545064),('phabricator:20150924.drydock.status.1.sql',1443545064),('phabricator:20150928.drydock.rexpire.1.sql',1443545064),('phabricator:daemonstatus.sql',1443545053),('phabricator:daemonstatuskey.sql',1443545054),('phabricator:daemontaskarchive.sql',1443545054),('phabricator:db.almanac',1443545048),('phabricator:db.audit',1443545048),('phabricator:db.auth',1443545048),('phabricator:db.badges',1443545048),('phabricator:db.cache',1443545048),('phabricator:db.calendar',1443545048),('phabricator:db.chatlog',1443545048),('phabricator:db.conduit',1443545048),('phabricator:db.config',1443545048),('phabricator:db.conpherence',1443545048),('phabricator:db.countdown',1443545048),('phabricator:db.daemon',1443545048),('phabricator:db.dashboard',1443545048),('phabricator:db.differential',1443545048),('phabricator:db.diviner',1443545048),('phabricator:db.doorkeeper',1443545048),('phabricator:db.draft',1443545048),('phabricator:db.drydock',1443545048),('phabricator:db.fact',1443545048),('phabricator:db.feed',1443545048),('phabricator:db.file',1443545048),('phabricator:db.flag',1443545048),('phabricator:db.fund',1443545048),('phabricator:db.harbormaster',1443545048),('phabricator:db.herald',1443545048),('phabricator:db.legalpad',1443545048),('phabricator:db.maniphest',1443545048),('phabricator:db.meta_data',1443545048),('phabricator:db.metamta',1443545048),('phabricator:db.multimeter',1443545048),('phabricator:db.nuance',1443545048),('phabricator:db.oauth_server',1443545048),('phabricator:db.owners',1443545048),('phabricator:db.passphrase',1443545048),('phabricator:db.pastebin',1443545048),('phabricator:db.phame',1443545048),('phabricator:db.phlux',1443545048),('phabricator:db.pholio',1443545048),('phabricator:db.phortune',1443545048),('phabricator:db.phragment',1443545048),('phabricator:db.phrequent',1443545048),('phabricator:db.phriction',1443545048),('phabricator:db.phurl',1443545048),('phabricator:db.policy',1443545048),('phabricator:db.ponder',1443545048),('phabricator:db.project',1443545048),('phabricator:db.releeph',1443545048),('phabricator:db.repository',1443545048),('phabricator:db.search',1443545048),('phabricator:db.slowvote',1443545048),('phabricator:db.spaces',1443545048),('phabricator:db.system',1443545048),('phabricator:db.timeline',1443545048),('phabricator:db.token',1443545048),('phabricator:db.user',1443545048),('phabricator:db.worker',1443545048),('phabricator:db.xhpastview',1443545048),('phabricator:db.xhprof',1443545048),('phabricator:differentialbookmarks.sql',1443545053),('phabricator:draft-metadata.sql',1443545054),('phabricator:dropfileproxyimage.sql',1443545054),('phabricator:drydockresoucetype.sql',1443545054),('phabricator:drydocktaskid.sql',1443545054),('phabricator:edgetype.sql',1443545054),('phabricator:emailtable.sql',1443545053),('phabricator:emailtableport.sql',1443545053),('phabricator:emailtableremove.sql',1443545053),('phabricator:fact-raw.sql',1443545053),('phabricator:harbormasterobject.sql',1443545053),('phabricator:holidays.sql',1443545053),('phabricator:ldapinfo.sql',1443545053),('phabricator:legalpad-mailkey-populate.php',1443545056),('phabricator:legalpad-mailkey.sql',1443545056),('phabricator:liskcounters-task.sql',1443545054),('phabricator:liskcounters.php',1443545054),('phabricator:liskcounters.sql',1443545054),('phabricator:maniphestxcache.sql',1443545053),('phabricator:markupcache.sql',1443545053),('phabricator:migrate-differential-dependencies.php',1443545053),('phabricator:migrate-maniphest-dependencies.php',1443545053),('phabricator:migrate-maniphest-revisions.php',1443545053),('phabricator:migrate-project-edges.php',1443545053),('phabricator:owners-exclude.sql',1443545054),('phabricator:pastepolicy.sql',1443545054),('phabricator:phameblog.sql',1443545053),('phabricator:phamedomain.sql',1443545054),('phabricator:phameoneblog.sql',1443545054),('phabricator:phamepolicy.sql',1443545054),('phabricator:phiddrop.sql',1443545053),('phabricator:pholio.sql',1443545054),('phabricator:policy-project.sql',1443545054),('phabricator:ponder-comments.sql',1443545054),('phabricator:ponder-mailkey-populate.php',1443545054),('phabricator:ponder-mailkey.sql',1443545054),('phabricator:ponder.sql',1443545054),('phabricator:releeph.sql',1443545054),('phabricator:repository-lint.sql',1443545054),('phabricator:statustxt.sql',1443545054),('phabricator:symbolcontexts.sql',1443545053),('phabricator:testdatabase.sql',1443545053),('phabricator:threadtopic.sql',1443545053),('phabricator:userstatus.sql',1443545053),('phabricator:usertranslation.sql',1443545053),('phabricator:xhprof.sql',1443545054); +INSERT INTO `patch_status` VALUES ('phabricator:000.project.sql',1453226118,NULL),('phabricator:0000.legacy.sql',1453226118,NULL),('phabricator:001.maniphest_projects.sql',1453226118,NULL),('phabricator:002.oauth.sql',1453226118,NULL),('phabricator:003.more_oauth.sql',1453226118,NULL),('phabricator:004.daemonrepos.sql',1453226118,NULL),('phabricator:005.workers.sql',1453226118,NULL),('phabricator:006.repository.sql',1453226118,NULL),('phabricator:007.daemonlog.sql',1453226118,NULL),('phabricator:008.repoopt.sql',1453226118,NULL),('phabricator:009.repo_summary.sql',1453226118,NULL),('phabricator:010.herald.sql',1453226118,NULL),('phabricator:011.badcommit.sql',1453226118,NULL),('phabricator:012.dropphidtype.sql',1453226118,NULL),('phabricator:013.commitdetail.sql',1453226118,NULL),('phabricator:014.shortcuts.sql',1453226118,NULL),('phabricator:015.preferences.sql',1453226118,NULL),('phabricator:016.userrealnameindex.sql',1453226118,NULL),('phabricator:017.sessionkeys.sql',1453226118,NULL),('phabricator:018.owners.sql',1453226118,NULL),('phabricator:019.arcprojects.sql',1453226118,NULL),('phabricator:020.pathcapital.sql',1453226118,NULL),('phabricator:021.xhpastview.sql',1453226118,NULL),('phabricator:022.differentialcommit.sql',1453226118,NULL),('phabricator:023.dxkeys.sql',1453226118,NULL),('phabricator:024.mlistkeys.sql',1453226118,NULL),('phabricator:025.commentopt.sql',1453226118,NULL),('phabricator:026.diffpropkey.sql',1453226118,NULL),('phabricator:027.metamtakeys.sql',1453226118,NULL),('phabricator:028.systemagent.sql',1453226118,NULL),('phabricator:029.cursors.sql',1453226118,NULL),('phabricator:030.imagemacro.sql',1453226118,NULL),('phabricator:031.workerrace.sql',1453226118,NULL),('phabricator:032.viewtime.sql',1453226118,NULL),('phabricator:033.privtest.sql',1453226118,NULL),('phabricator:034.savedheader.sql',1453226118,NULL),('phabricator:035.proxyimage.sql',1453226118,NULL),('phabricator:036.mailkey.sql',1453226119,NULL),('phabricator:037.setuptest.sql',1453226119,NULL),('phabricator:038.admin.sql',1453226119,NULL),('phabricator:039.userlog.sql',1453226119,NULL),('phabricator:040.transform.sql',1453226119,NULL),('phabricator:041.heraldrepetition.sql',1453226119,NULL),('phabricator:042.commentmetadata.sql',1453226119,NULL),('phabricator:043.pastebin.sql',1453226119,NULL),('phabricator:044.countdown.sql',1453226119,NULL),('phabricator:045.timezone.sql',1453226119,NULL),('phabricator:046.conduittoken.sql',1453226119,NULL),('phabricator:047.projectstatus.sql',1453226119,NULL),('phabricator:048.relationshipkeys.sql',1453226119,NULL),('phabricator:049.projectowner.sql',1453226119,NULL),('phabricator:050.taskdenormal.sql',1453226119,NULL),('phabricator:051.projectfilter.sql',1453226119,NULL),('phabricator:052.pastelanguage.sql',1453226119,NULL),('phabricator:053.feed.sql',1453226119,NULL),('phabricator:054.subscribers.sql',1453226119,NULL),('phabricator:055.add_author_to_files.sql',1453226119,NULL),('phabricator:056.slowvote.sql',1453226119,NULL),('phabricator:057.parsecache.sql',1453226119,NULL),('phabricator:058.missingkeys.sql',1453226119,NULL),('phabricator:059.engines.php',1453226120,NULL),('phabricator:060.phriction.sql',1453226120,NULL),('phabricator:061.phrictioncontent.sql',1453226120,NULL),('phabricator:062.phrictionmenu.sql',1453226120,NULL),('phabricator:063.pasteforks.sql',1453226120,NULL),('phabricator:064.subprojects.sql',1453226120,NULL),('phabricator:065.sshkeys.sql',1453226120,NULL),('phabricator:066.phrictioncontent.sql',1453226120,NULL),('phabricator:067.preferences.sql',1453226120,NULL),('phabricator:068.maniphestauxiliarystorage.sql',1453226120,NULL),('phabricator:069.heraldxscript.sql',1453226120,NULL),('phabricator:070.differentialaux.sql',1453226120,NULL),('phabricator:071.contentsource.sql',1453226120,NULL),('phabricator:072.blamerevert.sql',1453226120,NULL),('phabricator:073.reposymbols.sql',1453226120,NULL),('phabricator:074.affectedpath.sql',1453226120,NULL),('phabricator:075.revisionhash.sql',1453226120,NULL),('phabricator:076.indexedlanguages.sql',1453226120,NULL),('phabricator:077.originalemail.sql',1453226120,NULL),('phabricator:078.nametoken.sql',1453226120,NULL),('phabricator:079.nametokenindex.php',1453226120,NULL),('phabricator:080.filekeys.sql',1453226120,NULL),('phabricator:081.filekeys.php',1453226120,NULL),('phabricator:082.xactionkey.sql',1453226120,NULL),('phabricator:083.dxviewtime.sql',1453226120,NULL),('phabricator:084.pasteauthorkey.sql',1453226120,NULL),('phabricator:085.packagecommitrelationship.sql',1453226120,NULL),('phabricator:086.formeraffil.sql',1453226120,NULL),('phabricator:087.phrictiondelete.sql',1453226120,NULL),('phabricator:088.audit.sql',1453226120,NULL),('phabricator:089.projectwiki.sql',1453226120,NULL),('phabricator:090.forceuniqueprojectnames.php',1453226120,NULL),('phabricator:091.uniqueslugkey.sql',1453226120,NULL),('phabricator:092.dropgithubnotification.sql',1453226120,NULL),('phabricator:093.gitremotes.php',1453226120,NULL),('phabricator:094.phrictioncolumn.sql',1453226120,NULL),('phabricator:095.directory.sql',1453226120,NULL),('phabricator:096.filename.sql',1453226120,NULL),('phabricator:097.heraldruletypes.sql',1453226120,NULL),('phabricator:098.heraldruletypemigration.php',1453226120,NULL),('phabricator:099.drydock.sql',1453226120,NULL),('phabricator:100.projectxaction.sql',1453226120,NULL),('phabricator:101.heraldruleapplied.sql',1453226120,NULL),('phabricator:102.heraldcleanup.php',1453226120,NULL),('phabricator:103.heraldedithistory.sql',1453226120,NULL),('phabricator:104.searchkey.sql',1453226120,NULL),('phabricator:105.mimetype.sql',1453226120,NULL),('phabricator:106.chatlog.sql',1453226120,NULL),('phabricator:107.oauthserver.sql',1453226120,NULL),('phabricator:108.oauthscope.sql',1453226120,NULL),('phabricator:109.oauthclientphidkey.sql',1453226120,NULL),('phabricator:110.commitaudit.sql',1453226121,NULL),('phabricator:111.commitauditmigration.php',1453226121,NULL),('phabricator:112.oauthaccesscoderedirecturi.sql',1453226121,NULL),('phabricator:113.lastreviewer.sql',1453226121,NULL),('phabricator:114.auditrequest.sql',1453226121,NULL),('phabricator:115.prepareutf8.sql',1453226121,NULL),('phabricator:116.utf8-backup-first-expect-wait.sql',1453226122,NULL),('phabricator:117.repositorydescription.php',1453226122,NULL),('phabricator:118.auditinline.sql',1453226122,NULL),('phabricator:119.filehash.sql',1453226123,NULL),('phabricator:120.noop.sql',1453226123,NULL),('phabricator:121.drydocklog.sql',1453226123,NULL),('phabricator:122.flag.sql',1453226123,NULL),('phabricator:123.heraldrulelog.sql',1453226123,NULL),('phabricator:124.subpriority.sql',1453226123,NULL),('phabricator:125.ipv6.sql',1453226123,NULL),('phabricator:126.edges.sql',1453226123,NULL),('phabricator:127.userkeybody.sql',1453226123,NULL),('phabricator:128.phabricatorcom.sql',1453226123,NULL),('phabricator:129.savedquery.sql',1453226123,NULL),('phabricator:130.denormalrevisionquery.sql',1453226123,NULL),('phabricator:131.migraterevisionquery.php',1453226123,NULL),('phabricator:132.phame.sql',1453226123,NULL),('phabricator:133.imagemacro.sql',1453226123,NULL),('phabricator:134.emptysearch.sql',1453226123,NULL),('phabricator:135.datecommitted.sql',1453226123,NULL),('phabricator:136.sex.sql',1453226123,NULL),('phabricator:137.auditmetadata.sql',1453226123,NULL),('phabricator:138.notification.sql',1453226123,NULL),('phabricator:20121209.pholioxactions.sql',1453226124,NULL),('phabricator:20121209.xmacroadd.sql',1453226124,NULL),('phabricator:20121209.xmacromigrate.php',1453226124,NULL),('phabricator:20121209.xmacromigratekey.sql',1453226124,NULL),('phabricator:20121220.generalcache.sql',1453226124,NULL),('phabricator:20121226.config.sql',1453226124,NULL),('phabricator:20130101.confxaction.sql',1453226124,NULL),('phabricator:20130102.metamtareceivedmailmessageidhash.sql',1453226124,NULL),('phabricator:20130103.filemetadata.sql',1453226124,NULL),('phabricator:20130111.conpherence.sql',1453226124,NULL),('phabricator:20130127.altheraldtranscript.sql',1453226124,NULL),('phabricator:20130131.conpherencepics.sql',1453226124,NULL),('phabricator:20130201.revisionunsubscribed.php',1453226124,NULL),('phabricator:20130201.revisionunsubscribed.sql',1453226124,NULL),('phabricator:20130214.chatlogchannel.sql',1453226124,NULL),('phabricator:20130214.chatlogchannelid.sql',1453226124,NULL),('phabricator:20130214.token.sql',1453226124,NULL),('phabricator:20130215.phabricatorfileaddttl.sql',1453226124,NULL),('phabricator:20130217.cachettl.sql',1453226124,NULL),('phabricator:20130218.longdaemon.sql',1453226124,NULL),('phabricator:20130218.updatechannelid.php',1453226124,NULL),('phabricator:20130219.commitsummary.sql',1453226124,NULL),('phabricator:20130219.commitsummarymig.php',1453226124,NULL),('phabricator:20130222.dropchannel.sql',1453226124,NULL),('phabricator:20130226.commitkey.sql',1453226124,NULL),('phabricator:20130304.lintauthor.sql',1453226124,NULL),('phabricator:20130310.xactionmeta.sql',1453226124,NULL),('phabricator:20130317.phrictionedge.sql',1453226124,NULL),('phabricator:20130319.conpherence.sql',1453226124,NULL),('phabricator:20130319.phabricatorfileexplicitupload.sql',1453226124,NULL),('phabricator:20130320.phlux.sql',1453226124,NULL),('phabricator:20130321.token.sql',1453226124,NULL),('phabricator:20130322.phortune.sql',1453226124,NULL),('phabricator:20130323.phortunepayment.sql',1453226124,NULL),('phabricator:20130324.phortuneproduct.sql',1453226124,NULL),('phabricator:20130330.phrequent.sql',1453226124,NULL),('phabricator:20130403.conpherencecache.sql',1453226124,NULL),('phabricator:20130403.conpherencecachemig.php',1453226124,NULL),('phabricator:20130409.commitdrev.php',1453226124,NULL),('phabricator:20130417.externalaccount.sql',1453226124,NULL),('phabricator:20130423.conpherenceindices.sql',1453226125,NULL),('phabricator:20130423.phortunepaymentrevised.sql',1453226125,NULL),('phabricator:20130423.updateexternalaccount.sql',1453226124,NULL),('phabricator:20130426.search_savedquery.sql',1453226125,NULL),('phabricator:20130502.countdownrevamp1.sql',1453226125,NULL),('phabricator:20130502.countdownrevamp2.php',1453226125,NULL),('phabricator:20130502.countdownrevamp3.sql',1453226125,NULL),('phabricator:20130507.releephrqmailkey.sql',1453226125,NULL),('phabricator:20130507.releephrqmailkeypop.php',1453226125,NULL),('phabricator:20130507.releephrqsimplifycols.sql',1453226125,NULL),('phabricator:20130508.releephtransactions.sql',1453226125,NULL),('phabricator:20130508.releephtransactionsmig.php',1453226125,NULL),('phabricator:20130508.search_namedquery.sql',1453226125,NULL),('phabricator:20130513.receviedmailstatus.sql',1453226125,NULL),('phabricator:20130519.diviner.sql',1453226125,NULL),('phabricator:20130521.dropconphimages.sql',1453226125,NULL),('phabricator:20130523.maniphest_owners.sql',1453226125,NULL),('phabricator:20130524.repoxactions.sql',1453226125,NULL),('phabricator:20130529.macroauthor.sql',1453226125,NULL),('phabricator:20130529.macroauthormig.php',1453226125,NULL),('phabricator:20130530.macrodatekey.sql',1453226125,NULL),('phabricator:20130530.pastekeys.sql',1453226125,NULL),('phabricator:20130530.sessionhash.php',1453226125,NULL),('phabricator:20130531.filekeys.sql',1453226125,NULL),('phabricator:20130602.morediviner.sql',1453226125,NULL),('phabricator:20130602.namedqueries.sql',1453226125,NULL),('phabricator:20130606.userxactions.sql',1453226125,NULL),('phabricator:20130607.xaccount.sql',1453226125,NULL),('phabricator:20130611.migrateoauth.php',1453226125,NULL),('phabricator:20130611.nukeldap.php',1453226125,NULL),('phabricator:20130613.authdb.sql',1453226125,NULL),('phabricator:20130619.authconf.php',1453226125,NULL),('phabricator:20130620.diffxactions.sql',1453226125,NULL),('phabricator:20130621.diffcommentphid.sql',1453226125,NULL),('phabricator:20130621.diffcommentphidmig.php',1453226125,NULL),('phabricator:20130621.diffcommentunphid.sql',1453226125,NULL),('phabricator:20130622.doorkeeper.sql',1453226125,NULL),('phabricator:20130628.legalpadv0.sql',1453226125,NULL),('phabricator:20130701.conduitlog.sql',1453226125,NULL),('phabricator:20130703.legalpaddocdenorm.php',1453226125,NULL),('phabricator:20130703.legalpaddocdenorm.sql',1453226125,NULL),('phabricator:20130709.droptimeline.sql',1453226125,NULL),('phabricator:20130709.legalpadsignature.sql',1453226125,NULL),('phabricator:20130711.pholioimageobsolete.php',1453226126,NULL),('phabricator:20130711.pholioimageobsolete.sql',1453226126,NULL),('phabricator:20130711.pholioimageobsolete2.sql',1453226126,NULL),('phabricator:20130711.trimrealnames.php',1453226125,NULL),('phabricator:20130714.votexactions.sql',1453226125,NULL),('phabricator:20130715.votecomments.php',1453226125,NULL),('phabricator:20130715.voteedges.sql',1453226125,NULL),('phabricator:20130716.archivememberlessprojects.php',1453226126,NULL),('phabricator:20130722.pholioreplace.sql',1453226126,NULL),('phabricator:20130723.taskstarttime.sql',1453226126,NULL),('phabricator:20130726.ponderxactions.sql',1453226126,NULL),('phabricator:20130727.ponderquestionstatus.sql',1453226126,NULL),('phabricator:20130728.ponderunique.php',1453226126,NULL),('phabricator:20130728.ponderuniquekey.sql',1453226126,NULL),('phabricator:20130728.ponderxcomment.php',1453226126,NULL),('phabricator:20130731.releephcutpointidentifier.sql',1453226126,NULL),('phabricator:20130731.releephproject.sql',1453226126,NULL),('phabricator:20130731.releephrepoid.sql',1453226126,NULL),('phabricator:20130801.pastexactions.php',1453226126,NULL),('phabricator:20130801.pastexactions.sql',1453226126,NULL),('phabricator:20130802.heraldphid.sql',1453226126,NULL),('phabricator:20130802.heraldphids.php',1453226126,NULL),('phabricator:20130802.heraldphidukey.sql',1453226126,NULL),('phabricator:20130802.heraldxactions.sql',1453226126,NULL),('phabricator:20130805.pasteedges.sql',1453226126,NULL),('phabricator:20130805.pastemailkey.sql',1453226126,NULL),('phabricator:20130805.pastemailkeypop.php',1453226126,NULL),('phabricator:20130814.usercustom.sql',1453226126,NULL),('phabricator:20130820.file-mailkey-populate.php',1453226126,NULL),('phabricator:20130820.filemailkey.sql',1453226126,NULL),('phabricator:20130820.filexactions.sql',1453226126,NULL),('phabricator:20130820.releephxactions.sql',1453226126,NULL),('phabricator:20130826.divinernode.sql',1453226126,NULL),('phabricator:20130912.maniphest.1.touch.sql',1453226126,NULL),('phabricator:20130912.maniphest.2.created.sql',1453226126,NULL),('phabricator:20130912.maniphest.3.nameindex.sql',1453226126,NULL),('phabricator:20130912.maniphest.4.fillindex.php',1453226126,NULL),('phabricator:20130913.maniphest.1.migratesearch.php',1453226126,NULL),('phabricator:20130914.usercustom.sql',1453226126,NULL),('phabricator:20130915.maniphestcustom.sql',1453226126,NULL),('phabricator:20130915.maniphestmigrate.php',1453226126,NULL),('phabricator:20130915.maniphestqdrop.sql',1453226126,NULL),('phabricator:20130919.mfieldconf.php',1453226126,NULL),('phabricator:20130920.repokeyspolicy.sql',1453226126,NULL),('phabricator:20130921.mtransactions.sql',1453226126,NULL),('phabricator:20130921.xmigratemaniphest.php',1453226126,NULL),('phabricator:20130923.mrename.sql',1453226126,NULL),('phabricator:20130924.mdraftkey.sql',1453226126,NULL),('phabricator:20130925.mpolicy.sql',1453226126,NULL),('phabricator:20130925.xpolicy.sql',1453226126,NULL),('phabricator:20130926.dcustom.sql',1453226126,NULL),('phabricator:20130926.dinkeys.sql',1453226126,NULL),('phabricator:20130926.dinline.php',1453226126,NULL),('phabricator:20130927.audiomacro.sql',1453226126,NULL),('phabricator:20130929.filepolicy.sql',1453226126,NULL),('phabricator:20131004.dxedgekey.sql',1453226126,NULL),('phabricator:20131004.dxreviewers.php',1453226126,NULL),('phabricator:20131006.hdisable.sql',1453226126,NULL),('phabricator:20131010.pstorage.sql',1453226126,NULL),('phabricator:20131015.cpolicy.sql',1453226126,NULL),('phabricator:20131020.col1.sql',1453226126,NULL),('phabricator:20131020.harbormaster.sql',1453226126,NULL),('phabricator:20131020.pcustom.sql',1453226126,NULL),('phabricator:20131020.pxaction.sql',1453226126,NULL),('phabricator:20131020.pxactionmig.php',1453226126,NULL),('phabricator:20131025.repopush.sql',1453226127,NULL),('phabricator:20131026.commitstatus.sql',1453226127,NULL),('phabricator:20131030.repostatusmessage.sql',1453226127,NULL),('phabricator:20131031.vcspassword.sql',1453226127,NULL),('phabricator:20131105.buildstep.sql',1453226127,NULL),('phabricator:20131106.diffphid.1.col.sql',1453226127,NULL),('phabricator:20131106.diffphid.2.mig.php',1453226127,NULL),('phabricator:20131106.diffphid.3.key.sql',1453226127,NULL),('phabricator:20131106.nuance-v0.sql',1453226127,NULL),('phabricator:20131107.buildlog.sql',1453226127,NULL),('phabricator:20131112.userverified.1.col.sql',1453226127,NULL),('phabricator:20131112.userverified.2.mig.php',1453226127,NULL),('phabricator:20131118.ownerorder.php',1453226127,NULL),('phabricator:20131119.passphrase.sql',1453226127,NULL),('phabricator:20131120.nuancesourcetype.sql',1453226127,NULL),('phabricator:20131121.passphraseedge.sql',1453226127,NULL),('phabricator:20131121.repocredentials.1.col.sql',1453226127,NULL),('phabricator:20131121.repocredentials.2.mig.php',1453226127,NULL),('phabricator:20131122.repomirror.sql',1453226127,NULL),('phabricator:20131123.drydockblueprintpolicy.sql',1453226127,NULL),('phabricator:20131129.drydockresourceblueprint.sql',1453226127,NULL),('phabricator:20131204.pushlog.sql',1453226127,NULL),('phabricator:20131205.buildsteporder.sql',1453226127,NULL),('phabricator:20131205.buildstepordermig.php',1453226127,NULL),('phabricator:20131205.buildtargets.sql',1453226127,NULL),('phabricator:20131206.phragment.sql',1453226127,NULL),('phabricator:20131206.phragmentnull.sql',1453226127,NULL),('phabricator:20131208.phragmentsnapshot.sql',1453226127,NULL),('phabricator:20131211.phragmentedges.sql',1453226127,NULL),('phabricator:20131217.pushlogphid.1.col.sql',1453226127,NULL),('phabricator:20131217.pushlogphid.2.mig.php',1453226127,NULL),('phabricator:20131217.pushlogphid.3.key.sql',1453226127,NULL),('phabricator:20131219.pxdrop.sql',1453226127,NULL),('phabricator:20131224.harbormanual.sql',1453226127,NULL),('phabricator:20131227.heraldobject.sql',1453226127,NULL),('phabricator:20131231.dropshortcut.sql',1453226127,NULL),('phabricator:20131302.maniphestvalue.sql',1453226124,NULL),('phabricator:20140104.harbormastercmd.sql',1453226127,NULL),('phabricator:20140106.macromailkey.1.sql',1453226127,NULL),('phabricator:20140106.macromailkey.2.php',1453226127,NULL),('phabricator:20140108.ddbpname.1.sql',1453226127,NULL),('phabricator:20140108.ddbpname.2.php',1453226127,NULL),('phabricator:20140109.ddxactions.sql',1453226127,NULL),('phabricator:20140109.projectcolumnsdates.sql',1453226127,NULL),('phabricator:20140113.legalpadsig.1.sql',1453226127,NULL),('phabricator:20140113.legalpadsig.2.php',1453226127,NULL),('phabricator:20140115.auth.1.id.sql',1453226128,NULL),('phabricator:20140115.auth.2.expires.sql',1453226128,NULL),('phabricator:20140115.auth.3.unlimit.php',1453226128,NULL),('phabricator:20140115.legalpadsigkey.sql',1453226128,NULL),('phabricator:20140116.reporefcursor.sql',1453226128,NULL),('phabricator:20140126.diff.1.parentrevisionid.sql',1453226128,NULL),('phabricator:20140126.diff.2.repositoryphid.sql',1453226128,NULL),('phabricator:20140130.dash.1.board.sql',1453226128,NULL),('phabricator:20140130.dash.2.panel.sql',1453226128,NULL),('phabricator:20140130.dash.3.boardxaction.sql',1453226128,NULL),('phabricator:20140130.dash.4.panelxaction.sql',1453226128,NULL),('phabricator:20140130.mail.1.retry.sql',1453226128,NULL),('phabricator:20140130.mail.2.next.sql',1453226128,NULL),('phabricator:20140201.gc.1.mailsent.sql',1453226128,NULL),('phabricator:20140201.gc.2.mailreceived.sql',1453226128,NULL),('phabricator:20140205.cal.1.rename.sql',1453226128,NULL),('phabricator:20140205.cal.2.phid-col.sql',1453226128,NULL),('phabricator:20140205.cal.3.phid-mig.php',1453226128,NULL),('phabricator:20140205.cal.4.phid-key.sql',1453226128,NULL),('phabricator:20140210.herald.rule-condition-mig.php',1453226128,NULL),('phabricator:20140210.projcfield.1.blurb.php',1453226128,NULL),('phabricator:20140210.projcfield.2.piccol.sql',1453226128,NULL),('phabricator:20140210.projcfield.3.picmig.sql',1453226128,NULL),('phabricator:20140210.projcfield.4.memmig.sql',1453226128,NULL),('phabricator:20140210.projcfield.5.dropprofile.sql',1453226128,NULL),('phabricator:20140211.dx.1.nullablechangesetid.sql',1453226128,NULL),('phabricator:20140211.dx.2.migcommenttext.php',1453226128,NULL),('phabricator:20140211.dx.3.migsubscriptions.sql',1453226128,NULL),('phabricator:20140211.dx.999.drop.relationships.sql',1453226128,NULL),('phabricator:20140212.dx.1.armageddon.php',1453226128,NULL),('phabricator:20140214.clean.1.legacycommentid.sql',1453226128,NULL),('phabricator:20140214.clean.2.dropcomment.sql',1453226128,NULL),('phabricator:20140214.clean.3.dropinline.sql',1453226128,NULL),('phabricator:20140218.differentialdraft.sql',1453226128,NULL),('phabricator:20140218.passwords.1.extend.sql',1453226128,NULL),('phabricator:20140218.passwords.2.prefix.sql',1453226128,NULL),('phabricator:20140218.passwords.3.vcsextend.sql',1453226128,NULL),('phabricator:20140218.passwords.4.vcs.php',1453226128,NULL),('phabricator:20140223.bigutf8scratch.sql',1453226128,NULL),('phabricator:20140224.dxclean.1.datecommitted.sql',1453226128,NULL),('phabricator:20140226.dxcustom.1.fielddata.php',1453226128,NULL),('phabricator:20140226.dxcustom.99.drop.sql',1453226128,NULL),('phabricator:20140228.dxcomment.1.sql',1453226128,NULL),('phabricator:20140305.diviner.1.slugcol.sql',1453226128,NULL),('phabricator:20140305.diviner.2.slugkey.sql',1453226128,NULL),('phabricator:20140311.mdroplegacy.sql',1453226128,NULL),('phabricator:20140314.projectcolumn.1.statuscol.sql',1453226128,NULL),('phabricator:20140314.projectcolumn.2.statuskey.sql',1453226128,NULL),('phabricator:20140317.mupdatedkey.sql',1453226128,NULL),('phabricator:20140321.harbor.1.bxaction.sql',1453226128,NULL),('phabricator:20140321.mstatus.1.col.sql',1453226128,NULL),('phabricator:20140321.mstatus.2.mig.php',1453226128,NULL),('phabricator:20140323.harbor.1.renames.php',1453226128,NULL),('phabricator:20140323.harbor.2.message.sql',1453226128,NULL),('phabricator:20140325.push.1.event.sql',1453226128,NULL),('phabricator:20140325.push.2.eventphid.sql',1453226128,NULL),('phabricator:20140325.push.3.groups.php',1453226128,NULL),('phabricator:20140325.push.4.prune.sql',1453226128,NULL),('phabricator:20140326.project.1.colxaction.sql',1453226128,NULL),('phabricator:20140328.releeph.1.productxaction.sql',1453226128,NULL),('phabricator:20140330.flagtext.sql',1453226128,NULL),('phabricator:20140402.actionlog.sql',1453226128,NULL),('phabricator:20140410.accountsecret.1.sql',1453226128,NULL),('phabricator:20140410.accountsecret.2.php',1453226128,NULL),('phabricator:20140416.harbor.1.sql',1453226128,NULL),('phabricator:20140420.rel.1.objectphid.sql',1453226128,NULL),('phabricator:20140420.rel.2.objectmig.php',1453226128,NULL),('phabricator:20140421.slowvotecolumnsisclosed.sql',1453226128,NULL),('phabricator:20140423.session.1.hisec.sql',1453226128,NULL),('phabricator:20140427.mfactor.1.sql',1453226128,NULL),('phabricator:20140430.auth.1.partial.sql',1453226128,NULL),('phabricator:20140430.dash.1.paneltype.sql',1453226128,NULL),('phabricator:20140430.dash.2.edge.sql',1453226128,NULL),('phabricator:20140501.passphraselockcredential.sql',1453226128,NULL),('phabricator:20140501.remove.1.dlog.sql',1453226128,NULL),('phabricator:20140507.smstable.sql',1453226128,NULL),('phabricator:20140509.coverage.1.sql',1453226128,NULL),('phabricator:20140509.dashboardlayoutconfig.sql',1453226128,NULL),('phabricator:20140512.dparents.1.sql',1453226128,NULL),('phabricator:20140514.harbormasterbuildabletransaction.sql',1453226128,NULL),('phabricator:20140514.pholiomockclose.sql',1453226129,NULL),('phabricator:20140515.trust-emails.sql',1453226129,NULL),('phabricator:20140517.dxbinarycache.sql',1453226129,NULL),('phabricator:20140518.dxmorebinarycache.sql',1453226129,NULL),('phabricator:20140519.dashboardinstall.sql',1453226129,NULL),('phabricator:20140520.authtemptoken.sql',1453226129,NULL),('phabricator:20140521.projectslug.1.create.sql',1453226129,NULL),('phabricator:20140521.projectslug.2.mig.php',1453226129,NULL),('phabricator:20140522.projecticon.sql',1453226129,NULL),('phabricator:20140524.auth.mfa.cache.sql',1453226129,NULL),('phabricator:20140525.hunkmodern.sql',1453226129,NULL),('phabricator:20140615.pholioedit.1.sql',1453226129,NULL),('phabricator:20140615.pholioedit.2.sql',1453226129,NULL),('phabricator:20140617.daemon.explicit-argv.sql',1453226129,NULL),('phabricator:20140617.daemonlog.sql',1453226129,NULL),('phabricator:20140624.projcolor.1.sql',1453226129,NULL),('phabricator:20140624.projcolor.2.sql',1453226129,NULL),('phabricator:20140629.dasharchive.1.sql',1453226129,NULL),('phabricator:20140629.legalsig.1.sql',1453226129,NULL),('phabricator:20140629.legalsig.2.php',1453226129,NULL),('phabricator:20140701.legalexemption.1.sql',1453226129,NULL),('phabricator:20140701.legalexemption.2.sql',1453226129,NULL),('phabricator:20140703.legalcorp.1.sql',1453226129,NULL),('phabricator:20140703.legalcorp.2.sql',1453226129,NULL),('phabricator:20140703.legalcorp.3.sql',1453226129,NULL),('phabricator:20140703.legalcorp.4.sql',1453226129,NULL),('phabricator:20140703.legalcorp.5.sql',1453226129,NULL),('phabricator:20140704.harbormasterstep.1.sql',1453226129,NULL),('phabricator:20140704.harbormasterstep.2.sql',1453226129,NULL),('phabricator:20140704.legalpreamble.1.sql',1453226129,NULL),('phabricator:20140706.harbormasterdepend.1.php',1453226129,NULL),('phabricator:20140706.pedge.1.sql',1453226129,NULL),('phabricator:20140711.pnames.1.sql',1453226129,NULL),('phabricator:20140711.pnames.2.php',1453226129,NULL),('phabricator:20140711.workerpriority.sql',1453226129,NULL),('phabricator:20140712.projcoluniq.sql',1453226129,NULL),('phabricator:20140721.phortune.1.cart.sql',1453226129,NULL),('phabricator:20140721.phortune.2.purchase.sql',1453226129,NULL),('phabricator:20140721.phortune.3.charge.sql',1453226129,NULL),('phabricator:20140721.phortune.4.cartstatus.sql',1453226129,NULL),('phabricator:20140721.phortune.5.cstatusdefault.sql',1453226129,NULL),('phabricator:20140721.phortune.6.onetimecharge.sql',1453226129,NULL),('phabricator:20140721.phortune.7.nullmethod.sql',1453226129,NULL),('phabricator:20140722.appname.php',1453226129,NULL),('phabricator:20140722.audit.1.xactions.sql',1453226129,NULL),('phabricator:20140722.audit.2.comments.sql',1453226129,NULL),('phabricator:20140722.audit.3.miginlines.php',1453226129,NULL),('phabricator:20140722.audit.4.migtext.php',1453226129,NULL),('phabricator:20140722.renameauth.php',1453226129,NULL),('phabricator:20140723.apprenamexaction.sql',1453226129,NULL),('phabricator:20140725.audit.1.migxactions.php',1453226129,NULL),('phabricator:20140731.audit.1.subscribers.php',1453226129,NULL),('phabricator:20140731.cancdn.php',1453226129,NULL),('phabricator:20140731.harbormasterstepdesc.sql',1453226129,NULL),('phabricator:20140805.boardcol.1.sql',1453226129,NULL),('phabricator:20140805.boardcol.2.php',1453226129,NULL),('phabricator:20140807.harbormastertargettime.sql',1453226129,NULL),('phabricator:20140808.boardprop.1.sql',1453226129,NULL),('phabricator:20140808.boardprop.2.sql',1453226129,NULL),('phabricator:20140808.boardprop.3.php',1453226129,NULL),('phabricator:20140811.blob.1.sql',1453226129,NULL),('phabricator:20140811.blob.2.sql',1453226129,NULL),('phabricator:20140812.projkey.1.sql',1453226129,NULL),('phabricator:20140812.projkey.2.sql',1453226129,NULL),('phabricator:20140814.passphrasecredentialconduit.sql',1453226129,NULL),('phabricator:20140815.cancdncase.php',1453226129,NULL),('phabricator:20140818.harbormasterindex.1.sql',1453226129,NULL),('phabricator:20140821.harbormasterbuildgen.1.sql',1453226129,NULL),('phabricator:20140822.daemonenvhash.sql',1453226129,NULL),('phabricator:20140902.almanacdevice.1.sql',1453226129,NULL),('phabricator:20140904.macroattach.php',1453226129,NULL),('phabricator:20140911.fund.1.initiative.sql',1453226129,NULL),('phabricator:20140911.fund.2.xaction.sql',1453226129,NULL),('phabricator:20140911.fund.3.edge.sql',1453226129,NULL),('phabricator:20140911.fund.4.backer.sql',1453226129,NULL),('phabricator:20140911.fund.5.backxaction.sql',1453226129,NULL),('phabricator:20140914.betaproto.php',1453226129,NULL),('phabricator:20140917.project.canlock.sql',1453226129,NULL),('phabricator:20140918.schema.1.dropaudit.sql',1453226129,NULL),('phabricator:20140918.schema.2.dropauditinline.sql',1453226129,NULL),('phabricator:20140918.schema.3.wipecache.sql',1453226129,NULL),('phabricator:20140918.schema.4.cachetype.sql',1453226129,NULL),('phabricator:20140918.schema.5.slowvote.sql',1453226129,NULL),('phabricator:20140919.schema.01.calstatus.sql',1453226129,NULL),('phabricator:20140919.schema.02.calname.sql',1453226129,NULL),('phabricator:20140919.schema.03.dropaux.sql',1453226129,NULL),('phabricator:20140919.schema.04.droptaskproj.sql',1453226129,NULL),('phabricator:20140926.schema.01.droprelev.sql',1453226129,NULL),('phabricator:20140926.schema.02.droprelreqev.sql',1453226129,NULL),('phabricator:20140926.schema.03.dropldapinfo.sql',1453226129,NULL),('phabricator:20140926.schema.04.dropoauthinfo.sql',1453226129,NULL),('phabricator:20140926.schema.05.dropprojaffil.sql',1453226129,NULL),('phabricator:20140926.schema.06.dropsubproject.sql',1453226129,NULL),('phabricator:20140926.schema.07.droppondcom.sql',1453226129,NULL),('phabricator:20140927.schema.01.dropsearchq.sql',1453226129,NULL),('phabricator:20140927.schema.02.pholio1.sql',1453226129,NULL),('phabricator:20140927.schema.03.pholio2.sql',1453226129,NULL),('phabricator:20140927.schema.04.pholio3.sql',1453226129,NULL),('phabricator:20140927.schema.05.phragment1.sql',1453226130,NULL),('phabricator:20140927.schema.06.releeph1.sql',1453226130,NULL),('phabricator:20141001.schema.01.version.sql',1453226130,NULL),('phabricator:20141001.schema.02.taskmail.sql',1453226130,NULL),('phabricator:20141002.schema.01.liskcounter.sql',1453226130,NULL),('phabricator:20141002.schema.02.draftnull.sql',1453226130,NULL),('phabricator:20141004.currency.01.sql',1453226130,NULL),('phabricator:20141004.currency.02.sql',1453226130,NULL),('phabricator:20141004.currency.03.sql',1453226130,NULL),('phabricator:20141004.currency.04.sql',1453226130,NULL),('phabricator:20141004.currency.05.sql',1453226130,NULL),('phabricator:20141004.currency.06.sql',1453226130,NULL),('phabricator:20141004.harborliskcounter.sql',1453226130,NULL),('phabricator:20141005.phortuneproduct.sql',1453226130,NULL),('phabricator:20141006.phortunecart.sql',1453226130,NULL),('phabricator:20141006.phortunemerchant.sql',1453226130,NULL),('phabricator:20141006.phortunemerchantx.sql',1453226130,NULL),('phabricator:20141007.fundmerchant.sql',1453226130,NULL),('phabricator:20141007.fundrisks.sql',1453226130,NULL),('phabricator:20141007.fundtotal.sql',1453226130,NULL),('phabricator:20141007.phortunecartmerchant.sql',1453226130,NULL),('phabricator:20141007.phortunecharge.sql',1453226130,NULL),('phabricator:20141007.phortunepayment.sql',1453226130,NULL),('phabricator:20141007.phortuneprovider.sql',1453226130,NULL),('phabricator:20141007.phortuneproviderx.sql',1453226130,NULL),('phabricator:20141008.phortunemerchdesc.sql',1453226130,NULL),('phabricator:20141008.phortuneprovdis.sql',1453226130,NULL),('phabricator:20141008.phortunerefund.sql',1453226130,NULL),('phabricator:20141010.fundmailkey.sql',1453226130,NULL),('phabricator:20141011.phortunemerchedit.sql',1453226130,NULL),('phabricator:20141012.phortunecartxaction.sql',1453226130,NULL),('phabricator:20141013.phortunecartkey.sql',1453226130,NULL),('phabricator:20141016.almanac.device.sql',1453226130,NULL),('phabricator:20141016.almanac.dxaction.sql',1453226130,NULL),('phabricator:20141016.almanac.interface.sql',1453226130,NULL),('phabricator:20141016.almanac.network.sql',1453226130,NULL),('phabricator:20141016.almanac.nxaction.sql',1453226130,NULL),('phabricator:20141016.almanac.service.sql',1453226130,NULL),('phabricator:20141016.almanac.sxaction.sql',1453226130,NULL),('phabricator:20141017.almanac.binding.sql',1453226130,NULL),('phabricator:20141017.almanac.bxaction.sql',1453226130,NULL),('phabricator:20141025.phriction.1.xaction.sql',1453226130,NULL),('phabricator:20141025.phriction.2.xaction.sql',1453226130,NULL),('phabricator:20141025.phriction.mailkey.sql',1453226130,NULL),('phabricator:20141103.almanac.1.delprop.sql',1453226130,NULL),('phabricator:20141103.almanac.2.addprop.sql',1453226131,NULL),('phabricator:20141104.almanac.3.edge.sql',1453226131,NULL),('phabricator:20141105.ssh.1.rename.sql',1453226131,NULL),('phabricator:20141106.dropold.sql',1453226131,NULL),('phabricator:20141106.uniqdrafts.php',1453226131,NULL),('phabricator:20141107.phriction.policy.1.sql',1453226131,NULL),('phabricator:20141107.phriction.policy.2.php',1453226131,NULL),('phabricator:20141107.phriction.popkeys.php',1453226131,NULL),('phabricator:20141107.ssh.1.colname.sql',1453226131,NULL),('phabricator:20141107.ssh.2.keyhash.sql',1453226131,NULL),('phabricator:20141107.ssh.3.keyindex.sql',1453226131,NULL),('phabricator:20141107.ssh.4.keymig.php',1453226131,NULL),('phabricator:20141107.ssh.5.indexnull.sql',1453226131,NULL),('phabricator:20141107.ssh.6.indexkey.sql',1453226131,NULL),('phabricator:20141107.ssh.7.colnull.sql',1453226131,NULL),('phabricator:20141113.auditdupes.php',1453226131,NULL),('phabricator:20141118.diffxaction.sql',1453226131,NULL),('phabricator:20141119.commitpedge.sql',1453226131,NULL),('phabricator:20141119.differential.diff.policy.sql',1453226131,NULL),('phabricator:20141119.sshtrust.sql',1453226131,NULL),('phabricator:20141123.taskpriority.1.sql',1453226131,NULL),('phabricator:20141123.taskpriority.2.sql',1453226131,NULL),('phabricator:20141210.maniphestsubscribersmig.1.sql',1453226131,NULL),('phabricator:20141210.maniphestsubscribersmig.2.sql',1453226131,NULL),('phabricator:20141210.reposervice.sql',1453226131,NULL),('phabricator:20141212.conduittoken.sql',1453226131,NULL),('phabricator:20141215.almanacservicetype.sql',1453226131,NULL),('phabricator:20141217.almanacdevicelock.sql',1453226131,NULL),('phabricator:20141217.almanaclock.sql',1453226131,NULL),('phabricator:20141218.maniphestcctxn.php',1453226131,NULL),('phabricator:20141222.maniphestprojtxn.php',1453226131,NULL),('phabricator:20141223.daemonloguser.sql',1453226131,NULL),('phabricator:20141223.daemonobjectphid.sql',1453226131,NULL),('phabricator:20141230.pasteeditpolicycolumn.sql',1453226131,NULL),('phabricator:20141230.pasteeditpolicyexisting.sql',1453226131,NULL),('phabricator:20150102.policyname.php',1453226131,NULL),('phabricator:20150102.tasksubscriber.sql',1453226131,NULL),('phabricator:20150105.conpsearch.sql',1453226131,NULL),('phabricator:20150114.oauthserver.client.policy.sql',1453226131,NULL),('phabricator:20150115.applicationemails.sql',1453226131,NULL),('phabricator:20150115.trigger.1.sql',1453226131,NULL),('phabricator:20150115.trigger.2.sql',1453226131,NULL),('phabricator:20150116.maniphestapplicationemails.php',1453226131,NULL),('phabricator:20150120.maniphestdefaultauthor.php',1453226131,NULL),('phabricator:20150124.subs.1.sql',1453226131,NULL),('phabricator:20150129.pastefileapplicationemails.php',1453226131,NULL),('phabricator:20150130.phortune.1.subphid.sql',1453226131,NULL),('phabricator:20150130.phortune.2.subkey.sql',1453226131,NULL),('phabricator:20150131.phortune.1.defaultpayment.sql',1453226131,NULL),('phabricator:20150205.authprovider.autologin.sql',1453226131,NULL),('phabricator:20150205.daemonenv.sql',1453226131,NULL),('phabricator:20150209.invite.sql',1453226131,NULL),('phabricator:20150209.oauthclient.trust.sql',1453226131,NULL),('phabricator:20150210.invitephid.sql',1453226131,NULL),('phabricator:20150212.legalpad.session.1.sql',1453226131,NULL),('phabricator:20150212.legalpad.session.2.sql',1453226131,NULL),('phabricator:20150219.scratch.nonmutable.sql',1453226131,NULL),('phabricator:20150223.daemon.1.id.sql',1453226131,NULL),('phabricator:20150223.daemon.2.idlegacy.sql',1453226131,NULL),('phabricator:20150223.daemon.3.idkey.sql',1453226131,NULL),('phabricator:20150312.filechunk.1.sql',1453226131,NULL),('phabricator:20150312.filechunk.2.sql',1453226131,NULL),('phabricator:20150312.filechunk.3.sql',1453226131,NULL),('phabricator:20150317.conpherence.isroom.1.sql',1453226131,NULL),('phabricator:20150317.conpherence.isroom.2.sql',1453226131,NULL),('phabricator:20150317.conpherence.policy.sql',1453226131,NULL),('phabricator:20150410.nukeruleedit.sql',1453226131,NULL),('phabricator:20150420.invoice.1.sql',1453226131,NULL),('phabricator:20150420.invoice.2.sql',1453226131,NULL),('phabricator:20150425.isclosed.sql',1453226131,NULL),('phabricator:20150427.calendar.1.edge.sql',1453226131,NULL),('phabricator:20150427.calendar.1.xaction.sql',1453226131,NULL),('phabricator:20150427.calendar.2.xaction.sql',1453226131,NULL),('phabricator:20150428.calendar.1.iscancelled.sql',1453226131,NULL),('phabricator:20150428.calendar.1.name.sql',1453226131,NULL),('phabricator:20150429.calendar.1.invitee.sql',1453226131,NULL),('phabricator:20150430.calendar.1.policies.sql',1453226132,NULL),('phabricator:20150430.multimeter.1.sql',1453226132,NULL),('phabricator:20150430.multimeter.2.host.sql',1453226132,NULL),('phabricator:20150430.multimeter.3.viewer.sql',1453226132,NULL),('phabricator:20150430.multimeter.4.context.sql',1453226132,NULL),('phabricator:20150430.multimeter.5.label.sql',1453226132,NULL),('phabricator:20150501.calendar.1.reply.sql',1453226132,NULL),('phabricator:20150501.calendar.2.reply.php',1453226132,NULL),('phabricator:20150501.conpherencepics.sql',1453226132,NULL),('phabricator:20150503.repositorysymbols.1.sql',1453226132,NULL),('phabricator:20150503.repositorysymbols.2.php',1453226132,NULL),('phabricator:20150503.repositorysymbols.3.sql',1453226132,NULL),('phabricator:20150504.symbolsproject.1.php',1453226132,NULL),('phabricator:20150504.symbolsproject.2.sql',1453226132,NULL),('phabricator:20150506.calendarunnamedevents.1.php',1453226132,NULL),('phabricator:20150507.calendar.1.isallday.sql',1453226132,NULL),('phabricator:20150513.user.cache.1.sql',1453226132,NULL),('phabricator:20150514.calendar.status.sql',1453226132,NULL),('phabricator:20150514.phame.blog.xaction.sql',1453226132,NULL),('phabricator:20150514.user.cache.2.sql',1453226132,NULL),('phabricator:20150515.phame.post.xaction.sql',1453226132,NULL),('phabricator:20150515.project.mailkey.1.sql',1453226132,NULL),('phabricator:20150515.project.mailkey.2.php',1453226132,NULL),('phabricator:20150519.calendar.calendaricon.sql',1453226132,NULL),('phabricator:20150521.releephrepository.sql',1453226132,NULL),('phabricator:20150525.diff.hidden.1.sql',1453226132,NULL),('phabricator:20150526.owners.mailkey.1.sql',1453226132,NULL),('phabricator:20150526.owners.mailkey.2.php',1453226132,NULL),('phabricator:20150526.owners.xaction.sql',1453226132,NULL),('phabricator:20150527.calendar.recurringevents.sql',1453226132,NULL),('phabricator:20150601.spaces.1.namespace.sql',1453226132,NULL),('phabricator:20150601.spaces.2.xaction.sql',1453226132,NULL),('phabricator:20150602.mlist.1.sql',1453226132,NULL),('phabricator:20150602.mlist.2.php',1453226132,NULL),('phabricator:20150604.spaces.1.sql',1453226132,NULL),('phabricator:20150605.diviner.edges.sql',1453226132,NULL),('phabricator:20150605.diviner.editPolicy.sql',1453226132,NULL),('phabricator:20150605.diviner.xaction.sql',1453226132,NULL),('phabricator:20150606.mlist.1.php',1453226132,NULL),('phabricator:20150609.inline.sql',1453226132,NULL),('phabricator:20150609.spaces.1.pholio.sql',1453226132,NULL),('phabricator:20150609.spaces.2.maniphest.sql',1453226132,NULL),('phabricator:20150610.spaces.1.desc.sql',1453226132,NULL),('phabricator:20150610.spaces.2.edge.sql',1453226132,NULL),('phabricator:20150610.spaces.3.archive.sql',1453226132,NULL),('phabricator:20150611.spaces.1.mailxaction.sql',1453226132,NULL),('phabricator:20150611.spaces.2.appmail.sql',1453226132,NULL),('phabricator:20150616.divinerrepository.sql',1453226132,NULL),('phabricator:20150617.harbor.1.lint.sql',1453226132,NULL),('phabricator:20150617.harbor.2.unit.sql',1453226132,NULL),('phabricator:20150618.harbor.1.planauto.sql',1453226132,NULL),('phabricator:20150618.harbor.2.stepauto.sql',1453226132,NULL),('phabricator:20150618.harbor.3.buildauto.sql',1453226132,NULL),('phabricator:20150619.conpherencerooms.1.sql',1453226132,NULL),('phabricator:20150619.conpherencerooms.2.sql',1453226132,NULL),('phabricator:20150619.conpherencerooms.3.sql',1453226132,NULL),('phabricator:20150621.phrase.1.sql',1453226132,NULL),('phabricator:20150621.phrase.2.sql',1453226132,NULL),('phabricator:20150622.bulk.1.job.sql',1453226132,NULL),('phabricator:20150622.bulk.2.task.sql',1453226132,NULL),('phabricator:20150622.bulk.3.xaction.sql',1453226132,NULL),('phabricator:20150622.bulk.4.edge.sql',1453226132,NULL),('phabricator:20150622.metamta.1.phid-col.sql',1453226132,NULL),('phabricator:20150622.metamta.2.phid-mig.php',1453226132,NULL),('phabricator:20150622.metamta.3.phid-key.sql',1453226132,NULL),('phabricator:20150622.metamta.4.actor-phid-col.sql',1453226132,NULL),('phabricator:20150622.metamta.5.actor-phid-mig.php',1453226132,NULL),('phabricator:20150622.metamta.6.actor-phid-key.sql',1453226132,NULL),('phabricator:20150624.spaces.1.repo.sql',1453226132,NULL),('phabricator:20150626.spaces.1.calendar.sql',1453226132,NULL),('phabricator:20150630.herald.1.sql',1453226132,NULL),('phabricator:20150630.herald.2.sql',1453226132,NULL),('phabricator:20150701.herald.1.sql',1453226132,NULL),('phabricator:20150701.herald.2.sql',1453226132,NULL),('phabricator:20150702.spaces.1.slowvote.sql',1453226133,NULL),('phabricator:20150706.herald.1.sql',1453226133,NULL),('phabricator:20150707.herald.1.sql',1453226133,NULL),('phabricator:20150708.arcanistproject.sql',1453226133,NULL),('phabricator:20150708.herald.1.sql',1453226133,NULL),('phabricator:20150708.herald.2.sql',1453226133,NULL),('phabricator:20150708.herald.3.sql',1453226133,NULL),('phabricator:20150712.badges.1.sql',1453226133,NULL),('phabricator:20150714.spaces.countdown.1.sql',1453226133,NULL),('phabricator:20150717.herald.1.sql',1453226133,NULL),('phabricator:20150719.countdown.1.sql',1453226133,NULL),('phabricator:20150719.countdown.2.sql',1453226133,NULL),('phabricator:20150719.countdown.3.sql',1453226133,NULL),('phabricator:20150721.phurl.1.url.sql',1453226133,NULL),('phabricator:20150721.phurl.2.xaction.sql',1453226133,NULL),('phabricator:20150721.phurl.3.xactioncomment.sql',1453226133,NULL),('phabricator:20150721.phurl.4.url.sql',1453226133,NULL),('phabricator:20150721.phurl.5.edge.sql',1453226133,NULL),('phabricator:20150721.phurl.6.alias.sql',1453226133,NULL),('phabricator:20150721.phurl.7.authorphid.sql',1453226133,NULL),('phabricator:20150722.dashboard.1.sql',1453226133,NULL),('phabricator:20150722.dashboard.2.sql',1453226133,NULL),('phabricator:20150723.countdown.1.sql',1453226133,NULL),('phabricator:20150724.badges.comments.1.sql',1453226133,NULL),('phabricator:20150724.countdown.comments.1.sql',1453226133,NULL),('phabricator:20150725.badges.mailkey.1.sql',1453226133,NULL),('phabricator:20150725.badges.mailkey.2.php',1453226133,NULL),('phabricator:20150725.badges.viewpolicy.3.sql',1453226133,NULL),('phabricator:20150725.countdown.mailkey.1.sql',1453226133,NULL),('phabricator:20150725.countdown.mailkey.2.php',1453226133,NULL),('phabricator:20150725.slowvote.mailkey.1.sql',1453226133,NULL),('phabricator:20150725.slowvote.mailkey.2.php',1453226133,NULL),('phabricator:20150727.heraldaction.1.sql',1453226133,NULL),('phabricator:20150730.herald.1.sql',1453226133,NULL),('phabricator:20150730.herald.2.sql',1453226133,NULL),('phabricator:20150730.herald.3.sql',1453226133,NULL),('phabricator:20150730.herald.4.sql',1453226133,NULL),('phabricator:20150730.herald.5.sql',1453226133,NULL),('phabricator:20150730.herald.6.sql',1453226133,NULL),('phabricator:20150730.herald.7.sql',1453226133,NULL),('phabricator:20150803.herald.1.sql',1453226133,NULL),('phabricator:20150803.herald.2.sql',1453226133,NULL),('phabricator:20150804.ponder.answer.mailkey.1.sql',1453226133,NULL),('phabricator:20150804.ponder.answer.mailkey.2.php',1453226133,NULL),('phabricator:20150804.ponder.question.1.sql',1453226133,NULL),('phabricator:20150804.ponder.question.2.sql',1453226133,NULL),('phabricator:20150804.ponder.question.3.sql',1453226133,NULL),('phabricator:20150804.ponder.spaces.4.sql',1453226133,NULL),('phabricator:20150805.paste.status.1.sql',1453226133,NULL),('phabricator:20150805.paste.status.2.sql',1453226133,NULL),('phabricator:20150806.ponder.answer.1.sql',1453226133,NULL),('phabricator:20150806.ponder.editpolicy.2.sql',1453226133,NULL),('phabricator:20150806.ponder.status.1.sql',1453226133,NULL),('phabricator:20150806.ponder.status.2.sql',1453226133,NULL),('phabricator:20150806.ponder.status.3.sql',1453226133,NULL),('phabricator:20150808.ponder.vote.1.sql',1453226133,NULL),('phabricator:20150808.ponder.vote.2.sql',1453226133,NULL),('phabricator:20150812.ponder.answer.1.sql',1453226133,NULL),('phabricator:20150812.ponder.answer.2.sql',1453226133,NULL),('phabricator:20150814.harbormater.artifact.phid.sql',1453226133,NULL),('phabricator:20150815.owners.status.1.sql',1453226133,NULL),('phabricator:20150815.owners.status.2.sql',1453226133,NULL),('phabricator:20150823.nuance.queue.1.sql',1453226133,NULL),('phabricator:20150823.nuance.queue.2.sql',1453226133,NULL),('phabricator:20150823.nuance.queue.3.sql',1453226133,NULL),('phabricator:20150823.nuance.queue.4.sql',1453226133,NULL),('phabricator:20150828.ponder.wiki.1.sql',1453226133,NULL),('phabricator:20150829.ponder.dupe.1.sql',1453226133,NULL),('phabricator:20150904.herald.1.sql',1453226133,NULL),('phabricator:20150906.mailinglist.sql',1453226133,NULL),('phabricator:20150910.owners.custom.1.sql',1453226133,NULL),('phabricator:20150916.drydock.slotlocks.1.sql',1453226133,NULL),('phabricator:20150922.drydock.commands.1.sql',1453226133,NULL),('phabricator:20150923.drydock.resourceid.1.sql',1453226133,NULL),('phabricator:20150923.drydock.resourceid.2.sql',1453226133,NULL),('phabricator:20150923.drydock.resourceid.3.sql',1453226133,NULL),('phabricator:20150923.drydock.taskid.1.sql',1453226133,NULL),('phabricator:20150924.drydock.disable.1.sql',1453226133,NULL),('phabricator:20150924.drydock.status.1.sql',1453226133,NULL),('phabricator:20150928.drydock.rexpire.1.sql',1453226133,NULL),('phabricator:20150930.drydock.log.1.sql',1453226134,NULL),('phabricator:20151001.drydock.rname.1.sql',1453226134,NULL),('phabricator:20151002.dashboard.status.1.sql',1453226134,NULL),('phabricator:20151002.harbormaster.bparam.1.sql',1453226134,NULL),('phabricator:20151009.drydock.auth.1.sql',1453226134,NULL),('phabricator:20151010.drydock.auth.2.sql',1453226134,NULL),('phabricator:20151013.drydock.op.1.sql',1453226134,NULL),('phabricator:20151023.harborpolicy.1.sql',1453226134,NULL),('phabricator:20151023.harborpolicy.2.php',1453226134,NULL),('phabricator:20151023.patchduration.sql',1453226134,14142),('phabricator:20151030.harbormaster.initiator.sql',1453226134,35726),('phabricator:20151106.editengine.1.table.sql',1453226134,8030),('phabricator:20151106.editengine.2.xactions.sql',1453226134,7392),('phabricator:20151106.phame.post.mailkey.1.sql',1453226134,18595),('phabricator:20151106.phame.post.mailkey.2.php',1453226134,1616),('phabricator:20151107.phame.blog.mailkey.1.sql',1453226134,19832),('phabricator:20151107.phame.blog.mailkey.2.php',1453226134,1389),('phabricator:20151108.phame.blog.joinpolicy.sql',1453226134,16415),('phabricator:20151108.xhpast.stderr.sql',1453226134,24424),('phabricator:20151109.phame.post.comments.1.sql',1453226134,8007),('phabricator:20151109.repository.coverage.1.sql',1453226134,1405),('phabricator:20151109.xhpast.db.1.sql',1453226134,1559),('phabricator:20151109.xhpast.db.2.sql',1453226134,599),('phabricator:20151110.daemonenvhash.sql',1453226134,39904),('phabricator:20151111.phame.blog.archive.1.sql',1453226134,15720),('phabricator:20151111.phame.blog.archive.2.sql',1453226134,534),('phabricator:20151112.herald.edge.sql',1453226134,13618),('phabricator:20151116.owners.edge.sql',1453226134,13570),('phabricator:20151128.phame.blog.picture.1.sql',1453226134,15964),('phabricator:20151130.phurl.mailkey.1.sql',1453226134,10402),('phabricator:20151130.phurl.mailkey.2.php',1453226134,1457),('phabricator:20151202.versioneddraft.1.sql',1453226134,8923),('phabricator:20151207.editengine.1.sql',1453226134,76111),('phabricator:20151210.land.1.refphid.sql',1453226134,19463),('phabricator:20151210.land.2.refphid.php',1453226134,833),('phabricator:20151215.phame.1.autotitle.sql',1453226134,21510),('phabricator:20151218.key.1.keyphid.sql',1453226134,14834),('phabricator:20151218.key.2.keyphid.php',1453226134,429),('phabricator:20151219.proj.01.prislug.sql',1453226134,21059),('phabricator:20151219.proj.02.prislugkey.sql',1453226134,16233),('phabricator:20151219.proj.03.copyslug.sql',1453226134,474),('phabricator:20151219.proj.04.dropslugkey.sql',1453226134,7782),('phabricator:20151219.proj.05.dropslug.sql',1453226134,20865),('phabricator:20151219.proj.06.defaultpolicy.php',1453226134,1358),('phabricator:20151219.proj.07.viewnull.sql',1453226134,16753),('phabricator:20151219.proj.08.editnull.sql',1453226134,13683),('phabricator:20151219.proj.09.joinnull.sql',1453226134,10924),('phabricator:20151219.proj.10.subcolumns.sql',1453226134,129879),('phabricator:20151219.proj.11.subprojectphids.sql',1453226135,26586),('phabricator:20151221.search.1.version.sql',1453226135,14029),('phabricator:20151221.search.2.ownersngrams.sql',1453226135,7390),('phabricator:20151221.search.3.reindex.php',1453226135,436),('phabricator:20151223.proj.01.paths.sql',1453226135,22387),('phabricator:20151223.proj.02.depths.sql',1453226135,28069),('phabricator:20151223.proj.03.pathkey.sql',1453226135,12562),('phabricator:20151223.proj.04.keycol.sql',1453226135,24719),('phabricator:20151223.proj.05.updatekeys.php',1453226135,463),('phabricator:20151223.proj.06.uniq.sql',1453226135,12857),('phabricator:20151226.reop.1.sql',1453226135,19351),('phabricator:20151227.proj.01.materialize.sql',1453226135,697),('phabricator:20151231.proj.01.icon.php',1453226135,3273),('phabricator:20160110.repo.01.slug.sql',1453226135,31556),('phabricator:20160110.repo.02.slug.php',1453226135,461),('phabricator:20160111.repo.01.slugx.sql',1453226135,745),('phabricator:20160112.repo.01.uri.sql',1453226135,7698),('phabricator:20160112.repo.02.uri.index.php',1453226135,437),('phabricator:20160113.propanel.1.storage.sql',1453226135,6273),('phabricator:20160113.propanel.2.xaction.sql',1453226135,7608),('phabricator:daemonstatus.sql',1453226123,NULL),('phabricator:daemonstatuskey.sql',1453226123,NULL),('phabricator:daemontaskarchive.sql',1453226124,NULL),('phabricator:db.almanac',1453226117,NULL),('phabricator:db.audit',1453226117,NULL),('phabricator:db.auth',1453226117,NULL),('phabricator:db.badges',1453226117,NULL),('phabricator:db.cache',1453226117,NULL),('phabricator:db.calendar',1453226117,NULL),('phabricator:db.chatlog',1453226117,NULL),('phabricator:db.conduit',1453226117,NULL),('phabricator:db.config',1453226117,NULL),('phabricator:db.conpherence',1453226117,NULL),('phabricator:db.countdown',1453226117,NULL),('phabricator:db.daemon',1453226117,NULL),('phabricator:db.dashboard',1453226117,NULL),('phabricator:db.differential',1453226117,NULL),('phabricator:db.diviner',1453226117,NULL),('phabricator:db.doorkeeper',1453226117,NULL),('phabricator:db.draft',1453226117,NULL),('phabricator:db.drydock',1453226117,NULL),('phabricator:db.fact',1453226117,NULL),('phabricator:db.feed',1453226117,NULL),('phabricator:db.file',1453226117,NULL),('phabricator:db.flag',1453226117,NULL),('phabricator:db.fund',1453226117,NULL),('phabricator:db.harbormaster',1453226117,NULL),('phabricator:db.herald',1453226117,NULL),('phabricator:db.legalpad',1453226117,NULL),('phabricator:db.maniphest',1453226117,NULL),('phabricator:db.meta_data',1453226117,NULL),('phabricator:db.metamta',1453226117,NULL),('phabricator:db.multimeter',1453226117,NULL),('phabricator:db.nuance',1453226117,NULL),('phabricator:db.oauth_server',1453226117,NULL),('phabricator:db.owners',1453226117,NULL),('phabricator:db.passphrase',1453226117,NULL),('phabricator:db.pastebin',1453226117,NULL),('phabricator:db.phame',1453226117,NULL),('phabricator:db.phlux',1453226117,NULL),('phabricator:db.pholio',1453226117,NULL),('phabricator:db.phortune',1453226117,NULL),('phabricator:db.phragment',1453226117,NULL),('phabricator:db.phrequent',1453226117,NULL),('phabricator:db.phriction',1453226117,NULL),('phabricator:db.phurl',1453226117,NULL),('phabricator:db.policy',1453226117,NULL),('phabricator:db.ponder',1453226117,NULL),('phabricator:db.project',1453226117,NULL),('phabricator:db.releeph',1453226117,NULL),('phabricator:db.repository',1453226117,NULL),('phabricator:db.search',1453226117,NULL),('phabricator:db.slowvote',1453226117,NULL),('phabricator:db.spaces',1453226117,NULL),('phabricator:db.system',1453226117,NULL),('phabricator:db.timeline',1453226117,NULL),('phabricator:db.token',1453226117,NULL),('phabricator:db.user',1453226117,NULL),('phabricator:db.worker',1453226117,NULL),('phabricator:db.xhpast',1453226117,NULL),('phabricator:db.xhpastview',1453226117,NULL),('phabricator:db.xhprof',1453226117,NULL),('phabricator:differentialbookmarks.sql',1453226123,NULL),('phabricator:draft-metadata.sql',1453226123,NULL),('phabricator:dropfileproxyimage.sql',1453226124,NULL),('phabricator:drydockresoucetype.sql',1453226124,NULL),('phabricator:drydocktaskid.sql',1453226124,NULL),('phabricator:edgetype.sql',1453226123,NULL),('phabricator:emailtable.sql',1453226123,NULL),('phabricator:emailtableport.sql',1453226123,NULL),('phabricator:emailtableremove.sql',1453226123,NULL),('phabricator:fact-raw.sql',1453226123,NULL),('phabricator:harbormasterobject.sql',1453226123,NULL),('phabricator:holidays.sql',1453226123,NULL),('phabricator:ldapinfo.sql',1453226123,NULL),('phabricator:legalpad-mailkey-populate.php',1453226125,NULL),('phabricator:legalpad-mailkey.sql',1453226125,NULL),('phabricator:liskcounters-task.sql',1453226124,NULL),('phabricator:liskcounters.php',1453226124,NULL),('phabricator:liskcounters.sql',1453226124,NULL),('phabricator:maniphestxcache.sql',1453226123,NULL),('phabricator:markupcache.sql',1453226123,NULL),('phabricator:migrate-differential-dependencies.php',1453226123,NULL),('phabricator:migrate-maniphest-dependencies.php',1453226123,NULL),('phabricator:migrate-maniphest-revisions.php',1453226123,NULL),('phabricator:migrate-project-edges.php',1453226123,NULL),('phabricator:owners-exclude.sql',1453226124,NULL),('phabricator:pastepolicy.sql',1453226123,NULL),('phabricator:phameblog.sql',1453226123,NULL),('phabricator:phamedomain.sql',1453226123,NULL),('phabricator:phameoneblog.sql',1453226123,NULL),('phabricator:phamepolicy.sql',1453226123,NULL),('phabricator:phiddrop.sql',1453226123,NULL),('phabricator:pholio.sql',1453226124,NULL),('phabricator:policy-project.sql',1453226123,NULL),('phabricator:ponder-comments.sql',1453226123,NULL),('phabricator:ponder-mailkey-populate.php',1453226123,NULL),('phabricator:ponder-mailkey.sql',1453226123,NULL),('phabricator:ponder.sql',1453226123,NULL),('phabricator:releeph.sql',1453226124,NULL),('phabricator:repository-lint.sql',1453226124,NULL),('phabricator:statustxt.sql',1453226124,NULL),('phabricator:symbolcontexts.sql',1453226123,NULL),('phabricator:testdatabase.sql',1453226123,NULL),('phabricator:threadtopic.sql',1453226123,NULL),('phabricator:userstatus.sql',1453226123,NULL),('phabricator:usertranslation.sql',1453226123,NULL),('phabricator:xhprof.sql',1453226123,NULL); CREATE DATABASE /*!32312 IF NOT EXISTS*/ `{$NAMESPACE}_metamta` /*!40100 DEFAULT CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} */; @@ -1665,20 +1736,6 @@ CREATE TABLE `metamta_mail` ( KEY `status` (`status`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; -CREATE TABLE `metamta_mailinglist` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `phid` varbinary(64) NOT NULL, - `name` varchar(128) COLLATE {$COLLATE_TEXT} NOT NULL, - `email` varchar(128) COLLATE {$COLLATE_TEXT} NOT NULL, - `uri` varchar(255) COLLATE {$COLLATE_TEXT} DEFAULT NULL, - `dateCreated` int(10) unsigned NOT NULL, - `dateModified` int(10) unsigned NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `phid` (`phid`), - UNIQUE KEY `email` (`email`), - UNIQUE KEY `name` (`name`) -) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; - CREATE TABLE `metamta_receivedmail` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `headers` longtext COLLATE {$COLLATE_TEXT} NOT NULL, @@ -1774,6 +1831,24 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `{$NAMESPACE}_owners` /*!40100 DEFAULT USE `{$NAMESPACE}_owners`; +CREATE TABLE `edge` ( + `src` varbinary(64) NOT NULL, + `type` int(10) unsigned NOT NULL, + `dst` varbinary(64) NOT NULL, + `dateCreated` int(10) unsigned NOT NULL, + `seq` int(10) unsigned NOT NULL, + `dataID` int(10) unsigned DEFAULT NULL, + PRIMARY KEY (`src`,`type`,`dst`), + UNIQUE KEY `key_dst` (`dst`,`type`,`src`), + KEY `src` (`src`,`type`,`dateCreated`,`seq`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + +CREATE TABLE `edgedata` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `data` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + CREATE TABLE `owners_customfieldnumericindex` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `objectPHID` varbinary(64) NOT NULL, @@ -1803,6 +1878,15 @@ CREATE TABLE `owners_customfieldstringindex` ( KEY `key_find` (`indexKey`,`indexValue`(64)) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; +CREATE TABLE `owners_name_ngrams` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `objectID` int(10) unsigned NOT NULL, + `ngram` char(3) COLLATE {$COLLATE_TEXT} NOT NULL, + PRIMARY KEY (`id`), + KEY `key_object` (`objectID`), + KEY `key_ngram` (`ngram`,`objectID`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + CREATE TABLE `owners_owner` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `packageID` int(10) unsigned NOT NULL, @@ -1815,7 +1899,7 @@ CREATE TABLE `owners_owner` ( CREATE TABLE `owners_package` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `phid` varbinary(64) NOT NULL, - `name` varchar(128) COLLATE {$COLLATE_TEXT} NOT NULL, + `name` varchar(128) CHARACTER SET {$CHARSET_SORT} COLLATE {$COLLATE_SORT} NOT NULL, `originalName` varchar(255) COLLATE {$COLLATE_TEXT} NOT NULL, `description` longtext COLLATE {$COLLATE_TEXT} NOT NULL, `primaryOwnerPHID` varbinary(64) DEFAULT NULL, @@ -1823,8 +1907,7 @@ CREATE TABLE `owners_package` ( `mailKey` binary(20) NOT NULL, `status` varchar(32) COLLATE {$COLLATE_TEXT} NOT NULL, PRIMARY KEY (`id`), - UNIQUE KEY `phid` (`phid`), - UNIQUE KEY `name` (`name`) + UNIQUE KEY `key_phid` (`phid`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; CREATE TABLE `owners_packagetransaction` ( @@ -1979,7 +2062,9 @@ CREATE TABLE `phame_blog` ( `dateModified` int(10) unsigned NOT NULL, `viewPolicy` varbinary(64) DEFAULT NULL, `editPolicy` varbinary(64) DEFAULT NULL, - `joinPolicy` varbinary(64) DEFAULT NULL, + `mailKey` binary(20) NOT NULL, + `status` varchar(32) COLLATE {$COLLATE_TEXT} NOT NULL, + `profileImagePHID` varbinary(64) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `phid` (`phid`), UNIQUE KEY `domain` (`domain`) @@ -2011,7 +2096,7 @@ CREATE TABLE `phame_post` ( `phid` varbinary(64) NOT NULL, `bloggerPHID` varbinary(64) NOT NULL, `title` varchar(255) COLLATE {$COLLATE_TEXT} NOT NULL, - `phameTitle` varchar(64) CHARACTER SET {$CHARSET_SORT} COLLATE {$COLLATE_SORT} NOT NULL, + `phameTitle` varchar(64) CHARACTER SET {$CHARSET_SORT} COLLATE {$COLLATE_SORT} DEFAULT NULL, `body` longtext COLLATE {$COLLATE_TEXT}, `visibility` int(10) unsigned NOT NULL DEFAULT '0', `configData` longtext COLLATE {$COLLATE_TEXT}, @@ -2019,9 +2104,9 @@ CREATE TABLE `phame_post` ( `dateCreated` int(10) unsigned NOT NULL, `dateModified` int(10) unsigned NOT NULL, `blogPHID` varbinary(64) DEFAULT NULL, + `mailKey` binary(20) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `phid` (`phid`), - UNIQUE KEY `phameTitle` (`bloggerPHID`,`phameTitle`), KEY `bloggerPosts` (`bloggerPHID`,`visibility`,`datePublished`,`id`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; @@ -2046,6 +2131,24 @@ CREATE TABLE `phame_posttransaction` ( KEY `key_object` (`objectPHID`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; +CREATE TABLE `phame_posttransaction_comment` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `phid` varbinary(64) NOT NULL, + `transactionPHID` varbinary(64) DEFAULT NULL, + `authorPHID` varbinary(64) NOT NULL, + `viewPolicy` varbinary(64) NOT NULL, + `editPolicy` varbinary(64) NOT NULL, + `commentVersion` int(10) unsigned NOT NULL, + `content` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `contentSource` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `isDeleted` tinyint(1) NOT NULL, + `dateCreated` int(10) unsigned NOT NULL, + `dateModified` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `key_phid` (`phid`), + UNIQUE KEY `key_version` (`transactionPHID`,`commentVersion`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + CREATE DATABASE /*!32312 IF NOT EXISTS*/ `{$NAMESPACE}_phriction` /*!40100 DEFAULT CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} */; USE `{$NAMESPACE}_phriction`; @@ -2172,22 +2275,31 @@ CREATE TABLE `project` ( `dateCreated` int(10) unsigned NOT NULL, `dateModified` int(10) unsigned NOT NULL, `status` varchar(32) COLLATE {$COLLATE_TEXT} NOT NULL, - `subprojectPHIDs` longtext COLLATE {$COLLATE_TEXT} NOT NULL, - `phrictionSlug` varchar(128) COLLATE {$COLLATE_TEXT} DEFAULT NULL, - `viewPolicy` varbinary(64) DEFAULT NULL, - `editPolicy` varbinary(64) DEFAULT NULL, - `joinPolicy` varbinary(64) DEFAULT NULL, + `viewPolicy` varbinary(64) NOT NULL, + `editPolicy` varbinary(64) NOT NULL, + `joinPolicy` varbinary(64) NOT NULL, `isMembershipLocked` tinyint(1) NOT NULL DEFAULT '0', `profileImagePHID` varbinary(64) DEFAULT NULL, `icon` varchar(32) COLLATE {$COLLATE_TEXT} NOT NULL, `color` varchar(32) COLLATE {$COLLATE_TEXT} NOT NULL, `mailKey` binary(20) NOT NULL, + `primarySlug` varchar(128) COLLATE {$COLLATE_TEXT} DEFAULT NULL, + `parentProjectPHID` varbinary(64) DEFAULT NULL, + `hasWorkboard` tinyint(1) NOT NULL, + `hasMilestones` tinyint(1) NOT NULL, + `hasSubprojects` tinyint(1) NOT NULL, + `milestoneNumber` int(10) unsigned DEFAULT NULL, + `projectPath` varbinary(64) NOT NULL, + `projectDepth` int(10) unsigned NOT NULL, + `projectPathKey` binary(4) NOT NULL, PRIMARY KEY (`id`), - UNIQUE KEY `phid` (`phid`), - UNIQUE KEY `name` (`name`), - UNIQUE KEY `phrictionSlug` (`phrictionSlug`), + UNIQUE KEY `key_pathkey` (`projectPathKey`), + UNIQUE KEY `key_phid` (`phid`), + UNIQUE KEY `key_primaryslug` (`primarySlug`), + UNIQUE KEY `key_milestone` (`parentProjectPHID`,`milestoneNumber`), KEY `key_icon` (`icon`), - KEY `key_color` (`color`) + KEY `key_color` (`color`), + KEY `key_path` (`projectPath`,`projectDepth`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; CREATE TABLE `project_column` ( @@ -2347,9 +2459,11 @@ CREATE TABLE `repository` ( `credentialPHID` varbinary(64) DEFAULT NULL, `almanacServicePHID` varbinary(64) DEFAULT NULL, `spacePHID` varbinary(64) DEFAULT NULL, + `repositorySlug` varchar(64) CHARACTER SET {$CHARSET_SORT} COLLATE {$COLLATE_SORT} DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `callsign` (`callsign`), - UNIQUE KEY `phid` (`phid`), + UNIQUE KEY `key_phid` (`phid`), + UNIQUE KEY `key_slug` (`repositorySlug`), KEY `key_vcs` (`versionControlSystem`), KEY `key_name` (`name`(128)), KEY `key_space` (`spacePHID`) @@ -2422,7 +2536,7 @@ CREATE TABLE `repository_coverage` ( `pathID` int(10) unsigned NOT NULL, `coverage` longblob NOT NULL, PRIMARY KEY (`id`), - KEY `key_path` (`branchID`,`pathID`,`commitID`) + UNIQUE KEY `key_path` (`branchID`,`pathID`,`commitID`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; CREATE TABLE `repository_filesystem` ( @@ -2537,6 +2651,7 @@ CREATE TABLE `repository_pushlog` ( CREATE TABLE `repository_refcursor` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `phid` varbinary(64) NOT NULL, `repositoryPHID` varbinary(64) NOT NULL, `refType` varchar(32) COLLATE {$COLLATE_TEXT} NOT NULL, `refNameHash` binary(12) NOT NULL, @@ -2545,6 +2660,7 @@ CREATE TABLE `repository_refcursor` ( `commitIdentifier` varchar(40) COLLATE {$COLLATE_TEXT} NOT NULL, `isClosed` tinyint(1) NOT NULL, PRIMARY KEY (`id`), + UNIQUE KEY `key_phid` (`phid`), KEY `key_cursor` (`repositoryPHID`,`refType`,`refNameHash`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; @@ -2600,6 +2716,15 @@ CREATE TABLE `repository_transaction` ( KEY `key_object` (`objectPHID`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; +CREATE TABLE `repository_uriindex` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `repositoryPHID` varbinary(64) NOT NULL, + `repositoryURI` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + PRIMARY KEY (`id`), + KEY `key_repository` (`repositoryPHID`), + KEY `key_uri` (`repositoryURI`(128)) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + CREATE TABLE `repository_vcspassword` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `userPHID` varbinary(64) NOT NULL, @@ -2645,6 +2770,58 @@ CREATE TABLE `search_documentrelationship` ( KEY `relation` (`relation`,`relatedPHID`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; +CREATE TABLE `search_editengineconfiguration` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `phid` varbinary(64) NOT NULL, + `engineKey` varchar(64) COLLATE {$COLLATE_TEXT} NOT NULL, + `builtinKey` varchar(64) COLLATE {$COLLATE_TEXT} DEFAULT NULL, + `name` varchar(255) COLLATE {$COLLATE_TEXT} NOT NULL, + `viewPolicy` varbinary(64) NOT NULL, + `properties` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `isDisabled` tinyint(1) NOT NULL DEFAULT '0', + `isDefault` tinyint(1) NOT NULL DEFAULT '0', + `dateCreated` int(10) unsigned NOT NULL, + `dateModified` int(10) unsigned NOT NULL, + `isEdit` tinyint(1) NOT NULL, + `createOrder` int(10) unsigned NOT NULL, + `editOrder` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `key_phid` (`phid`), + UNIQUE KEY `key_engine` (`engineKey`,`builtinKey`), + KEY `key_default` (`engineKey`,`isDefault`,`isDisabled`), + KEY `key_edit` (`engineKey`,`isEdit`,`isDisabled`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + +CREATE TABLE `search_editengineconfigurationtransaction` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `phid` varbinary(64) NOT NULL, + `authorPHID` varbinary(64) NOT NULL, + `objectPHID` varbinary(64) NOT NULL, + `viewPolicy` varbinary(64) NOT NULL, + `editPolicy` varbinary(64) NOT NULL, + `commentPHID` varbinary(64) DEFAULT NULL, + `commentVersion` int(10) unsigned NOT NULL, + `transactionType` varchar(32) COLLATE {$COLLATE_TEXT} NOT NULL, + `oldValue` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `newValue` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `contentSource` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `metadata` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `dateCreated` int(10) unsigned NOT NULL, + `dateModified` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `key_phid` (`phid`), + KEY `key_object` (`objectPHID`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + +CREATE TABLE `search_indexversion` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `objectPHID` varbinary(64) NOT NULL, + `extensionKey` varchar(64) COLLATE {$COLLATE_TEXT} NOT NULL, + `version` varchar(128) COLLATE {$COLLATE_TEXT} NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `key_object` (`objectPHID`,`extensionKey`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + CREATE TABLE `search_namedquery` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `userPHID` varbinary(64) NOT NULL, @@ -2660,6 +2837,43 @@ CREATE TABLE `search_namedquery` ( UNIQUE KEY `key_userquery` (`userPHID`,`engineClassName`,`queryKey`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; +CREATE TABLE `search_profilepanelconfiguration` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `phid` varbinary(64) NOT NULL, + `profilePHID` varbinary(64) NOT NULL, + `panelKey` varchar(64) COLLATE {$COLLATE_TEXT} NOT NULL, + `builtinKey` varchar(64) COLLATE {$COLLATE_TEXT} DEFAULT NULL, + `panelOrder` int(10) unsigned DEFAULT NULL, + `visibility` varchar(32) COLLATE {$COLLATE_TEXT} NOT NULL, + `panelProperties` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `dateCreated` int(10) unsigned NOT NULL, + `dateModified` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `key_phid` (`phid`), + KEY `key_profile` (`profilePHID`,`panelOrder`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + +CREATE TABLE `search_profilepanelconfigurationtransaction` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `phid` varbinary(64) NOT NULL, + `authorPHID` varbinary(64) NOT NULL, + `objectPHID` varbinary(64) NOT NULL, + `viewPolicy` varbinary(64) NOT NULL, + `editPolicy` varbinary(64) NOT NULL, + `commentPHID` varbinary(64) DEFAULT NULL, + `commentVersion` int(10) unsigned NOT NULL, + `transactionType` varchar(32) COLLATE {$COLLATE_TEXT} NOT NULL, + `oldValue` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `newValue` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `contentSource` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `metadata` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `dateCreated` int(10) unsigned NOT NULL, + `dateModified` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `key_phid` (`phid`), + KEY `key_object` (`objectPHID`) +) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; + CREATE TABLE `search_savedquery` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `engineClassName` varchar(255) COLLATE {$COLLATE_TEXT} NOT NULL, @@ -3144,15 +3358,17 @@ CREATE TABLE `worker_triggerevent` ( KEY `key_next` (`nextEventEpoch`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; -CREATE DATABASE /*!32312 IF NOT EXISTS*/ `{$NAMESPACE}_xhpastview` /*!40100 DEFAULT CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} */; +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `{$NAMESPACE}_xhpast` /*!40100 DEFAULT CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} */; -USE `{$NAMESPACE}_xhpastview`; +USE `{$NAMESPACE}_xhpast`; -CREATE TABLE `xhpastview_parsetree` ( +CREATE TABLE `xhpast_parsetree` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `authorPHID` varbinary(64) DEFAULT NULL, `input` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `returnCode` int(10) NOT NULL, `stdout` longtext COLLATE {$COLLATE_TEXT} NOT NULL, + `stderr` longtext COLLATE {$COLLATE_TEXT} NOT NULL, `dateCreated` int(10) unsigned NOT NULL, `dateModified` int(10) unsigned NOT NULL, PRIMARY KEY (`id`) @@ -4286,6 +4502,7 @@ CREATE TABLE `auth_providerconfigtransaction` ( CREATE TABLE `auth_sshkey` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `phid` varbinary(64) NOT NULL, `objectPHID` varbinary(64) NOT NULL, `name` varchar(255) COLLATE {$COLLATE_TEXT} NOT NULL, `keyType` varchar(255) COLLATE {$COLLATE_TEXT} NOT NULL, @@ -4297,6 +4514,7 @@ CREATE TABLE `auth_sshkey` ( `isTrusted` tinyint(1) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `key_unique` (`keyIndex`), + UNIQUE KEY `key_phid` (`phid`), KEY `key_object` (`objectPHID`) ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT}; @@ -5471,6 +5689,7 @@ CREATE TABLE `phurl_url` ( `dateModified` int(10) unsigned NOT NULL, `alias` varchar(64) CHARACTER SET {$CHARSET_SORT} COLLATE {$COLLATE_SORT} DEFAULT NULL, `authorPHID` varbinary(64) NOT NULL, + `mailKey` binary(20) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `key_phid` (`phid`), UNIQUE KEY `key_instance` (`alias`), From 0a554c2ed535cb57bd31c10e96461ebf2bee6d06 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 19 Jan 2016 10:35:32 -0800 Subject: [PATCH 34/66] Allow profile menus to be collapsed and expanded Summary: Ref T10054. I think this gets everything except: - circles on icons; - I spent ~15 minutes poking at animations but wasn't able to get anything that looked reasonable whatsoever. Test Plan: - Collapsed menus. - Expanded menus. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15056 --- resources/celerity/map.php | 13 +- .../CelerityDefaultPostprocessor.php | 17 ++- .../PhabricatorProjectController.php | 31 +++-- .../PhabricatorProjectPanelController.php | 9 +- .../engine/PhabricatorProfilePanelEngine.php | 130 +++++++++++++++--- .../storage/PhabricatorUserPreferences.php | 2 + src/view/layout/AphrontSideNavFilterView.php | 10 +- src/view/layout/PHUIApplicationMenuView.php | 5 +- src/view/phui/PHUIListItemView.php | 23 ++++ webroot/rsrc/css/phui/phui-profile-menu.css | 103 +++++++++++++- .../js/phui/behavior-phui-profile-menu.js | 28 ++++ 11 files changed, 329 insertions(+), 42 deletions(-) create mode 100644 webroot/rsrc/js/phui/behavior-phui-profile-menu.js diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 9188e2343f..6070c0a247 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => 'c61091b0', + 'core.pkg.css' => '7fce81fc', 'core.pkg.js' => '573e6664', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -143,7 +143,7 @@ return array( 'rsrc/css/phui/phui-object-item-list-view.css' => '26c30d3f', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', - 'rsrc/css/phui/phui-profile-menu.css' => 'a26fa598', + 'rsrc/css/phui/phui-profile-menu.css' => '72d69773', 'rsrc/css/phui/phui-property-list-view.css' => '27b2849e', 'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591', 'rsrc/css/phui/phui-spacing.css' => '042804d6', @@ -500,6 +500,7 @@ return array( 'rsrc/js/core/phtize.js' => 'd254d646', 'rsrc/js/phui/behavior-phui-dropdown-menu.js' => '54733475', 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', + 'rsrc/js/phui/behavior-phui-profile-menu.js' => 'bf2c93d6', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', 'rsrc/js/phuix/PHUIXAutocomplete.js' => '21dc9144', @@ -648,6 +649,7 @@ return array( 'javelin-behavior-pholio-mock-view' => 'fbe497e7', 'javelin-behavior-phui-dropdown-menu' => '54733475', 'javelin-behavior-phui-object-box-tabs' => '2bfa2836', + 'javelin-behavior-phui-profile-menu' => 'bf2c93d6', 'javelin-behavior-policy-control' => 'ae45872f', 'javelin-behavior-policy-rule-editor' => '5e9f347c', 'javelin-behavior-project-boards' => 'ba4fa35c', @@ -817,7 +819,7 @@ return array( 'phui-object-item-list-view-css' => '26c30d3f', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', - 'phui-profile-menu-css' => 'a26fa598', + 'phui-profile-menu-css' => '72d69773', 'phui-property-list-view-css' => '27b2849e', 'phui-remarkup-preview-css' => '1a8f2591', 'phui-spacing-css' => '042804d6', @@ -1772,6 +1774,11 @@ return array( 'javelin-util', 'javelin-request', ), + 'bf2c93d6' => array( + 'javelin-behavior', + 'javelin-stratcom', + 'javelin-dom', + ), 'bff6884b' => array( 'javelin-install', 'javelin-dom', diff --git a/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php b/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php index 6244e8554e..e6212c4eb0 100644 --- a/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php +++ b/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php @@ -191,14 +191,29 @@ final class CelerityDefaultPostprocessor // Background color for "dark" themes. 'page.background.dark' => '#ebecee', + // NOTE: We can't just do these with an alpha channel because the + // fixed items in the footer may render on top of other items, so the + // backgrounds must be opaque. + + // This is the base background color. 'menu.profile.background' => '#525868', + + // This is premultiplied 7.5% alpha. + 'menu.profile.background.hover' => '#4c5160', + + // This is premultiplied 15% alpha. + 'menu.profile.background.selected' => '#464b59', + 'menu.profile.text' => '#c6c7cb', 'menu.profile.text.selected' => '#ffffff', - 'menu.profile.icon' => '#ffffff', 'menu.profile.icon.disabled' => '#b9bcc2', 'menu.main.height' => '44px', + 'menu.profile.width' => '240px', + 'menu.profile.width.collapsed' => '80px', + 'menu.profile.item.height' => '46px', + ); } diff --git a/src/applications/project/controller/PhabricatorProjectController.php b/src/applications/project/controller/PhabricatorProjectController.php index 56f5774391..ebb3b31a2a 100644 --- a/src/applications/project/controller/PhabricatorProjectController.php +++ b/src/applications/project/controller/PhabricatorProjectController.php @@ -4,6 +4,7 @@ abstract class PhabricatorProjectController extends PhabricatorController { private $project; private $profileMenu; + private $profilePanelEngine; protected function setProject(PhabricatorProject $project) { $this->project = $project; @@ -98,14 +99,8 @@ abstract class PhabricatorProjectController extends PhabricatorController { protected function getProfileMenu() { if (!$this->profileMenu) { - $project = $this->getProject(); - if ($project) { - $viewer = $this->getViewer(); - - $engine = id(new PhabricatorProjectProfilePanelEngine()) - ->setViewer($viewer) - ->setProfileObject($project); - + $engine = $this->getProfilePanelEngine(); + if ($engine) { $this->profileMenu = $engine->buildNavigation(); } } @@ -131,4 +126,24 @@ abstract class PhabricatorProjectController extends PhabricatorController { return $crumbs; } + protected function getProfilePanelEngine() { + if (!$this->profilePanelEngine) { + $viewer = $this->getViewer(); + $project = $this->getProject(); + if ($project) { + $engine = id(new PhabricatorProjectProfilePanelEngine()) + ->setViewer($viewer) + ->setProfileObject($project); + $this->profilePanelEngine = $engine; + } + } + return $this->profilePanelEngine; + } + + protected function setProfilePanelEngine( + PhabricatorProjectProfilePanelEngine $engine) { + $this->profilePanelEngine = $engine; + return $this; + } + } diff --git a/src/applications/project/controller/PhabricatorProjectPanelController.php b/src/applications/project/controller/PhabricatorProjectPanelController.php index 49ed00f34e..d20b5b9828 100644 --- a/src/applications/project/controller/PhabricatorProjectPanelController.php +++ b/src/applications/project/controller/PhabricatorProjectPanelController.php @@ -12,10 +12,13 @@ final class PhabricatorProjectPanelController $viewer = $this->getViewer(); $project = $this->getProject(); - return id(new PhabricatorProjectProfilePanelEngine()) + $engine = id(new PhabricatorProjectProfilePanelEngine()) ->setProfileObject($project) - ->setController($this) - ->buildResponse(); + ->setController($this); + + $this->setProfilePanelEngine($engine); + + return $engine->buildResponse(); } } diff --git a/src/applications/search/engine/PhabricatorProfilePanelEngine.php b/src/applications/search/engine/PhabricatorProfilePanelEngine.php index 1cf03b9bac..8e11d43e32 100644 --- a/src/applications/search/engine/PhabricatorProfilePanelEngine.php +++ b/src/applications/search/engine/PhabricatorProfilePanelEngine.php @@ -6,6 +6,7 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { private $profileObject; private $panels; private $controller; + private $navigation; public function setViewer(PhabricatorUser $viewer) { $this->viewer = $viewer; @@ -147,6 +148,10 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { } public function buildNavigation() { + if ($this->navigation) { + return $this->navigation; + } + $nav = id(new AphrontSideNavFilterView()) ->setIsProfileMenu(true) ->setBaseURI(new PhutilURI($this->getPanelURI(''))); @@ -185,14 +190,15 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { } } - $configure_item = $this->newConfigureMenuItem(); - if ($configure_item) { - $nav->addMenuItem($configure_item); + $more_items = $this->newAutomaticMenuItems($nav); + foreach ($more_items as $item) { + $nav->addMenuItem($item); } $nav->selectFilter(null); - return $nav; + $this->navigation = $nav; + return $this->navigation; } private function getPanels() { @@ -301,26 +307,112 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { } } - private function newConfigureMenuItem() { - if (!$this->isPanelEngineConfigurable()) { - return null; + private function newAutomaticMenuItems(AphrontSideNavFilterView $nav) { + $items = array(); + + // NOTE: We're adding a spacer item for the fixed footer, so that if the + // menu taller than the page content you can still scroll down the page far + // enough to access the last item without the content being obscured by the + // fixed items. + $items[] = id(new PHUIListItemView()) + ->setHideInApplicationMenu(true) + ->addClass('phui-profile-menu-spacer'); + + if ($this->isPanelEngineConfigurable()) { + $viewer = $this->getViewer(); + $object = $this->getProfileObject(); + + $can_edit = PhabricatorPolicyFilter::hasCapability( + $viewer, + $object, + PhabricatorPolicyCapability::CAN_EDIT); + + $expanded_edit_icon = id(new PHUIIconView()) + ->addClass('phui-list-item-icon') + ->addClass('phui-profile-menu-visible-when-expanded') + ->setIconFont('fa-pencil'); + + $collapsed_edit_icon = id(new PHUIIconView()) + ->addClass('phui-list-item-icon') + ->addClass('phui-profile-menu-visible-when-collapsed') + ->setIconFont('fa-pencil') + ->addSigil('has-tooltip') + ->setMetadata( + array( + 'tip' => pht('Edit Menu'), + 'align' => 'E', + )); + + $items[] = id(new PHUIListItemView()) + ->setName('Edit Menu') + ->setKey('panel.configure') + ->addIcon($expanded_edit_icon) + ->addIcon($collapsed_edit_icon) + ->addClass('phui-profile-menu-footer') + ->addClass('phui-profile-menu-footer-1') + ->setHref($this->getPanelURI('configure/')) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit); } + $collapse_id = celerity_generate_unique_node_id(); + $viewer = $this->getViewer(); - $object = $this->getProfileObject(); - $can_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - $object, - PhabricatorPolicyCapability::CAN_EDIT); + $collapse_key = + PhabricatorUserPreferences::PREFERENCE_PROFILE_MENU_COLLAPSED; - return id(new PHUIListItemView()) - ->setName('Configure Menu') - ->setKey('panel.configure') - ->setIcon('fa-gear') - ->setHref($this->getPanelURI('configure/')) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit); + $preferences = $viewer->loadPreferences(); + $is_collapsed = $preferences->getPreference($collapse_key, false); + + if ($is_collapsed) { + $nav->addClass('phui-profile-menu-collapsed'); + } else { + $nav->addClass('phui-profile-menu-expanded'); + } + + if ($viewer->isLoggedIn()) { + $settings_uri = '/settings/adjust/?key='.$collapse_key; + } else { + $settings_uri = null; + } + + Javelin::initBehavior( + 'phui-profile-menu', + array( + 'menuID' => $nav->getMainID(), + 'collapseID' => $collapse_id, + 'isCollapsed' => $is_collapsed, + 'settingsURI' => $settings_uri, + )); + + $collapse_icon = id(new PHUIIconView()) + ->addClass('phui-list-item-icon') + ->addClass('phui-profile-menu-visible-when-expanded') + ->setIconFont('fa-angle-left'); + + $expand_icon = id(new PHUIIconView()) + ->addClass('phui-list-item-icon') + ->addClass('phui-profile-menu-visible-when-collapsed') + ->addSigil('has-tooltip') + ->setMetadata( + array( + 'tip' => pht('Expand'), + 'align' => 'E', + )) + ->setIconFont('fa-angle-right'); + + $items[] = id(new PHUIListItemView()) + ->setName('Collapse') + ->addIcon($collapse_icon) + ->addIcon($expand_icon) + ->setID($collapse_id) + ->addClass('phui-profile-menu-footer') + ->addClass('phui-profile-menu-footer-2') + ->setHideInApplicationMenu(true) + ->setHref('#'); + + return $items; } public function getConfigureURI() { diff --git a/src/applications/settings/storage/PhabricatorUserPreferences.php b/src/applications/settings/storage/PhabricatorUserPreferences.php index 1527f2844d..53c080ec88 100644 --- a/src/applications/settings/storage/PhabricatorUserPreferences.php +++ b/src/applications/settings/storage/PhabricatorUserPreferences.php @@ -41,6 +41,8 @@ final class PhabricatorUserPreferences extends PhabricatorUserDAO { const PREFERENCE_RESOURCE_POSTPROCESSOR = 'resource-postprocessor'; const PREFERENCE_DESKTOP_NOTIFICATIONS = 'desktop-notifications'; + const PREFERENCE_PROFILE_MENU_COLLAPSED = 'profile-menu.collapsed'; + // These are in an unusual order for historic reasons. const MAILTAG_PREFERENCE_NOTIFY = 0; const MAILTAG_PREFERENCE_EMAIL = 1; diff --git a/src/view/layout/AphrontSideNavFilterView.php b/src/view/layout/AphrontSideNavFilterView.php index 5040f81efc..3a267510f0 100644 --- a/src/view/layout/AphrontSideNavFilterView.php +++ b/src/view/layout/AphrontSideNavFilterView.php @@ -27,6 +27,7 @@ final class AphrontSideNavFilterView extends AphrontView { private $crumbs; private $classes = array(); private $menuID; + private $mainID; private $isProfileMenu; private $footer = array(); @@ -168,6 +169,13 @@ final class AphrontSideNavFilterView extends AphrontView { return $this; } + public function getMainID() { + if (!$this->mainID) { + $this->mainID = celerity_generate_unique_node_id(); + } + return $this->mainID; + } + public function render() { if ($this->menu->getItems()) { if (!$this->baseURI) { @@ -212,7 +220,7 @@ final class AphrontSideNavFilterView extends AphrontView { $local_id = null; $background_id = null; $local_menu = null; - $main_id = celerity_generate_unique_node_id(); + $main_id = $this->getMainID(); if ($this->flexible) { $drag_id = celerity_generate_unique_node_id(); diff --git a/src/view/layout/PHUIApplicationMenuView.php b/src/view/layout/PHUIApplicationMenuView.php index f542674de9..164f897550 100644 --- a/src/view/layout/PHUIApplicationMenuView.php +++ b/src/view/layout/PHUIApplicationMenuView.php @@ -75,8 +75,11 @@ final class PHUIApplicationMenuView extends Phobject { $profile_menu = $this->getProfileMenu(); if ($profile_menu) { foreach ($profile_menu->getMenu()->getItems() as $item) { + if ($item->getHideInApplicationMenu()) { + continue; + } + $item = clone $item; - $item->setRenderNameAsTooltip(false); $view->addMenuItem($item); } } diff --git a/src/view/phui/PHUIListItemView.php b/src/view/phui/PHUIListItemView.php index 45c2b56128..1173319f4e 100644 --- a/src/view/phui/PHUIListItemView.php +++ b/src/view/phui/PHUIListItemView.php @@ -28,6 +28,17 @@ final class PHUIListItemView extends AphrontTagView { private $aural; private $profileImage; private $indented; + private $hideInApplicationMenu; + private $icons = array(); + + public function setHideInApplicationMenu($hide) { + $this->hideInApplicationMenu = $hide; + return $this; + } + + public function getHideInApplicationMenu() { + return $this->hideInApplicationMenu; + } public function setDropdownMenu(PhabricatorActionListView $actions) { Javelin::initBehavior('phui-dropdown-menu'); @@ -150,6 +161,15 @@ final class PHUIListItemView extends AphrontTagView { return $this; } + public function addIcon(PHUIIconView $icon) { + $this->icons[] = $icon; + return $this; + } + + public function getIcons() { + return $this->icons; + } + protected function getTagName() { return 'li'; } @@ -274,6 +294,8 @@ final class PHUIListItemView extends AphrontTagView { $classes[] = 'phui-list-item-indented'; } + $icons = $this->getIcons(); + return javelin_tag( $this->href ? 'a' : 'div', array( @@ -285,6 +307,7 @@ final class PHUIListItemView extends AphrontTagView { array( $aural, $icon, + $icons, $this->renderChildren(), $name, )); diff --git a/webroot/rsrc/css/phui/phui-profile-menu.css b/webroot/rsrc/css/phui/phui-profile-menu.css index 1434475ef3..b2475a5457 100644 --- a/webroot/rsrc/css/phui/phui-profile-menu.css +++ b/webroot/rsrc/css/phui/phui-profile-menu.css @@ -16,12 +16,17 @@ display: table-cell; position: relative; vertical-align: top; - width: 240px; - max-width: 240px; + width: {$menu.profile.width}; + max-width: {$menu.profile.width}; margin-top: 0; overflow: hidden; } +.device-desktop .phui-profile-menu-collapsed .phabricator-nav-local { + width: {$menu.profile.width.collapsed}; + max-width: {$menu.profile.width.collapsed}; +} + .device-desktop .phui-profile-menu .phabricator-nav-content { display: table-cell; margin-left: 0; @@ -47,23 +52,47 @@ line-height: 22px; overflow: hidden; text-overflow: ellipsis; + + /* NOTE: We must have an opaque background on these items so the footer + items appear opaque when the render over normal items. */ + background: {$menu.profile.background}; } .phui-profile-menu .phabricator-side-menu .phui-list-item-icon, .phui-profile-menu .phabricator-side-menu .phui-list-item-href .phui-icon-view { position: absolute; - left: 13px; top: 12px; + left: 13px; font-size: 20px; width: 22px; height: 22px; line-height: 22px; text-align: center; - color: {$menu.profile.icon}; + color: {$menu.profile.text}; background-size: 100%; } +.phui-profile-menu .phui-profile-menu-collapsed .phui-list-item-href { + text-align: center; + padding: 42px 8px 12px; + font-size: 11px; + line-height: 13px; +} + +.phui-profile-menu .phui-profile-menu-collapsed .phui-list-item-name { + display: block; + overflow: hidden; + text-overflow: ellipsis; +} + +.phui-profile-menu .phui-profile-menu-collapsed .phui-list-item-icon, +.phui-profile-menu .phui-profile-menu-collapsed + .phui-list-item-href .phui-icon-view { + top: 10px; + left: 29px; +} + .phui-profile-menu .phabricator-side-menu .phui-list-item-disabled .phui-list-item-icon { @@ -76,7 +105,16 @@ .device-desktop .phui-profile-menu .phabricator-side-menu .phui-list-item-href:hover { - background-color: rgba(0, 0, 0, 0.075); + background-color: {$menu.profile.background.hover}; + color: {$menu.profile.text.selected}; +} + +.phui-profile-menu .phabricator-side-menu + .phui-list-item-selected + .phui-list-item-icon, +.device-desktop .phui-profile-menu .phabricator-side-menu + .phui-list-item-href:hover + .phui-list-item-icon { color: {$menu.profile.text.selected}; } @@ -85,7 +123,7 @@ .device-desktop .phui-profile-menu .phabricator-side-menu .phui-list-item-selected .phui-list-item-href:hover { - background-color: rgba(0, 0, 0, 0.150); + background-color: {$menu.profile.background.selected}; color: {$menu.profile.text.selected}; } @@ -107,3 +145,56 @@ font-size: 12px; color: {$menu.profile.text}; } + +.phui-profile-menu .phabricator-side-menu .phui-profile-menu-spacer { + box-sizing: border-box; + height: {$menu.profile.item.height}; +} + +.phui-profile-menu .phabricator-side-menu .phui-profile-menu-footer { + position: fixed; + box-sizing: border-box; + width: {$menu.profile.width}; + bottom: 0px; +} + +.phui-profile-menu .phabricator-side-menu .phui-profile-menu-footer-1 { + left: 0; +} + +.phui-profile-menu .phabricator-side-menu .phui-profile-menu-footer-2 { + left: 120px; +} + +.phui-profile-menu .phui-profile-menu-collapsed .phui-profile-menu-footer { + width: 40px; + height: {$menu.profile.item.height}; + bottom: 0px; +} + +.phui-profile-menu .phui-profile-menu-collapsed .phui-profile-menu-footer-1 { + left: 0; +} + +.phui-profile-menu .phui-profile-menu-collapsed .phui-profile-menu-footer-2 { + left: 40px; +} + + +.phui-profile-menu .phui-profile-menu-collapsed .phui-profile-menu-footer + .phui-list-item-name { + display: none; +} + +.phui-profile-menu .phui-profile-menu-collapsed .phui-profile-menu-footer + .phui-list-item-icon { + top: 10px; + left: 10px; +} + +.phui-profile-menu .phui-profile-menu-expanded + .phui-profile-menu-visible-when-collapsed, +.phui-profile-menu .phui-profile-menu-collapsed + .phui-profile-menu-visible-when-expanded { + display: none; +} diff --git a/webroot/rsrc/js/phui/behavior-phui-profile-menu.js b/webroot/rsrc/js/phui/behavior-phui-profile-menu.js new file mode 100644 index 0000000000..bd305b5cf2 --- /dev/null +++ b/webroot/rsrc/js/phui/behavior-phui-profile-menu.js @@ -0,0 +1,28 @@ +/** + * @provides javelin-behavior-phui-profile-menu + * @requires javelin-behavior + * javelin-stratcom + * javelin-dom + */ + +JX.behavior('phui-profile-menu', function(config) { + var menu_node = JX.$(config.menuID); + var collapse_node = JX.$(config.collapseID); + + var is_collapsed = config.isCollapsed; + + JX.DOM.listen(collapse_node, 'click', null, function(e) { + is_collapsed = !is_collapsed; + JX.DOM.alterClass(menu_node, 'phui-profile-menu-collapsed', is_collapsed); + JX.DOM.alterClass(menu_node, 'phui-profile-menu-expanded', !is_collapsed); + + if (config.settingsURI) { + new JX.Request(config.settingsURI) + .setData({value: (is_collapsed ? 1 : 0)}) + .send(); + } + + e.kill(); + }); + +}); From b1c77f6527abfc4dd4ab035a1439be9df7bbb3c5 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Tue, 19 Jan 2016 13:20:28 -0800 Subject: [PATCH 35/66] Add new Project icons, 200px Summary: Adds 64? or so 200px (retina) icons for better Project organization. Test Plan: Edit Picture -> Choose Icon -> Retro Camera -> Save. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D15057 --- resources/builtin/projects/fa-android.png | Bin 0 -> 1663 bytes resources/builtin/projects/fa-apple.png | Bin 0 -> 1492 bytes resources/builtin/projects/fa-beer.png | Bin 0 -> 719 bytes resources/builtin/projects/fa-bomb.png | Bin 0 -> 1876 bytes resources/builtin/projects/fa-book.png | Bin 0 -> 1774 bytes resources/builtin/projects/fa-briefcase.png | Bin 406 -> 721 bytes resources/builtin/projects/fa-bug.png | Bin 851 -> 1577 bytes resources/builtin/projects/fa-building.png | Bin 716 -> 1088 bytes resources/builtin/projects/fa-calendar.png | Bin 462 -> 954 bytes .../builtin/projects/fa-camera-retro.png | Bin 0 -> 1477 bytes resources/builtin/projects/fa-chrome.png | Bin 0 -> 2667 bytes resources/builtin/projects/fa-cloud.png | Bin 567 -> 1083 bytes resources/builtin/projects/fa-coffee.png | Bin 0 -> 958 bytes resources/builtin/projects/fa-comments.png | Bin 0 -> 1739 bytes resources/builtin/projects/fa-credit-card.png | Bin 348 -> 643 bytes resources/builtin/projects/fa-database.png | Bin 0 -> 2146 bytes resources/builtin/projects/fa-desktop.png | Bin 0 -> 760 bytes resources/builtin/projects/fa-diamond.png | Bin 0 -> 2065 bytes resources/builtin/projects/fa-empire.png | Bin 0 -> 4598 bytes resources/builtin/projects/fa-envelope.png | Bin 831 -> 1446 bytes resources/builtin/projects/fa-facebook.png | Bin 0 -> 1109 bytes resources/builtin/projects/fa-fax.png | Bin 0 -> 1304 bytes resources/builtin/projects/fa-film.png | Bin 0 -> 1276 bytes resources/builtin/projects/fa-firefox.png | Bin 0 -> 2300 bytes .../builtin/projects/fa-flag-checkered.png | Bin 1011 -> 1896 bytes resources/builtin/projects/fa-flask.png | Bin 692 -> 1223 bytes resources/builtin/projects/fa-folder.png | Bin 375 -> 752 bytes resources/builtin/projects/fa-gamepad.png | Bin 0 -> 1375 bytes resources/builtin/projects/fa-gears.png | Bin 0 -> 2691 bytes resources/builtin/projects/fa-google.png | Bin 0 -> 1851 bytes resources/builtin/projects/fa-group.png | Bin 0 -> 2411 bytes .../builtin/projects/fa-hand-peace-o.png | Bin 0 -> 2680 bytes resources/builtin/projects/fa-hashtag.png | Bin 0 -> 1195 bytes resources/builtin/projects/fa-heart.png | Bin 0 -> 1343 bytes .../builtin/projects/fa-internet-explorer.png | Bin 0 -> 2479 bytes resources/builtin/projects/fa-key.png | Bin 0 -> 1792 bytes resources/builtin/projects/fa-legal.png | Bin 0 -> 1133 bytes resources/builtin/projects/fa-linux.png | Bin 0 -> 3424 bytes resources/builtin/projects/fa-lock.png | Bin 462 -> 1128 bytes resources/builtin/projects/fa-microphone.png | Bin 0 -> 1649 bytes resources/builtin/projects/fa-mobile.png | Bin 0 -> 840 bytes resources/builtin/projects/fa-money.png | Bin 0 -> 1279 bytes resources/builtin/projects/fa-phone.png | Bin 0 -> 1499 bytes resources/builtin/projects/fa-pie-chart.png | Bin 0 -> 1587 bytes resources/builtin/projects/fa-rebel.png | Bin 0 -> 2394 bytes .../builtin/projects/fa-reddit-alien.png | Bin 0 -> 2238 bytes resources/builtin/projects/fa-safari.png | Bin 0 -> 3632 bytes resources/builtin/projects/fa-search.png | Bin 0 -> 1773 bytes resources/builtin/projects/fa-server.png | Bin 0 -> 714 bytes .../builtin/projects/fa-shopping-cart.png | Bin 0 -> 1212 bytes resources/builtin/projects/fa-sitemap.png | Bin 0 -> 912 bytes resources/builtin/projects/fa-star.png | Bin 0 -> 1574 bytes resources/builtin/projects/fa-tablet.png | Bin 0 -> 761 bytes resources/builtin/projects/fa-tag.png | Bin 0 -> 1070 bytes resources/builtin/projects/fa-tags.png | Bin 1009 -> 1302 bytes resources/builtin/projects/fa-trash-o.png | Bin 460 -> 1714 bytes resources/builtin/projects/fa-truck.png | Bin 553 -> 1326 bytes resources/builtin/projects/fa-twitter.png | Bin 0 -> 1634 bytes resources/builtin/projects/fa-umbrella.png | Bin 820 -> 1584 bytes resources/builtin/projects/fa-university.png | Bin 0 -> 698 bytes resources/builtin/projects/fa-user-secret.png | Bin 0 -> 2108 bytes resources/builtin/projects/fa-user.png | Bin 0 -> 1432 bytes resources/builtin/projects/fa-users.png | Bin 1284 -> 0 bytes resources/builtin/projects/fa-warning.png | Bin 0 -> 1415 bytes resources/builtin/projects/fa-wheelchair.png | Bin 0 -> 1905 bytes resources/builtin/projects/fa-windows.png | Bin 0 -> 854 bytes resources/celerity/map.php | 4 +- ...PhabricatorFilesComposeIconBuiltinFile.php | 115 ++++++++---------- .../css/application/people/people-profile.css | 2 +- 69 files changed, 57 insertions(+), 64 deletions(-) create mode 100644 resources/builtin/projects/fa-android.png create mode 100644 resources/builtin/projects/fa-apple.png create mode 100644 resources/builtin/projects/fa-beer.png create mode 100644 resources/builtin/projects/fa-bomb.png create mode 100644 resources/builtin/projects/fa-book.png create mode 100644 resources/builtin/projects/fa-camera-retro.png create mode 100644 resources/builtin/projects/fa-chrome.png create mode 100644 resources/builtin/projects/fa-coffee.png create mode 100644 resources/builtin/projects/fa-comments.png create mode 100644 resources/builtin/projects/fa-database.png create mode 100644 resources/builtin/projects/fa-desktop.png create mode 100644 resources/builtin/projects/fa-diamond.png create mode 100644 resources/builtin/projects/fa-empire.png create mode 100644 resources/builtin/projects/fa-facebook.png create mode 100644 resources/builtin/projects/fa-fax.png create mode 100644 resources/builtin/projects/fa-film.png create mode 100644 resources/builtin/projects/fa-firefox.png create mode 100644 resources/builtin/projects/fa-gamepad.png create mode 100644 resources/builtin/projects/fa-gears.png create mode 100644 resources/builtin/projects/fa-google.png create mode 100644 resources/builtin/projects/fa-group.png create mode 100644 resources/builtin/projects/fa-hand-peace-o.png create mode 100644 resources/builtin/projects/fa-hashtag.png create mode 100644 resources/builtin/projects/fa-heart.png create mode 100644 resources/builtin/projects/fa-internet-explorer.png create mode 100644 resources/builtin/projects/fa-key.png create mode 100644 resources/builtin/projects/fa-legal.png create mode 100644 resources/builtin/projects/fa-linux.png create mode 100644 resources/builtin/projects/fa-microphone.png create mode 100644 resources/builtin/projects/fa-mobile.png create mode 100644 resources/builtin/projects/fa-money.png create mode 100644 resources/builtin/projects/fa-phone.png create mode 100644 resources/builtin/projects/fa-pie-chart.png create mode 100644 resources/builtin/projects/fa-rebel.png create mode 100644 resources/builtin/projects/fa-reddit-alien.png create mode 100644 resources/builtin/projects/fa-safari.png create mode 100644 resources/builtin/projects/fa-search.png create mode 100644 resources/builtin/projects/fa-server.png create mode 100644 resources/builtin/projects/fa-shopping-cart.png create mode 100644 resources/builtin/projects/fa-sitemap.png create mode 100644 resources/builtin/projects/fa-star.png create mode 100644 resources/builtin/projects/fa-tablet.png create mode 100644 resources/builtin/projects/fa-tag.png create mode 100644 resources/builtin/projects/fa-twitter.png create mode 100644 resources/builtin/projects/fa-university.png create mode 100644 resources/builtin/projects/fa-user-secret.png create mode 100644 resources/builtin/projects/fa-user.png delete mode 100644 resources/builtin/projects/fa-users.png create mode 100644 resources/builtin/projects/fa-warning.png create mode 100644 resources/builtin/projects/fa-wheelchair.png create mode 100644 resources/builtin/projects/fa-windows.png diff --git a/resources/builtin/projects/fa-android.png b/resources/builtin/projects/fa-android.png new file mode 100644 index 0000000000000000000000000000000000000000..db56162683c6ea53fc08e8a6f064dc714d493701 GIT binary patch literal 1663 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 M^GEnGd=l^d2hg5}T>t<8 literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-book.png b/resources/builtin/projects/fa-book.png new file mode 100644 index 0000000000000000000000000000000000000000..f6bda5d61c048b2f86a14306f2867c69e272e807 GIT binary patch literal 1774 zcmVj1g>Kq>Y+VW;RTEr zdW&u7fE+&)j*9pI4?8(M+vhapuijX3hb(5jY3Ak&C}bkT<+Gt!8G^wS5VFATA|YQvEQU#Nl9 z)&^ub47CdA!qJ%=M?%$F9pz!jwL}w+9QZ^Jq^2eyM_}lcSr3lF3UD0OwOMQE)kYJL z0x%)<3~R7F5^Z+e+0U&BNIWEt#u1lu9wyD`p0*`nA_R`Qk!Lp|X-)&R0ZH?D8wd-M zW>r)dj;t`w>K?sQGU-?3ld}DER0shiZ{*pPNSf0e5o0}COc>&f<3R>wH#%unRYV{L z_fST=%Va?G**Un0#z7yv`B`p&iM4!+~)1EWA$#j#Bh zBJ=r;qrD0oXDy?9`>)6s{2miY4{;|Fy>ZN^v)yAxwNA(4ub9oWiE`SAf=+D_`J6jk zO8E`sL}(zDJgl%ivpjiAaK#6H16dgo$F2;>@levNMv2em6e5@UKEoR5dvB{#$y0m{ zp(UX!9<4%tKjM*R*!XLkbFg1_#cP`MuJrPSwNyTEO^7_?{~CREC?HiL&oA58Hs_#* z5ZRi058Z<*DO!JRa}E|09=CyPp>W*EfIXTgU)P+27!q>+egkO)6G}NEo?q?%+U6XT zl#PA91KA#SlN7TtJR+?^>en~tV3ZJ9gx=IZpnI0FJ^S~zl=nO7XrTbeAm?MHX88ZY zy21}cZq7j$A+jQU`!j(o%{e$nXl%e71wiIF8-KR&f6y5uRu0fWh-}1fYhaLA>cl1? zGMn!=9V8UskehP?A@U-BA0dO9Ivanw`hNUUnhGFtbIx=jGQZz<;v7(cah|WZ!IIdBitqu`20CHN;JjU__Lh%U>W}A zoK|Fq@{5ZmP0cw6$c#UTDFL#<+4ysW_xL{k=A0UI$6=xfjN;~;C3MGOqLbd{9K?{2 zcHBvu5BTrSK`DacFja0!*_v}k(;0uzTm_C7YK%WPqXNiiXXDRozj5S+QK3@K#-GZ5 z0~x^&!`>r^3uH&kAix(DK$hBE{A34cpb0+=d#Ml&g~-N!*Rbv>0U|f&Y!)K3`wXO- z5*$aIYuK0leqmiz0;G-eoj^T&#!*WJ4106V4617-5vbWmf1twngI+L7G{|{NVI0Hy zoL|M9ZR2J9eO+BwgX0ro^u`~|fl;Hm;s|pIkt==0QAP_4d#Mm@h;CAs+wPSae+~(; zS$qXz6lslo%_Noa2iFw=sp7okZR;IcR`j@8Gq1DxwSe#s=S)_6-Zy@y&$E9 z$RR!hnW+TFsSvN^Vm<@eujhjHNQa zZJu>}7uk$I^)&e0ZFO5@7oxZOy^p?#9>*5ML!Ecs#BU%MsbL&Ih5sDg76RjsaJLMT zzTg>7VFmi33bMFQSmfClORaYo3Ly3i{XbNajX!LMh~HBH!(M|Z;Cs@0XzD!Sjj?KFNIVo`AwN9x5w zUy8+gjdC593!xRJ zVGl0ij@LSi4VZ%Zv{T$)+k*oF000mKK>uHNBNYGu00000000000001paFG2aBZEA$ QUjP6A07*qoM6N<$f*E`)r~m)} literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-briefcase.png b/resources/builtin/projects/fa-briefcase.png index 2923f59af98f789abb0a1619fda3f49ff7a2964e..afa70e2a3a92b8601a99c149625b4834d83747b5 100644 GIT binary patch literal 721 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k1xT_7rin5zFwO9EaSW+oe0yu_J{4DnqYrm= z9oCVY^x)mQclr&&3-dPsnR(MQoO33!l&>zga>?*l-n%(AeBb-|=Y78a40R2@#s)MC z2`F^mRG%Ds!!A5;h8MK7JjKKZ>mv3GLop^}@k zZY|Jl&D^B9HE^<1_&V?0D_dLF0lLP?}C9$OO&D`Lk(7e;O%)d>xUN+vDe$00At(TYY7;m^;6zX^GUTW#d zm~*GAS4!{rUKIE2)T;^2o0UT=_1UL=D@t5d_x{eMuyvkS<999EGFds;`sIa7ZepKv zv(#&6AHC$1=Xdo=UPiIqs;XZ*4@#cAxboH86Gq$aOkQ>GU0m${MVE?GbADQc?yU_u zHf>e?DFwEPj%{fIl1CJbPF&zoYL;+elbq$4BG7z7!P&S2=vc{=44@LA49{5wqYjV^ z&_CJA%@V*EIgzr5t^Rw^;rlk*u6&gGb9efd-)E)M!75-rhI+mYsFf#af?~nFB~mHV{!Xzj3hI-%;JH)VeretdJkC*S zK4S-R5Xgz2LRVG&Ueu$TzjW31sYcs!yhHP&Pv0ntTUBMfyhpbhC~AB9$0wIn%f4k~ zD*j%cl{NX2Tb^I&a%nH?N`tTZFZW#vdglA-x}{P4t*rXOoolQ%Y4$J6`yh96$r`nr y+Rsz6!#=sbVtduSCMEma$+%Q;Mx-Z4;uunK>+P-Geuoky+6xao zGszUbPW zH{bU6()|ldDsOwWc0fSg@>OiJG_S{>GQI2&8b2Xo;n8^#&o`AkW4~nTxT{XVR(Q#C zL8Gve2U5S=RM_JuGcXou32Ze9S+#QB_H{Y6!KY=@|HhpDYI?J8^D-~fkk=AD`|LtW z-oJ{LH2-vIYwN{pr+8DAb{Cvzwkeh8t1M-$FVdQ&MBb@0AM(;6951J diff --git a/resources/builtin/projects/fa-bug.png b/resources/builtin/projects/fa-bug.png index 6494e0a204f67aa8cd0925828f147fbabf9d5046..83c538f88565dec4c91d550de67483227ca14d1c 100644 GIT binary patch literal 1577 zcma)6i8~Vt09ULz=6sH@jJ_cul_%y%Gjg`DVY23&ipSd=$r0L$t;6ORO46l_@U|y5 zO{@)Du2(+KoS$QkCnXa-mAriK{Q>XyeZTV$_)-0lo~p_Q%5rjYs@`7ifj?ZdLq&xj z3Ji$Vk&^>_^md1%FYQ|9U-_}g<=)?7>M?ik#D5X7@qzDKWTh(j+prKnFKJE~YkrzA zW-!*A(A@Xc)y3(BC-LH2hQ9vi`OlfOu`P7S`YkVoJWArmtOIhv?a)+8L3DU4wZu_{ z1+kYoHi&T385<05`OD*iI4mGcJn^ZP2qO0ig1Dien(rW(5r2sDm5N`Y%7;=7Uj?(< zmpTcy4QelNh;x*3a@}C8)`bJ0BLh=Q9CJ#LB|@0Yaa^(3Kh$*?IGo#uwg$D#7&IBi z)OPYYdlGYQ$I+ux5#(pkQYKhHRGkzYW$dTm%;Ze62-i_A_D~!(YP;f4$XDi;UwJ3 zX{-lsq$`^mR$l=N2zqG0ZtPO4HIY^R_i8b=MPayLb1hqE=eRLyr%5H7q^y(<*h`eI=4!kc>Zx!?KrGbywrS5UMv!|~wF=qS zi+i9ji2xk$8=hqnTuL-+5MKN(#~(In9Q-HIs6p7w`t>jjXI`q#*&7lSHsVA9H){0g zVFS#>_a+xE-NqcBcEnN>V$vFuc_+Z5gTEZ3hnzfuG3#CvnoJg)?e+#U_?2k0Zd;*D zCvA53*q~6RuMS|$D(%mlO1ZeauVEW_CEC^iDoma$OKg_u~!dxB!wd8r>;&^2J2m$D)fNUnFtx>mLlN zZ-M(s+7pE8Ta-#&D5}w7AWEf(nRYfJO(ihKrUvFPM$(q(HPwYms?@E$qQbZ|OrHl( zUTQfSXhXI#4WG`SN`K1B)RzWayPnSjCAGVCPT=-%5f5ezY{=Mpe_}xyyg#tUVY0{A z(-OVBf~Rk3AIxY2y?x}bnW+yA=3o}i(izJ7v~;}~rdwCvB!G)FnLWQk0@u>t%$=np zuibLxDa*)i-RB!g<4^w}azfy0!HblUzfRHn+?63~ZAwRj>vIupN=dnAc4^kNDay!a z0K@5;(yZsoqmsf+;|eh|^|0d_ydmJ-eVVGiI{ONyo}`xDiFX#AZmP4>SS!@qe!un5 zv`Az1rhOUmxcN7z-{&RS*M%mFm~nECpN8+NPTX-<>EMZCLQ~6W$tJV|y4=^_tH6Td z)kv-cgR!IggsYkf^+_67Pnr<-EIy82f49d6OTFyXprb}|lK5^T>>)o}i|j#OpYp06 ze}jKqlzyIj`9vYT1hb8>$(i<9mQRX=DA>H+j)c5K+KJScpDJX$hNjc793VdvEvGrm zvSk=Maqf93nV4JTXxwE!T#UsD$X1WT0B=z9{H&Erx35MMOgEeZMv8l!R8?f4%md6X zP$CA%AD{;9Qk$=C1%`?yeH2~2H_20wl-j6I$xb;#rlJLG@Mfc*dV86lOqaM9$nOKy z#4Y!y@=($Aea`*dPc=R%z@n@62J2I{Q5!QUAEHelAAuD&_KfsGcmn6d1*puuR&xTM zc+B;|@+=fft+Z+^Ih90W7tBSvxZFIH&DWVgy>8WN-_rC^go@AL_l3_WC$h9i-m(|$ z0@lm#w8wr$RRq8>kI-%$z-IcnI5|bvk6p&5B1r!L=qK0q literal 851 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 literal 462 zcmeAS@N?(olHy`uVBq!ia0vp^DIm@#WAFU@$D@`FKtJe;~#yU z^pun|np#UQI2~oKU<&SHim3jsk1!8i_3}aPwLN|cb~oI z^HxsY7Acn$ z`{Z)Z@ap;5TE3s;bT8MRSRJgi&}HtP=Nl#%R*DvfE9R%ntW#cZV{FaGZ5Ww%ce(F= zA*Bw5+cqD%PI48VF|vNDe_iKi^PB`OcEjEqpP6qqtq|~t{LZ+upRZ9`enMgm$Nw6K z4t_@V4uzw;r&Xt2@8Z)y+Xg*>OHxy{fqlYyNOdIv4x~^Wn0~k*Xp00i_>zopr05=!COaK4? diff --git a/resources/builtin/projects/fa-camera-retro.png b/resources/builtin/projects/fa-camera-retro.png new file mode 100644 index 0000000000000000000000000000000000000000..c1ac04d27bdb7277d69b16fe11dd3bac6340c57b GIT binary patch literal 1477 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 B{IUQ5 literal 567 zcmV-70?7S|P);hDk%6CcieJFnEe@m*pQ_)bXt?|2R(w`{f(A2%#k3ct{A( z0*kk%&}eRAV-C)ol$ZOlf4$ll@#;DpvDd*!8Y2&VUfJtagKPLl{@Yck2mDxiWkJ> zh+MHuOeW=uRbo<+D;mV4CReNw6}e)DsK^y##H1xx3=)%faz~YTJdis^h{p-JqriLO z@P!^FL6JC&D=DVQ-X}IIDY_|>tu{rafqq_-rRz!y{glbdZKa8BrU|djRrx@H5vqi+ z%q2F-F9w<6B`Y*Y-zrPYbC?Y>#u#IaF~%5Uj4|e)_Z{#127_}_#HauO002ovPDHLk FV1nU}_@Mv* diff --git a/resources/builtin/projects/fa-coffee.png b/resources/builtin/projects/fa-coffee.png new file mode 100644 index 0000000000000000000000000000000000000000..8d0850f0ee7fbf5fb326b65bb569e3cce769a713 GIT binary patch literal 958 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k1xT_7rin5zFt>WTIEGX(zBy>f2oyY|@O!!0 zQM&|AAR84}SU*3Ib5_*#U}@m__eZzoZWa(pnwE5XTkh>`b8G%B`a9q1+1fL`>E~x& z{VQBmaYQTTsLrB7y(h8rp1JX*yH8ub+~`5VA_4jIaJ4HrHySj~v`09fZGGOsR6B9& zRhJh+N2{2Hv!uRsHvOG+R#s(p`i0U7G51{0I~M)aQRbVZ>j`94>c_I5d>Y9&>Fiq> zmFe+@u?`bT_8q!x|4T_;u>Rz2E{;j(IRA24`E1lQ7pT9~JEh@M6VCyb<-$DQO|85f zIvv>(Ebl3|?P@Fvs1xY4;}>wQ@ru;2?{Jy^yF>Au2KQ6;i7!5j1-_hj%K4|G$}}mn zO-p^I$h$nsSafM$P+;AJz(tp)PVM~E>=EM@vSacjpa^d#SAU4nDSjhh04@dz@C80h zKIID3{Vb$6LsQ+Ay>j*sXZt|En)Z|f?*;Zd|C#z!LE7Y{{gL`t*4wQ*j&G8Aa>8Zt zUcN&@E=$jAYOAs>JTC3Bv|3x+_1wz)Q#1YUuJ(KPb=71O$B0?m_v&e%KXr6+=fh8I zvZ@Q7Y~4FK=gii)+p`nD{{CEF`Stf)udeUy79LF7!fxO(i}$#s9=_(X_)b{r zVTp?x$3v{{IG7yE4z<(qHaWKRD%*~pjF#uCWepDLDD9nZuxQ(XQ!Z8E0kadlmA1~- z67<_N^A?BpC(l#m$GNh!dzMIhS@sKVm7exQNU1e^!;~}S28WK#IkLIN^~!_KbB-|ec%4g@+;#kCj6LMR)3ZIaf|QPym^m1~bs_`w< d8Z~DDc?$Qho<1Y<_FMu;#?#f$Wt~$(69ByCujc>& literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-comments.png b/resources/builtin/projects/fa-comments.png new file mode 100644 index 0000000000000000000000000000000000000000..927fb91bb2e80f2a103c915f50cc5bfc9141b17b GIT binary patch literal 1739 zcmV;+1~mDJP)qr?$l|U;qFB00000000000000006^mG-36E9HWz^5YbWbrC}pSVoaIwy zW@c`enW4`7xBkOvI=%UO~T*4gg=0(2bch<6% z3fo!BQoi98?qeR8b1Z}O5KGW_#FRLP+xY=a-S6DXMU*K@1B5rC%(Z-pHl&}K#t32w z(xbrPJW2&^LN9YXiPR<_Vl)q{Tz{5^h9u+p|RC z7cNJgDO}z;1kHWti7)76JL*9P__DV881fu;bhe7W{Cm6J9|We66$qF8RsT-$W9hJ zh*7WWG2X=0AzMKdPGmK{jbgyTP9Krrbky7CiUHHm8hS_Upbho5K{4PH$-QFv`}r#)|<7nxf%i3!kE1 zwUeS4a0Z&9GsG4SK)vcrG2++s%VtZMhkDb;V#F9URnLe$#QchSQH4G+;+^zoRxDya z)Qe6RBSxSpTP=2RjyFf+4EPL9*)Fk-o6ubM8F2#-&2ACfh|bBbag zF(2l2vz=bq3vQ@?wPqcKT)rins=OVe(7L);+(675Xs%ja*V;8ZwjAtCW`E((XR7LOqJ!r8+ zTtn#m?jqt{G~-q>e)eqR0=a{$x8l^V61Z zqv^9SS!m(j`rUL$hUn#?3^(%aBT6yG^CW$eAqIIigYh@Fa9_>;i0gn%zqQBlU3T;A z_N5t%tZ*BpOegARvL%CAl3f0;gr%ID-SUuru4gscv`!MYF{j#nW^Q3bW~;n0OyhU7 ziLIwBuH!=Uu}UT}KqO7aFv?t+$xPRqB;r02HvY$F=mAcrx9OMbF2-^>kFwsvli^)Q z8&@-#6B!_BzykV6j%FN#l-QSj*pC55Fpk4Hj`Ntw!+gmu3#a7!rBxAeIeVNM2t89; z9UVOG*h9?%4&ZsziMl2D8%lPctYSFg6VS(OcA{46kl^1Db3C6pHX0hx$?3dp^IyFL z1|%HLLY8Jek(fwO4GH78nnziQrmVu3b(}qZgGg!-5YxwKj^{Gw@+fcfIX|@z2SjE4L{vJO1HCkV)6NjplJK?w#ef&)k-3$n0LMYo#OS_WzIJszR2d%eNk# zQ)8)BD0bNV^kkK9%pN~=Ud|Uke&R~=o5GM!j5{wsQJ6iQ-F^SE=Qq~cIBctbuJC%2 z?TOAQ#%8XjnvoZk^_JOmPP{4qDgLlv`{W=o+hB*Z)Oxq*$Isn^E(JM+i9hTpbttM4 zb7){-WMbhEP(WjNh%xRI(^ZXibmT#mlt5K#h^jH^-}mZuj1Uv|qbbE|57clWS^KTO z;{V+Ls_V*xrfzjz*46uUXOH!=JqlNM_!kFt=!9);%4Q5dw_Lp`{}JRzuTvM5SyRHk zrO)yD?b4gYX?YG90D(85iJy_Ti|QdZqZ(8_bXH&O7>GiG=I-8{+G|dkf9QTvauL y0z2yrHK!ff6_o3HrtjiK-HF&E+%xE56|?AKwUk*c&(8xB7lWs(pUXO@geCz0*7G(1 literal 348 zcmeAS@N?(olHy`uVBq!ia0vp^DIm+P+LS%(~Cj(>FF z_1GXHzhIW)FNL`>zgS#Z9ACW9E1h5$$}U^OT)N@HTKx;|KT5p?RGr^_s9$*heJ^_> zzvA@M6E&1zfM4@sQ2eGh?$TdlBx~P_I;E%T^-L?{TDtjg>_s2Nttgs)3*LPA_ zDm%*SRs6D?lx;VT)G6+KxQmm8LqOrb#HTfPaw=L`1O*fv8Ws8Kj7&=c1@0+3{Bb&#)-#RYoR>BY7-|fju6{1-oD!M<1P_XG diff --git a/resources/builtin/projects/fa-database.png b/resources/builtin/projects/fa-database.png new file mode 100644 index 0000000000000000000000000000000000000000..bafcd1e338b939f7f3f9d0b9f97bb4db62f49a94 GIT binary patch literal 2146 zcmV-o2%YzdP)tp61QHWQe_lN{!A+)=CV=w>}_6ysR`i~)yA9_KLkaL2ro z^ss??{Fsr0pJsNDz!joWT;p*{v2`2~)okNOTtVvw^T^XfMJBVki7Q1VSVxJ<%XK3? zxYAXErTEobD>gBJD{=Mkh$4$V1)RcFqWWl;Tnc_p;VM=AG|0PVtix5Z-XtKOj$-<8 z6|SXHOsklO1Evw215vwK}Ax4N1f)RodVuWCXV1yVU7$F!TMhHd-16m3R zi!0;(3 zG=yoafGGRN{cNA2mt{=C8OC2N9`sQ;jQ5|EGMz2lVsH#Qp!U&0Waw`K!plC%O5Eu8+(Kszu%H6b&_Bw+=-78FCAA>4KN&DGE z7_aa*2?6GFL#J%-yL1sDL%7MQkhz>9sc+c&XU?&hsrbiln~aZgqHO1LlYamE`iPf_ zGKoB#Q6C98l+wsbuKcf~!L%d9ImJ4nL?|VXEWCJz_|Ny@r;rfMbh49I`AwI0gya}R zH{;yo1P9s0OKfF5D_P8w#CV)emea*%o?|l~DwCh`pqw zQt=*h@L4K@O_-M?7%e@_BFoYT@|epd0msYdtS3a8uI&gOg3MwU561lx{Tho1sn(8g zkMJ-~_rSTabILh`%R`ZdJ zF`yJL6I4uwmnh%Joy&Tc7Q9NxC}A5ZRf2NIh{$^rM1W-^R7@_Oqm@jlZWSunNJ8}} zX&)P@!Vy|TKJ)3;E!%sKZL|?2O_<$NHdQR+jtN^QIKmS|#-k+xhf-$n9B-NQ`@gPF zIYt+=sUm=bXB3iSxs=nylWe1xr1?6+|6BcBWgnaABuYJDikUzrJ{-K**m(Xb4G%Up zX{6(jK@LGGsivJ6YuLsq-ey3ruOs}3t6^1&E99n@LMDhSq(eg;KU(5~kCb*oIxLZ) zQ!^c3VT*n>eNC(Gsh|w^Kd)<|BSlD-E4eco==hl;OCESaaUDI<#pehpJ9Q`& z3FUOWh$DA!G^&u4UF4{d(x~TM$yNNqDl#pVAjlR;zmIT(I&4)FO<{JBlt#s?%pt>4 z9Xyn>lFxx8 z0djD#N9h$i2W3m0#Hqt$DF}Y{$r=NCzyi{hk`dyH?76HIyC|1`tdK>FK6Qd}36_yB zsS1Z?deuxWe#b^Cu_an9qP(g@l=K>N35qL*EUI~#AN0%i-eeJBvc*_oNT-My?Bxd& zwodUXn`xyG@0ee7<`Us4PW?L#CjI^c-Mm1II*Q4{9)%@3k1(_7;uxQ(o_-&d>@2r9 z#&axVF3nU?@;B`WY5%1iA)iWWnaPuEU=No@>B_%KTpbXi6m z4k;?5kFX^tRPeTPy&+FXp7Ui2?sI&J@TFABZ2Ae`=v6J|?^$%X8lkmT~ zmojSnOs0ci_@% literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-desktop.png b/resources/builtin/projects/fa-desktop.png new file mode 100644 index 0000000000000000000000000000000000000000..f463db8e1b66d33c6d0a16f7b1f47bc6c5e7c4ec GIT binary patch literal 760 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k1xT_7rin5zFzxqraSW+oe0%HgEY@_1){E-} zZ*R-Jz3pvJQnFOF*qP+pWuNX}KBuuxu0&pK>$QCi$9{|WU0wN~7ia^$$J zdgk6+`jxu7mzYmI(N_bj%^&;5%J<(>5L4cqqX_Qu5XDS33@W#Q?sbN8Q6wOkf% zt@piLEpqcQ-SeeSA{JI@sF$(a+;(j3`rcDseTE$UR|1~IV-Zcf?C#G%xofJDqd z;?!~`xnJG!bgoHsK{b$G38bU1?ReS*q_wZ^NL_3aosfU!N2=QU<)!EPR(hUTmnpm1 z-za+WMD zJ5%F3S!Z%?af;rFtnS$cU8afXqK^ X9NphH@h_hr2NL&m^>bP0l+XkKlPx#b literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-diamond.png b/resources/builtin/projects/fa-diamond.png new file mode 100644 index 0000000000000000000000000000000000000000..34a68c328458416a82a1f68e095536cba7fc81e5 GIT binary patch literal 2065 zcmY*adpr}07grLS++|3O=CK)tJQ9Oixf6}+b+_`kq2%Vh61Jg+Ww=6?Q0THe zB26+;A{+#dmoXt*`NcUqg=7i9F3k?SQM9F>nySB`RdR>wGFQPtp6FkQJ9l+j1%)hC+KJyd;Tj}WK7I{Ar^LugvG96lW{6~f4|vngGG8^4ys zD{2hx;+r{Hduc=C@PotmW&|T^MmVDva&Ee1e@udcWdVxd1;> zE9v_RvsQy{dYIT6iY;Yj^UiIk{vcw|&B2834<(g7egoK&+aO60?c7MP+p|rm;k-DK zWkw%G=f_WDem#jOmw}x&>6;ggG=O%iLnt_YFi2PmZW;b(oVWlF-$;hk%0}78>Hipb z{Y}VW_Rm09_}`V9_+{x7N^S~VdkyEE713h9_2q1-Bo$K7Cz>)nqGj2f5wdKaGdj+N zIbEL3<{>tc>*eSCdULop3+8{enS`!XubqK)x+AWAeEJiV7|}9NU~_SToXJT8=Do-2 z1c6LdB8FXBb<*7&{^>KrM!u5t?YErP3edTF(ecm5 zp?$?62IsHSW>RrS8Q0;ut60T#l0wW50gUwdV_lCNIvBvD?#K)3?cK>-D_$oPkO2uq ztsB7Stb>TYk%fKH06Jo#cQ3iR+N9rBl z9cL-R!OV)>yTx738iOkr)peB?y&Yd6VQys8Us)fW6k|p}&O$eeJR9W$Z;#?79q(Q2 z*K_l-t3SdtKC*u_zjlm;xuQC4FwJ;z7W|7bz`3vIvvB!%?Bnzk6{o_^xG1kmDW=Yi zV&VcagUH!(J0l$)QjxV5W_M=0{@CutwClULI$?jjJ+Nnzq!6QW>~f|Jq45uhlJ*Qv zx)_2bz#Arq;s=Z(n`}U>YS;|k(dkhxhTC>9Jl==aRexVTer{22i&hZT%Jx$VtC1y2 zJ98j7)W~7Up^!}veB-7v?oV&^*Vh)MpFGoZYr+K@Y$dV??Pp8vNMTTtpnU6Am08&8Et{)YE8LLc*U~nnBT;e>yo0r zovE_qz#%n)c9ejoM2x`=>Nc-g(_8y35zx@3;0Z4pD<31~axEgk>j*YOlb(2EX*)MG zBTu7`r$RP5mJJbZ{k9gtR0lZk*rQrIQ@ewD%~IDHzR|kW@0{qt1A?+UEKi9rQb!7& zoZ>7E+t?DJ3pJF+%ldGJ9CB-dyL5N;>-#sXQI|TvICPK^X&8ny7-SDVZi=D(sHfi!7$ja18w?s2a`l-RYf(tGC-Kdu0(}eH@FKUuj2VS*Z59`W z`sOH|e2pMM`_NzIF7`HVBb58TWC?*j#&&MkpA=|_NH6?*oC{C$y%XwUW1DQ@IL1U1 zdatR+)gh0nLcer@FZJp%Zv@gJz zIr(BDZxey3UZj|#E_H+DHJg>6 zvNqf~$y&$=DpOjQ1FcpZpie1;)FAtAx~mT6nB+)ZziDNU$8lHReT6cqOq^ z?Y8$4Jmo#eG1zmeP~%Rp4(TcCIhd^h032NqpYT%D%_|l+dzP>OWM_eB)ToNsp4hrr zxvE1#&-18Do#1r|{EW(A?Inf7jD=zPd_tYoy{+F%_Y>cR`&RW+*Y1R7Jl4ox2EG*D zK96ec0(Y&_Ba9C48jW;QJlqX(Rb*(?8$^rnle?*+=3YegjfNdtl#79MN5plg~lk@8GKQd%BVITbNJ zk;jVE^FZ~ah9p=$W-0&A%}byX!Ka{pA4sC|4~n2l_|F1UQI;J#s^ZiNZohyngRk}^y9_Eu$DN?3k%Pf{{mI9=WhT2 literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-empire.png b/resources/builtin/projects/fa-empire.png new file mode 100644 index 0000000000000000000000000000000000000000..2d9dc3a8dfddedb04aeb2435d8387c2d736fc2d4 GIT binary patch literal 4598 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 AD*ylh literal 831 zcmV-F1Hk-=P)0^|W4cgU@xhrd^h_3%OZC4jplA zJCI&K$)#TnREOLrr#4rI?3Ppet3#&b)NFOgDLFM)9dcAo{ZbvWPfopF9rC!Gx~n?m zJTr1>%EIc9WTRXfZTGv@+j8hlsa?pB1G?SU&TSu(EOk&fo3d1@1Cm_sN8RchOQgCW z$zt#6M(-Gq>VzZ)lS*0C%kd3-{~|2UUhz0dA;vc>3b{Vw{5S${6P54?O|=N z=QaJGnzrf-Z@JAu<`Y8G3;M(Q)eiZu9kM#??z2^s`G&v`ZVEewy`gn%GaPo_=m2yF z!fDSqC+xc4@fKI@hIn1rV)xi$i%}QE&#W>@ju6fm*CVwaJ;t3O zR|tG;Sxd%pdm(QK$86Foon`urnVxW#JLS~6>X2loT-qVE1L?P24sF+80TO17J*G8v zqo!$ltf~HA-OQ#yx;zC^AO%t&1yUddQXmCVAO%t&1yUdd@-NUGf@M{lE_MI_002ov JPDHLkV1l^dkfHzp diff --git a/resources/builtin/projects/fa-facebook.png b/resources/builtin/projects/fa-facebook.png new file mode 100644 index 0000000000000000000000000000000000000000..3d5a5f1f9a84a3cb2e8a56b7e3ad3a50640b8377 GIT binary patch literal 1109 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k1xT_7rin5zu*i72IEGX(zB$+k6k}*u@OP#7 zN+u8!0@9w#ZIL~B$bjen?!L7fb8m0UJ%8xNw%pqha^>>d?*5*4Z)0%w(*>LUd)3~r zX0Mzi(v;Ox_wA95+@s>UB-V{3Yg6RnKdFdslt0|^$%)16nbkDG*{iPJIejf9_3#Oc z36)2dD^XSoO4_#X=&8q#yU$s#js7;wM8+G zYjXGnjyzo5{w3|{+Sj(Sr<4N=r%V^Vt9t0i;;%Lhd(=Ai|C**_dR#8)NBHukPftWB zwA62HJ2ypvz579Z?5sXz1FeStTW4JhQJ5_h+WXCywMaPd>WjT03YGFFR(%tZVRo5% zIZV^xo0^&9=ZePJJ7#fPzMg*WS&iO9u60k%9^#O^0*(hKDVtZ|1IT zv0A_FmSmE7(p}q0Oiwlj1?fDtY0G6>+!|4Se>ua?O)cxYYft9dm(+n=H^Aw^bKAbxGWu}q`ct``fZ z+x@D~Y;bIoNNXv*>7`&P`Y~aH-t*6rg;JbLRs_dcRjk~h-s&K?IkPvcPKj&Dj&&O{ zdv|v*6&Clo>IW(u-8SDhd5+G6MYqo`GmI1UxR{%NSzy zt-vJM;lQFK(8%F}!34%dV`^e4o!JmP**(fEUDryo%0 zo&ZqjC{rPelbc9~`h+;3_)Qm}_%|V-xG_kn9#H6~4^SwK`-mXNT9?KOCP|Q{wIIoa z#w+iXx2<2?mw9*bt$lrR!XAHLW;@_<6?V76L{E4%K5_Sc?D&jR#U2<%HJTIttoiuZ zu<^+^XRZm{tdnjh1CxiCN8a-vzj9YOZ1Z9iicp*|=a%l#9gzyA)#oquoMj2x{5PnP z#f|mT{%aS~Rvuf(^fP{XM%lQlpAB5T`h$=Dc RUa<-!=IQF^vd$@?2>@Ht+P?q* literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-fax.png b/resources/builtin/projects/fa-fax.png new file mode 100644 index 0000000000000000000000000000000000000000..af00c31269b1b615d64a247e0697384c0e9fd711 GIT binary patch literal 1304 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k1xT_7rin5zu-x}_aSW+od~?u{k%58ZfP(&S z^Ld;(3_L&;P;g-V+Z(&t)x)=GbRCxUS$3>uTkdTrdi#3!|K<0cS8A7D(!X45bkjC6 zdusOedDfp>=T>Vi?m3^-{?dC&z=}=c^OIs<*yN>0|4N;}r5t<6<9l7$)FbtY4fhSi zYr8{*Tf+_A_fD+JFJ9AY`FeZLH=`3zXY4+gysO;N?pVwupRZaclFp?5e-kKlCij0z zkb<5ki_yF@P7vYOOi7vZgQfOR-;SsFtO}ofccB|Hruh7Ot^wc4m>^yw1T&V%43lvm4BV zMLpb|n$0)L)b`pny6|6RQn!j*qBP;e!>Bb5>qR`SY!C|Dpv`sUI^&kz{a6mFJx9giqg%8Y^CJaH#nj z(fH$4Khwu+nLzp*)5ojbERR;7=QE44hNPZJ?V{p z3uYH3Uw+b=BQWE3!{ph|)}>B2B5}!M0no zm&}?aedf-NO%7atW?i{G*XQk;^mD!3P$MCx@6?7^^71_6rTLcI*Enq2T{B70%-`2< z`_J@yCdH2zGM#+4eT}z$Z6n_X(a%AX=WmkgJrL7;^{0*LclBrkfjbr_=FM>U6Ap2w z(gY6C6WKlL2LlpW_j&r-9WLlTnK;k?Z0*USkf@xP$(2CUGA0RL%XzP&qr7sbsge0R zr3p;?)p}*#Uy+_!9K4kA;#M8FuaN@4N%thjV#{;wTk1=F6dL7brnIaMp8PxYjI6{D zwKWbaJ}hzgx8A=%<2Or{%6fC(d#4*4cQWtXp7}16k3Y|5TEAiAl&#=^e6*jbatiZJ zmkYiI5(y#6Pidzo_XX>-|3>8#Hlw>QaJT>3W6Zo#LkuYobk z&V3|292m3LSRSo3SKlmOcUbAmbs6cubJ0NX|m*)tn27Vlp;uSEM!zvvrVU+MRHmdBlzO?uZ_xF*4U zwprg)nUvloyB}Jtap>pDvDtOxd*9W`@7k?5&e^;5=&@+;Uv~_rR&ZRMqq03Hcjv|$ z74u;KKP|!=B){D_Fl&=t!QRuaI=36xHHXK1H@bK1nBlvFcfN?Kh6Xyt(yO= hRo}Qd3RZFfX-3b;&z(PKnn;7hJYD@<);T3K0RRNgIvM}~ literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-film.png b/resources/builtin/projects/fa-film.png new file mode 100644 index 0000000000000000000000000000000000000000..2c30ffe47709c40c522a269f762cef66f6364c0b GIT binary patch literal 1276 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k1xT_7rin5zupIVuaSW+od~=YImw|!ffP(Rj z{jc9XY^Y=fDnWpTZOQNTW<51qq|uk1B2f^Q$Yu-zoA>e8e3@n^7^oY zFZD`)+V-z|b2+_MEOx)+!BBoTqo<2bsjw9(hh~eIZu`XiPU#$DTkyt18>jFrFX+1mOqMY$ zCzR$0`E32FaQ?AP<@9+=8r_<=?nvmnJax;0`R`&aTe;H&w?2@6w6yV@?%MmucHjHI zTDB;vw(#B_&!`XoSH@c8?|NpkyE@u=a+v=6{h#%I+P>edvUr-vo{Wm}Ejo*KUb;N{ z)-T>2%WNdK7y5tRcjUmMz?k4y&vz`A6mt-pS6n=ebHdLZ|J65TiliK~G+#c0VWy%$ zBZrFulVFDfixQZb8_hIRQy^Ml_Ts9{nGPPwWhtUhg0%$q&Rfd#QtaaEL_U>&ACzP( zwudOFdlui9Pk+;7Ar{10{^Ag0%t{BD{2=b~6`Q%!C69d6oIUeo&oZ4Sp7n<qN}lL#8Z?x@DkVK=MtocU|-s8)gN! zzSO(fOivzul0R+L&M2w#$!v9N@s*S3-o~DtXtg)s_}#fQ^*X0{viEHyd$_pU`{tP_6V^BwOUH+pkWv z-+T6D$pcXZOXpekvkz&Vcpjouwb$ls`Q$_5qVL(m`#aM7S1UxHtCYHM>&Stm$&Hx~ zZqHJEO&N_oH(9l=#^(3WtV!HYKCXyc?4xi+xvF%vLZ6#UzVAwhX>MPp-DbV%-aaSn z{3YJ`I}QJTD%`D5dHzsr=&6rB+^4PQc`~2D49c1lY|9LnY8F>^teK)vUtqr3#(LIK z+dqjCD*q>CzS(6aP96zi+qMyK(LP1A6b-mOVRDTYvbnp~E4Q7=`oC=PanYc>C4WU%GeNK0m9y zW;9jPcjn>dlpO^X(@p0+`*|+p+6O&7nYzb*X;rg~cN$l4ecyDg`3rBJ!_SFcuN|$} z;$=^rThbvavv&QJZpN1n{w`g*#-}SP=H3_6wKo2$nt2yL+pCk(TQq51=Ui9!Uxm`UfBaHPK2b6KdE}|7o!92SJ-8867#&cke;xQ{wHl&e a0Qj)rFLkm2kFaXel9T-G@yGywq1f-X-0 literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-firefox.png b/resources/builtin/projects/fa-firefox.png new file mode 100644 index 0000000000000000000000000000000000000000..25fd9fc7390ca52f1ea1568db599c622ad608623 GIT binary patch literal 2300 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 W$#uglAfNOA00000)Y^2 z6tedYNLW#hi={FO$wk$>A+`u+0Z=4U~ zX?Kh;R){H~GZ>7jP)5}bPQ>fYR&T#?e*EzDg>$3Eb-^bOUd0Pm+;eHWbg|@XeLjzR z%nj>*(>akUC|4|S?+*EBvEN&hXzN5-QTKbbbzS{N?jT7i@)piSQ z;cbueTFHSnK+Cx_p?Z|d{E9>5E%2&kR9OM@21~nXW6m=n*oO_mv^NR{bQ|P$W6f8s z>v40c_}$ZQqC>yC!x)t(2tTEjaOjpOodX*!|K-SjDh+>(x|w0}w(Bp(No1I`8=rAt z<5bzzw;M{mH!tT!TFI01PBEkQ>Ov^uE858geX$MP2MsO*))YrWOS0H*(I+Q2&9Px* z-r}7H_AMm_(-yi}gppTtwx@o0^#~1~`Nig1bdKTu;bn6_AgOSU{r+C|l}65xB2QuK z&?}f(!HRss=oWD`{)5fAAXdKQ``~OgC5BqW9&&UY?9cT#<=tq^YQ!Z>-m8!r@%Vs) z^OMBXbR^=CO7F#}N_V;3-9Q>@mad)-Df->xLYYgg zhJr+Ud+VRwmx11fl{sg%?q>5OuI=pt*Xv8Ev>We@lB)56E5Krd?_;p)9?5mbi;I}5 zUcRY1e@;)o61q;DD3niX!8X&+N^3o-+(|Uw6b#+GJU-vCN6c5)?DwK`HKg;YX+ojz z5E=FKd4%52cfH+xkE9O(`X=x1J7hrz0ex~>4VXo6=#1h$zM=0Vo`UPN+5_0@#&R+qn*34B_BS+>ktCa;U%VQbv?u$E! zCN)yKBdw5jUmT<$C~`0kVtn@9Yz+!P04Vx!{9bL#fW&{aKLMe%UGwKs&_f-H{Xt6nScTWcFMC4sy8= zz5Vb>mKW6()l@vWwb(lZL>K$rEctqiGe|@^>C0g-L9)o(;kqL+rYI)VQg{>=|IGFy zco1-1f%HZiXY-o6r>Rj91_-qNGc4DzIgP+qO1Pf4?9k-)5LQkq4aJuy$}R#0fG=QRU?Lj1eLf7@*eH$$D^;IXB;*>f2{=e$ggfGo)$VJVJ9X zNP6OxwPr z40uJ`-mv!Y>~a9@F;CchSiMHF5f1G4S7CFdm#?{Cph%CRWkHU8joO$@<~9v73Jp`4 z5F0^uMxKWu6yeal=kDF>9}QL9h4qT@;?k9y>udAI zMnCR(uyQ@k44{+ja5MUPLu4gJ(VL!^aj{mJ5*<=YDc!-#Est4lBC5>Q9SQVxvGaM0l=aWU-C1AiN>rGOn+1Ws>#bN{b zl6Qv^)BW*;xvM8fSki8-Zrx^B_@0!hDb2$ZVYGd02{~xc3@HC8~vhuE#g@eM0;SPKf37*``>WE`F~!- g2f)6)!7pS_-ocj|ewuht!{^lPhhya1heFu@2bF|SWB>pF literal 1011 zcmV+DWfd}0c}ES)BBbD;j;+fgWUR15 zS%fqQYZb*zf47=tt|eaaoM+8)r-9wx;zUc_n-nry*f0ONdZ3x!w8wd29PqY>Tvid{ zX4?Uc$smy*b!=6*N{!ieDvIxK?`lwpM;L0YqEbayC4=16VSB&3I{2xraZ+U+wBV9| zlWM)@jPgb%gG8oZw9UP4D*N69TeRz5C#+N(-jgP2(k5(FQb=T*Qcsut5`KBfZSJ;R zTx~uy(-;E`c8fXQ(hQ^p8SN9Dw^ySXr6(;(DL|%a6}Hdw!8uOaj_N{wRbIO-CX2#J zh?pR%F682h-s^AyB!{$kL%m3p9%O5Xs2I|s)G1$E?jC(bqI4k*qQsEMAa$-+BMK*5 zkZ^hs}-Sr$hRJ?%(`GWa5fvC?TX)qcbjUL^UBxZPP9&5u~r_wkj&`jGC%IVmfP=_bs!?e2cBH z$hknA&tY-3c-3%`sCtkSO0mZreM&1U#2nChr)}~;a6GF3 zSqV5~wt}eJ)63mf`$miNE;wz!ZC*54|6pa6AO(+DXMS)YCYa!XqyXumlSAU?pZ4pR z1^^I>VxS>RVE}QsLIn&E9Q@%WmnyiiARr(hARr)>fy@sX*^vHDd+nADi3kJ)1Ox;G h1Ox;GS=^6h*;TibYEEmExKhCZ|gP?AQhj-S=02M|%MP00000000000H={Poss#+8|kcd z8ClYqPh4lI^GIhtd0m{7E%OCii_@~dBuE#hWxOQFCjAc7!>AP6FeAc6=Yh#&|e2!aTLAiqZt z1Q7&51VIo%1QA3KK?Fe%K{&8?PW|;IK@_cUY}>YNdtS!2ZQHhO+vZ>UJFT&&PSp9O zZg;Kq8rPj~9{SO!vEHBF7i$ zvt<0RCvx4R>~|$2!dxBa`g8PkTvspn*A;Ww_(-@1xh~ZCoeLq?yKOuqY=m47AMv}7 zK&~6wSVTjcoO$Ri5+`2ab7%aDzYgo}{t3N{K@5xHJyK1un1W~qakjC{NKhN1Ge zy`=mDxqM-elrLFFD4iFykx1y{*^+}g=I$6=K0RWPlCX2>*rPK@*~z*{n3EZ$gF*Uu z2|3PSPV-5)wS08m9pQ7Uc_gfhT#vO0z;VcRUHd;02Kfp(eoX%aM>d}#$FCT)|B`Sn za$VIX2&*F3v+ds`EQ?&Pob*Qj%i6!lu;gvz_&vjg^5Y+oT=%oWus?F$))HoC8ghJ-Axn6H=!&=Do6q_VC6}hfy?ZN<`Bgan}n3CW7x%+$ThtsC& zOl8f^E3-|y@8toWU9qXH+UczBUT<(}w|hJgZ2VI{-6Q632|@kvaCfE@DnqLuwnVN6 zhDn*Xu-b?}FVQ&<^CQFgitc5D%~aM;_uO{Cx%~KqS^W`zwM%?BA>#Td)UO}^gn%3BMt|@-0(jbMskn7Gi#jp!<-P5Y0d!NR$^abCSGIv`|0OEU()dicN z9(UvVn*j8d-&Pc)a0#lwODbyuP=PB})dZjdKd2x`;V4v*M^@GZpaK`_?XcuIRGI!D zHa_f%Ds-2sngCQ_uQnUt4pgbPTkpa8sAAW%-hv^%LbX^yvjNUUm3wY2O#td~+1?3D z-bD@gZjS^h9D*A0pk8kRP@fA}ba)aqtQQd_L{7sf77Z`VZ%g)uu09BG;G1av7US zSP-TEaDjZN$Fe`m-Yk3n4lAQH)V5IWMQNaZ56sC|i1bV5uo$o)Uy_GofmqEmZbuD! zYrw`EEW`DvL9b<*$UCQ2WPdKM000000000008q!$kukxx(ft4b002ovPDHLkV1gX%M^^v< literal 692 zcmeAS@N?(olHy`uVBq!ia0vp^DImgfqBA(&%#~H#?zrXTRW&sOw-ul5Q_MT!f=p!-YEug#>ekZILjh&e#M{T$6Q&S*Yd7h zCcpT|ugtnI*#k3{+&n*FGl!nf?yYkf9&2X)ce?gT_%ZLy31{_Kj@NK|er8clh<=eL zt1OXh@=LTx z;r0owH3v0Zel1?W?&AGP@w#J*vhB?y7RRcesY-8RcJY6*yuW$Jl#~-OY=*}&m43av z-2Sn<_hf5HgN5N@a}(pvkCU|26&K1sRV^wxmvOJrVy=sa>iN#wEZTS5=NxK_yRLXz zGs%7S?FsBRKFw8q=d|fY$?;GRTh=#OrNTwRx7${3mEXiIzU~&^%=79o95<58Rob=x zhTP`9c|_#hoXw(>o{8%DZaU?6LNVs`HsMR{*^FO5w(BHtedjwOf5}6L@3{P=M4s)?wfsmZ5bVy=uH0k?EXzk Tg4^VQsgc3c)z4*}Q$iB}i~K?2 diff --git a/resources/builtin/projects/fa-folder.png b/resources/builtin/projects/fa-folder.png index d2fb95f9b0001e4a4d43eda58789e85bdaff2676..f6003fcd913ab2c0db12d5331efa51b3e03082df 100644 GIT binary patch literal 752 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k1xT_7rin5zFm3mAaSW+oe0#llQ|WQ0){FOk zAK8|>dXDt%ZMnC#j+o`YS<-XE>gs!w`rA>fC)*yYX<1*rutx!?9|<(9nXtAvK<||A zPJMozYwu2kS}InjoINz@MA1$C_sjK;{+-pmIWF;H>Wtve;jfHt7I#au=1k5Hp8itr z{01GFBEKy5-x{l@uqrm+nS1NvzVlY8|4uNklzn%7P2jWMn2EPO?mNqs`tF3>O4~O- zc}~qa!S&O2>vY+eXD)f3Z!_!9e!QWydg-?v#i!PsaNW!HQ~j_Jv*eTOSK_v3&uq+@ za_e)Rw(*3+)%>4=XExrMcI$VT#^nj$r8zd`&1|c=?J(i&DU*~vjS9D?WP0Q#+!kk< zY3?X@Ds%4pDKc~ar_NrZ=8^qd^?KUoYfU%OZ|>Zx@GT}RQ@i8u%(>CrN$p$3j`U^f zcD%hDCLn!2DwlQRc_V=%r)%vT-(2Up&6V_ftLPECEZvT^m%;>YuU)H9<`(Vvrg2-- z4QY_lTU<%;+)5pPrJFgFIuz786q-OZoZv*}0ELs_GEg-$5NaVTVvP8dyy|T6|Mzw$ z(pQ?Dx4l|Bfjua9-tIlW71WpBve_R0-Eo`O*2=uQ@0xp3ZLU7s6>p?*_w?MAX4hjQ zeog2N%3T+|_=~ds(pxgS*MCvXUVba*x4QQ9e@{X<({3{^^_P57DHv4|<2!w0jn0uP zdnYBnj1QZT@+t0gM5gnxM+d)pv@MmD?D_J#)~0>>x0JPlfAuSMR!y_R~j(<6`)8;I$4mgVUN-E}6*ro07lJzf1= J);T3K0RSN6RJZ^D literal 375 zcmeAS@N?(olHy`uVBq!ia0vp^DIm+P-m+O2^S2RSg354d{UX$G=U79DaKoIV4O@g7)*Npz(Mqpz`xSR0_2`7d0_s_N!cJruOC`DP zH9Dm%teAF1%W{M8F{eKfOI*Ll-4@T-S4_C_e8hsxg#(@89ZJ6T-G@y GGywoO^`kQY diff --git a/resources/builtin/projects/fa-gamepad.png b/resources/builtin/projects/fa-gamepad.png new file mode 100644 index 0000000000000000000000000000000000000000..db3e7df75e5afabd3fda71855ef50f53b470d881 GIT binary patch literal 1375 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 literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-google.png b/resources/builtin/projects/fa-google.png new file mode 100644 index 0000000000000000000000000000000000000000..cd1ad99b1bc8a9a6d7aa881de23003852a89a26e GIT binary patch literal 1851 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 literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-hand-peace-o.png b/resources/builtin/projects/fa-hand-peace-o.png new file mode 100644 index 0000000000000000000000000000000000000000..20a9181f5c0dc6caeeb722966c82e1deb03dc73e GIT binary patch literal 2680 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 literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-key.png b/resources/builtin/projects/fa-key.png new file mode 100644 index 0000000000000000000000000000000000000000..8b7f810fe58b06f17e305e65e656b08abca14991 GIT binary patch literal 1792 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 diff --git a/resources/builtin/projects/fa-microphone.png b/resources/builtin/projects/fa-microphone.png new file mode 100644 index 0000000000000000000000000000000000000000..d279fe69345487c79317f3f5e01a28ca3ca95b47 GIT binary patch literal 1649 zcmZvdYgE!_7{DtAXnUdWkfk(own zS+p7y31X#7Q$bx}*aayvL98^``ZEnRZ=>y;ed;~W`#$G)o)7PH-gDmHQ}QDr#2ju5 zhd?0apf-%FW z3rn@6Pw*I$cOlbLVSS`kTq}9k4Qz?a;5qZB?BmG;)n;_2gTnggdGoNTW$~M5UOE=? zw9%g{Oc;$(`2$kV-XH#OR7C=1moj%i*9RkrwoQ&5|8db)zc7np_V zso(Jm4th;bsaE}thEMgh@l>jnzP@OM>R{h{SJc8DDEVxIPhF=CkL9F-&ejcvqlaKl zD&%Zk95Fe(qhTstj1v_>C$BYH|K#xa53$vqrRzsFVuJ0|39R$a2CiuT!8EPo=C9p&n$xxpnj6= z7F7;Q6B3IV{1#(LhasnlrKkexx0@=+Sh73@Vvm(PVY^MCkg3@D+>FqgMu-Ru+QVZh z7(l%>qWvMz@qJj1K(~hNc9+v-_yLY3-6mPhDDyJ~EX7`|WLoRaH1bctF$-Y6{WVm7 zFsS^=G~+I;y7DepHdsTw2GmCm2NF%96L76mSaf1I&eRf}Y>;C{d>SbZo16DYw}=?d z*EKmls2R;0!)Xd&pE*U|AAHpTrit0DI`kQm)lpS`CKpA{!%Ao)h%O>n<0qo_m=fOT z1Ss+%Ps-a4DZrV_e@vD6&jSM!A!lwGyZAhN)dvT$$kE8oaj_r?fiH~&YwpY8>xyB1 zFKUX50Ir-3iBUF9cpY|c_W-z|>BxxlbJP$*hx^BH5gTHk3 zv3<%CJE2*?qZ5z1P7YaM(!@eTfNO(@G1?YY_T&n!*Mll7Vhp8*i(H=p+{zIIuJ6TE z(1C=brK?g_BQ^ff(u~-X%O}{M+Lt|1T{}*r^l)IcLR0-q)0qPxHM6ny!tl=lqvNd~ zj1H?yVnAvHgEW4}FJ3mCOTX`q;UPRn)0yJ4q=hcu82Ld3u9eGRXYolL@pheKu|4;g zkCmEsmwQF$0!{Bqi;bN#+D%&|OG_TOejM0~#>x=oM=q|m@-aLWTZ}cX1l)b_gD8@2&~BNQdP;!l5ZmLE0l+@%&)uQxKZ-R64--YOuaa26H?XBa6mCOpBXWh+_-M=5@advM`rMT85 zK^^Lwk5ydi<)j7o9VWbEw3bcwM6{O?lP}T zE}6L$I_pt?gO_K8P*UE6&FF<RmV<#+eK}P9D1n4-A>eNXCs6+ZD0Co2 literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-mobile.png b/resources/builtin/projects/fa-mobile.png new file mode 100644 index 0000000000000000000000000000000000000000..3147473cb701eabcf3e15c0ad154b7799e99f307 GIT binary patch literal 840 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k1xT_7rin5zF!Ou5IEGX(zP-D(F2qry?PI=Z zd3ifmdHHju4R)6lLiZe9Suov<_tpb}^LH+H?{+myKlkTZt!N0$}1~j13_-g zrf$NvIX!Gz$??ihx5PYuYV&^2G;MY_x7$}$rcW}>+-+o7%yX%B=ajee*p8ht49kBS zv}3!JwDNI{t*4fjtd$a#b`L!NG-%Irtz)c3UV2ZhC54aY>|`*rmYY!R*l?$_HF-yj zg0vj_iE9ZC+m0{>iSu~G$|&?6Y%n>-cu9oEBUnaZ-E{5nYr7_FS~cPIU51yZjzx-J zu5g&da5E*=XEviJ(~*~pR_)&4T@)*?@KR2pfq{twh1le3`FTRoEv6Iiqm$$=3pv!? zQ~o?hj`7oDsWZh{3{Q@S&VC-ki=u@^2E_n0^XSPf{Zm`M%Rz3|^DhDu=5N1Xv#hnq zo__*gZpb;CC3DP9F-}^=$kg$lfssYPf#GF9^R>)-?Q4UZt^PDI6a`fNR(x7|L!3jw zcUD%thw+t1%q$Z)zfCvcobbeP+b#P`d=8UXD;M?rRZjgXGC{@h+l~55aSoGMB$NMp zCNp>nEy?)r`4>p5WdHZHbl5c`j_or~B`})SCfsw*1ICl!nZPht83pbpOa4d!b`QlF z#$TI`PVD>saqF7SBGns#-KxAn?(%VO=f+K1y;oK$<>M0DBGsFX_usY4Owm61Eh6US zlo-!z>!Q|Pyu%;8c-N%6hBm1im#$fNa%su+DW=^MpOk1>`e|lwTvogC@r~@l<&IYK zqvIY(@zo#$Ifc63hm~--dLiT18_2g=gaR~;fdJC4li(3tjvk`s>)`sI zKpr9>tc=UiO&%P*f&4_vfRu5$J;&!_@7H?+aU5qr!adqKE+=KaRt(6e;d3nma%jfm z;LMkb0%KtesHb~)^l{Z0Uo2MkD#}T6w`s3Udu?H8p%ag)44qhTF{{dhixz&*%EIqeC8z{I^pjpo z;i`aKZa@^99CB3UCI{OFw3zAL$_=_q&*+P;BQ*?&Vx!!a!N)n+Hp(eGEddZshh;$8 zDj>GmTIF(w28cb5pmJG71H>NK(fK?k1#)KD^D!VR3xRw~YnXt1&rIIoCJtjwYC@;0 z{yF|vf%-vTqLvO@aVC#2o`o?K4)~T!SwZB~;tQNW<29EFHMZlmI7@5Xt%<6#g#gFT ztSC8`Etws2@tGgkP2zTSX&?tl_QE`pLV2cZs0q4>r%U0uR1#a8lS%=zhXhFKyc3M$ zZo&Uuov%_V@pq3TW%XDPj!PtW$JeP9!8}_szqzpRP=0`nG-BRPn3QLV2#00O;8|;#WAB=x-x809 z$VI%&WWMGL#`7F!vNcPq_lKnlBwMW{g2tq@fxHwMjuq2?<_# zU7`XqGkqW@+KVLz3&;f#0jUoIkPkRK8l92~5R(DHfS3%30SSAtwMmc`lO}CU8}uK@ z1~`*Plc-g(Y&s5?BhzA*t7;{?0gu~Q@;}Yw?9tiK{cC%0KmY&$f&l3M>u#h1$p8QV p0000000000000000000001m!;eBF$ViqZf8002ovPDHLkV1hpjN6r8M literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-phone.png b/resources/builtin/projects/fa-phone.png new file mode 100644 index 0000000000000000000000000000000000000000..ad5f77913fec1ea92cda5b2bba01bbc7e9c63903 GIT binary patch literal 1499 zcmV<11tj{3P)E21msoS`jb^SwB9=4B+t|cm%kf_{c+175#lvX$m>@14K1IXFGD*j=5^YI|q~WNeEoo5F zaMaM2)FWv)Droq4Oww_DfQFATl8)mcG!o>)^=Oce5tju^Q1jL?U0gOCgc|og1LCq`IBMDw63N5y9ctFel9%H$)TBD|BtOR# zqusm{#e$<`aOqoRgjjK0lY2wlFtOtp?{^gz44?b-dZBP4nz0&*6o~KfeOg=yJdS4S zBXJ?HhwmsU6q3x(ayVFA2>d7O?5?;Fn2cs@j<^u0_>&t7h0}d-7|WK21_NTx@g$nD zd&Qn(H`Gt<1wz6)e<)L-a5kE`Q^lI2H`l6qpICF;>bF1_3S-b5%@9|p+ju@FkwWn` z_Upu&<32xZ#dIF2P!?CHM`JD!TaJDj{&>H5#_Y;Edc~3>p@QbMC>?va^GR~5G8T;`+jq@MC|#ZRj&Rcb{q*G zqdB`+>^Mf!i0RpK{!|qE{}RW4(E^=I93@^xbGMXI_)B#LNjhUpQblw3P{=QfF+BF$ zGv}Egv12?9G?Jk`WRs65c^gTE}jZ6UU+{yOyqaFM+>B zjaooiGGjX0MC&<{lEjEXR-;B$n34Hb)pZ%RgwK~4F`A92S=W(dICQ>`X6jkSOMI9_ z9X0FoX8%uEnsXXwKw`rT8mM8*>64T=70un%bW2>AZTyqeIW^5`mwBj3HBKUtm@p4D z?(-ep_s&GqgJp%iBqr>Hns@KEkMN9OJ!;(ROp|ypp9X4NgVQL<78phq4bqd0^>ay+ z2QS968V%S@bj5SURYwE#J_pnD>$u}IG zR(K(`FFT`$ zhtYy}m~<8nrG^%`KIt^{axYrY?w8KQZdA|$Hd#6q31=5>e6mzJ8~rRt3)5GW#WAKJ zXOuMziu(oQc?ccSs*Di#XN(!bvHaWgiQ5uAoHGQY`2{56wuOY|uTg+svsXlAWWU6Zsr9sLlm+iL=0XuE}*3R^kEJ000002=ccc Bx!nK& literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-pie-chart.png b/resources/builtin/projects/fa-pie-chart.png new file mode 100644 index 0000000000000000000000000000000000000000..23fefc60c3bdc3a336b792d777ac960cc6f4854b GIT binary patch literal 1587 zcmV-32F&@1P)R z+Jk?-ee?{~7{(EPLjGarvIvq|FXQ`fB&fhxo*{*^0U{hC=_#tRlwXk4tb+)j#Q4(1 zYYgQJBsDc4LOzY-h*6#$NNVapQX3L4j9Oek5XB(El=yry&LN0;5MfCi&Ws%h;s}Va zBHG`k22p@G1tQFjDn~^gAc%7y!k8$2HYOm5qaZ@ZsGS?v5T`+eiqYX{NL4)(>7ondO6);S=s!Q=1tJ7`Kz1W| zkoWXF-4z56(pd}02s}t?>$N<;`U(${+Q<sv#ak(Xq}74^p@{G+eNL@gRk(tLqNL zgLKmMx{n7LVISm$2l>Mm+vZ3jf0ze3U>l^S2l>;k>bghwAP;PV9QPo9+9$R_e(@lG z+E2=kbOj)Jykc{9LCUHE@zKJgJcz2e<3Uu#3lE|yzVRTc zBHt>=$K;qakwdQ41@U^4mD+`LB$T!M_Zu5N$QOupl0YrVi10z4Al7#-ElD|xBm=?+ zxrr#)nIcGjMXaoA_#j6R6+5kxq?xsM78UGNT9WcsNNR=;G6qqz4NCQOGj;JC@gb(sIqHKrLl2qW=NWXtV4x(-cl#pyt@_13f_LERR(%%lq4n*Ph zr6s8t3P~+RuQ@2#9_u7|c0kG_O1HZRl6)kK`^?yh08zUg7D*N;{EZU@+h&cVfjy8u zh~jOrM3S@z@;2fyNu{iiTrxJ}3*{smLnrC1`h`*j+mM!|a>hwswhQtuqJHZ`BspVj z$9+Wo))*5KNfY}ZT@VMhIuw$h2<(F-DR6>hMF=DljE0zlII(3WO;pJM$t(JQ zwwUP@$()Rm{6tb8NG{(xMKUvkBwdZhXn{Dj8756sD>lhB5=LhncZ_6OMo8W^TH`hH z9V3}y(nR%Qkc=>zqdnr-CYOrj0tur#wmC;Kp~NIV@v_k#xqJ~Zk{bU?QqQ;$?^EC$ z$=DK*j4-Z5E5x~tF=?Xa-$=F?mtu;8BqNJY!WjbNR%~#PWJEDZ?vra=iv;@}BpF%^ zk|!jMixF_zL6ROtkUSyJxEcW`9OJlO)PFY#<8lP-afss*xhCq7V7((8M+i(jVibZn z@TPoxq6zuRzg@*G-r<>2jBluF;urxd6mpy(Y2q7A`AHSWC=w>#kz|t+j5EAte5t6# z$Cfd^r6D06tl6qS!$`twbeDSlxR zd8WAeNKi9t@2gy(S&5!f`AE{10~w^aLAO$0qf7+`90RR91073rNgIp3# lmjD0&000000000000^xSFBZGvl;Z#Z002ovPDHLkV1ljX#0vlb literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-rebel.png b/resources/builtin/projects/fa-rebel.png new file mode 100644 index 0000000000000000000000000000000000000000..1ada36553be284ab478c96fc479839796e7ecde6 GIT binary patch literal 2394 zcmV-g38nUlP)Z0@O;kFe30000000000003`gvgu>*uAk$!`Y?)rS7tj6Q<=HpGPj{J zGc&hNnKNZZms`(UW+sovWsk=h?>zt0d1pKYud`Z7tDC*juFmJ@G|hr^LDE__D&i!B zxXp^P5G&E&&Nbf^u|1mNNGtLgvlvGe_Ap-+(Zw*DW`YG)Ug<+MTzWW31d6NG1gkK4`V!FiQ{~f&_$Lw)*&9Fy>(^~ z7bAY4%@Ri&BPfCI2&|5H0x`rwYyRkD03jAxU9l%hV3)f8FaKzX#Y*Ndl6Ik-r%_BV zS>3T0n$%Cpnl*O$dxZ1_rBo}tifNIhhzHQ5H|cEl>D)p~75AbT-b{UP9YvFdm~G7# zr=Y)GVJTw)ieV3jdy$*i#hNM3oU%CHW(nd{USk`Z7Vn}6qm-;7+PNm_zB_NCe;s1Y z66d0S9Z=U{?vBb?0SBN67h6Rv`Fq@SLBc_ZrZ~l#AjzX=`U^S)OBG zG{r*}J7zM9HgitJ2{&ASDvn*x={GNObIfKzP?H{tyVn#ckM{hjw7Ya4Q%#1ZC)G*x^GghN%cDB4li9u8$ z=H!ZiH&IQOnVInz3RN=W2vpPOw8j2_OrQ$mxtl7|k19M6`;B}IMLNcei&2PgDo1Fc zUL&wracPxrSf}MDR-kDX#(qN%Wf(^GzjZRTxCmXGMEd^r-& zKT52Qd_lkC92DYu-bOWjlXUZ#=fVdVnU7b|G^;FObn+0Ysfn}8W5}^h>}_>KQ1v@IN@w;DR}*NOjVUgL7(@>J${edRuBm>$vTVoWZok+B z+=m<)qBqqvS5@t5SuJ$1*_nPr%7GDjQ_if$LIwz>>`n%U&}QCs@ZWtJCFgo7#|@~e z!z`O|6sqD3OC9YDqg3{Ba!r7$`klbC7i}S{OFNo_*cPR*!5l<@Laepy#i^*O4s#NZ zq&R!DnUi=abpIvD-uGiu^%uk8HC?LH9xmrtA&#+Z#adL=1LiCqLv{F{Ig1@?%y5Ei zjjw)1Rh?kYVgX9d<=zF|DAdwyK22eZuJ-UIO6V(d8f6sXUCT~<9DVhNi&%;hI^3Mb z7bw(x%SOyap?Vz;9m*(?c8kd2Snn3gMqGwMb+~^)5_rNK$Bi{tk^}P}LCwviz?{Z1 zl)wse92cM(b~OL78wzKRqZ=jA*?{S9*7gwD;OY%=a9XYOjX94~qA&6G8YRXX{DxeL zV!EW^Z-|&@eq%e-;5TG%6w_X24L*m6qs(dUZ&VJyhdGWe6vG+jJdQ_^J~8(>9f0m_ zjw3)ZoMz5r07dgUDfIId_Vb3&hGOY3Kd}l`YSf~%pFR<~W{5 zv21UC;!gM1eKjf`H8ntO!GbLi42(2xCX_v-u%RnpRH8pp%_LSe+bGb zrgO|slu>N+J)B(I+}>3j+ZDdHrj)=l?w>9cX||`!ST~rDXm@i%K=OFE;eX>GN?@bM zrS}AWrOg~f2a4$ia}r0RM4r#b8zOFYecN1wzsy0*Vge=dT3+4|v9tl(Q%)~AAmAI6 z&`bGwLnfH%cBMDMWtK8FqQsu@eo{~18`@l6R1sl|6=s{q%a)Rvf^SdUV>fFN=-cRot(2WCbN<487bVK5LLo4p z@dPSN@v-@hBT!+A3(RlKK!r>_?WAI!TWHJD(?|<%n*W%E{#ICLS%^Q z7V)a(A-Y=Rur)!i1{+u|Mdtd_@m`pr*Bh8 zXB>!{&_>H|oP?Up+XR;9xB@kiuV}Zt$Hk~gjL>7v5N9;W+cDFcCDx;y`sM_|nwZ9If>i|_OMonZ5TqC_dK1}DiLsL zalc^3Vjl0IOnRBEtQDigF>K1**3)up<>;m#Wki_^XtyHz*nqsdF*~#I;!WwVa@Htf z1~*V{_*~-@IxVas+BupZQ9}%{jKGSbV-c4#xTRqR)!z zkF8iqKO-oGQ66G7+YnfhtLS1oj-sDI#!(Do3~(h!up_-zv}L1>KIXF{OE`c-If~UB z$-%5-345>&GwJ+)`*c76004pj=>O|(q{0WHE&u=k000000002M0e($1n3r1pP5=M^ M07*qoM6N<$g6XAmHUIzs literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-reddit-alien.png b/resources/builtin/projects/fa-reddit-alien.png new file mode 100644 index 0000000000000000000000000000000000000000..897eca4f39d7c13e27dbf7058037f22b20c0be80 GIT binary patch literal 2238 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 D@=qX= literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-safari.png b/resources/builtin/projects/fa-safari.png new file mode 100644 index 0000000000000000000000000000000000000000..fc056a738800f13e5c18d395741fda2b2376f6ae GIT binary patch literal 3632 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 P00000NkvXXu0mjf?aMlv literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-server.png b/resources/builtin/projects/fa-server.png new file mode 100644 index 0000000000000000000000000000000000000000..3369e094b7201aff07682c2ac935f9a13d873b63 GIT binary patch literal 714 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k1xT_7rin5zFirGyaSW+oe0$e*+g&$-hQ!!Z zk!OhojA?22nr8w*CU;sjYg*Zv4a<#!7hO**Re%0F>)z!5i7)SjeU$^6f&vugEjh-a zbfUhNMbJgSu}7haqez|aXx9zF=PW1f)gQIL2w8vR`9{YHbBv$+_Lwg!x6v~7`2J(j zkC*?ds zJ%48Z*5j*Ivl$-O)4o3E$JcVtD;p0L89uk^;{51)B~*0o4~w>=skiT4JI1W#2zEb< zVH3xu151`M0sZ)I{hLiX;;bNVu?QaFQ0h?l{-|J0M{Hr-gg?b1lHRvbLRu5!o!E9N1+NgHCr)jbAn{@(?YN~#J11DU%Csyk(@IF{y zqobRdrPJ@z9obxV!6%QO?0kNU4;m-`!>1`s7ZztY-%jD*$&qh5is!XgIH-0269zB@frQ6Gl=K7Q%wy7d^RD&x RYJN8m&(qb9i=sHbbH;wQZQHhO+qP}nwr#(c zN@{P}n$}yw9M{n7qLK;gJ)uEbFkj;x(xRDB{^S+*BUv4ADLx?imRXCB?eKxg zcMMx}EQJqHj?UnNWLEjs;^P&3aANUsq6!Ix4OB=dOsSAy_)mp|!aXV^6!udgp|FYy z358J=5)9v}kWjcxg%s1wSB0>&3JHazLW1En6%q<3sgO|EP=#pbt3ovMwff**6%q>j ztB_DwRfUAYs0s;&?^H-AT&_YwVS5!)Ofz2Bz9#zmSLP^d1J?LTf9EPdF;<-ti&`!HfUG|uQ31c3fFQpJFpf@ zGTQGIKqJP_xQ8>?n~hkW$&PP7!dv)a%5OZw@Q+u}jzRPW##BNGx#=Mm#SyvB7L!w#&)Qj2i`7Mcau|Gk{aK5WbiT7dhC2k{O$*d)}< z_d%0TGvB63u$k|qNvN6cS|*`x{l^k`$Gl|{>Z?GTne-nk z;T`isC9^8wCA?!EVvE4pl$A&pijH{soy{y5eU)?%%L$Ws?K5ZjV4n;MInVOJvl$ff zndO5&GbrRw3q||NJ!PTjpvfIAA0)oQYn`_q_2d%yL6wKVGMa*D6h3V^5Oh zi&eOVHa?#RSTD@M{14&tX>k)PTizHgIOOFyrmRxT6bwJ_V#IRAEZ^b<`ID6@ebxSj z7vw8ubG@JbJ5F)hEMt{mIob<6>@c3=lKx(a2aQK7c^mzy#D98|m5|@wq!))h*Lpw8 z2}7l~Q=aboV(z8#4?|WU@7;j*3%jfEhE^c&Z7^R6JNCTH%FF2F=(hD0?LJ&8@$frd zIw|O*+P_&o_#uNrz8lP2xc`NC>akOv8O$ft?+g3&q*JWCj84Vf*7}O=@RC`@@`v1Bal>z_&000000000000000 a0A~$mLg=u5GZhH{0000U;11zj+eY zKPm4OwqM+LYhjVA>p8=(;Sx7mG}ceJwqB(LJMlXP&h^&aSs8 ztji}o;epVi)?*6GnWhWGhNoEj@khC+K2xwfx5`;$rvJRnTpS7w3`{^mz=1)rfx(Hv zkV}C@z=1=7jj;tN&d4GFk_4+@_;gf8<#c3ehhAhe%MsOCSv;G}74!m~lPBmg7Iue8 z7tP`9$ewc1Qn}Avi{(g5%38+bjJL)2*i84ix^z(-%k&q!#8#O;H)zZF;?FRR?Y}$3 zK8Q64yIdBoS~*Wj>inJg4Q~RRKd)Tfbm&XMmaA%0H9pnYWiE~S(I4pBF0wSEY}Er} zcjdi-Q#MsDW7}7B<&wIq=A80XFP~rjA?vC+_chmFX32FLM~%x}*Lps2r|dbn+-KVS)SK~(6OCZrM0gm^3VGMp%I*4h-;>$vG8?19 zio845{r#)PzV(Vt?B(rBRr_8{TDB^1lZ52tSljBU#TkaTOBc=gCh=uWsG4P;ahK1t z#!q~@YPTDvT(@03ulUrD{U=|!T>8DKd@Ui39M;-#+omH+Fb zoW2(R`utq4ly8;Wl+btc)o0guZ?b(-U0t96$|DLV?pL)ku3|>y7Z8gn>a{)Z7h#So OAdaW2pUXO@geCxHTxgpB literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-star.png b/resources/builtin/projects/fa-star.png new file mode 100644 index 0000000000000000000000000000000000000000..02b66e7ef25ad6dd932f6c837336c7ff261267fc GIT binary patch literal 1574 zcmV+>2HE+EP)}2w2n3*gX&2O5XAprk4gdfE0000000000Kwf?-&8|5ZT^2?`aBYXPwr$(C9mWQ* zIjpT)lT)vLKEL~^Fx?sSsVSb%9A%tq6o>J=L<7DkeiFkKG{Su@QWWN)2B*17L3oZD zJnt%{_tEH7mnj5~Q43GIOc9ua8udmB!UNRC6RwjTW}^;HaiPp`2X*k63uT2_sG}8= zT`42nLR~!UO4(p0>T1O#m&yd!Q4j8SsVp!ZHR_ENgv+Q$_qbMan1*`x7ZY79F`P$z zxZB0b?xWEkNjG9Rjrw%Et0jY}sBeET!Q~Rc2~@)^E|&x*qgsAXvJt~kRMU;Fmtr3k zs_9q8yI^EEgaTaef>B`-6$aWQF&@?R5hWce{RAfJcdNVzyN?1zg{I|L-f5!BPqMjXs_ ze27ax?{YN`IF04j7c|Y@qHYV7KGkBC=amw^F4|6KpGfFEt zxglyRqin~?Jiw1QL;8+;If1PiqJ^x4S@fN`g>NSx7xX39u`PAdCZ&S*O9RJl1s)W% zQSw0EFYuh82a^Z#X@TbiJt=DzJ!tPV${tHig9Lq@N&?BcxJ4B7Cj)5(zPsWUC}_1b zQ^OqsfI0e;(X_Mmt#FeH`h!6Um8?wzipi?*aw)~d^$0kArB715cP-;Mex_Sm34Ve< z&EoihWfHq0BSw*YN4wNU)k^*_n3cCmZr=_VE2w-)v-FO74?mm1@u?TrO6WAwSO3r( z(| z@gzC_=iT2_gX0mhI_BSBRe|GvvU>a&p7$QdU1W8wI6v(*j$6s-+p2xkTO2p2!!e2E z0WWb}r4q*^l6$`PATpKRMiBdRB$@!vj z92w4g36RuNVqw2zg-sxbhy}8(O(1uO1#+fMAU}u&@}f{-rK(4Wb zBjdpW_2-s=G~zr^&JK_vFMuqw17t@pfUFw^9AxQWJ3!v>0?2JvaAbWkm9YY(73Ya+ zYyer!8z4P4fb8WBkd18sxyl92B8f?rvlkF)27WLMzU#^aHsiBA4}p$rtcfIVmC_ zr>O@L$&tO2s4b!AauKd-J*yo@zWNci(w#tQt9s-2PcpiJbXRF{(N@7H-iNC~jkorUDJ;%Nk6hH*_a*f4k|gHZ_x{6^OAD# zgUBWHdp)5fAQNhVlu*z(f!buPo=X@>+EXu(2MWhCG^8|iah=gPtAH2$b?Gk1(8aw= zzfCWY#oc@FrAx%?mh)tRim#D1ohMl?>V;#xhMT7?t&GUM#<)=1s1Ik~C{(@v$y$6l z>7%}e=!K$%I000E}TMu$|0RR910000000000 Y1R^s0_kSRDS^xk507*qoM6N<$f&m@d>;M1& literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-tablet.png b/resources/builtin/projects/fa-tablet.png new file mode 100644 index 0000000000000000000000000000000000000000..263e50d73391b6d3bebcad4a88515b47081fbb82 GIT binary patch literal 761 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k1xT_7rin5zFdgu8aSW+oe0#%m9;>Uw(TiDk zRF8)@sPFLZs_xo-JM7q{pS}Jq!q?~Nxm2io*zc=)UO&BH*XpI2dnc)QqM)M4yz{$n zp1J#AQyq4c0F^|L(7pg7r(|>b0Ud^HgrHb^2*mn#L?jUlzX^t6lqc?^3=KQx-q8=ixWn%B1^$ z@1GOz>*m@_*mq%F-qusxFS*~g@0s?y{+{+vz1oGgw^vQoj9u*oXdOYQHak||JzkRw#Kjd!vT=(wGQ(u%6 fr{Z}j>Z|bKAd|&brp3X)B+cOI>gTe~DWM4fi7hhl literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-tag.png b/resources/builtin/projects/fa-tag.png new file mode 100644 index 0000000000000000000000000000000000000000..558fbc40fbd8608a2fb5ac04ef7026ae366f0259 GIT binary patch literal 1070 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k1xT_7rin5zFn{%QaSW+od~>i7D8|sR;O|QD zl}sQe1f)HmcWcSXCJnCeXX*X9x3|I28ufpdrFQRHb?(fZGk0st*8JYlvHgmS_hFr~ zN0my!@rA~}H;X*Bo_FxD$~gt8S9aGDoAU3aM|9|SwC!%Ftob?b@F^GXyT^t0{lDK< z`9esyOnP(l!|#bQ^99zH3ry9mW4zfu;e}^fiA~RP?~X5`+!86SPAl|IPvhV z28GY}xqJ)LmP`qIbnYxCP-y1F9mULtR4g5z`QF(neKBD5bk0pRkIn^yoZIAf ztbSCr=;$>aZj~G92jXYl@e@$X*e0>8(7v0{Rj2i``0c{5!$BMV#FET$#mOc=99e1 z9=xjsT(>RM@;J(_Hc@Ju0#MF$zL@u>iE1aUTEf&ScO^{f6?J^3;PdGHpI2Ktl}`Qy zD$~j{?7R|Cyxr4BX@Y0T?JFuwGhKFH^;vZF`^aE$QtTx?Z;`6C%R-5Ot znM?fZE*hQWi{ewWT(j8v%AIhT6LwK-YBznn52$!&+`X@|_0n74qRwkieT}?dzEZOc zl31XAk~w+Sm9mEgT{!GH* z(+bN|Kr=)-EthzlQFQ&}#nj&Z(I$&8SE!g{f=wDUP)zZ1b>$yX zOk)Odf}2$?UtuFdsb?JB`4$)Z`I?#3_2PHpbhXPLnNNKw)L4eg<9U)c;)!w=bFlz)p$?0icT|DS?&%JM9& zr4XVAF41$FPU4M8%JM$_B>S-sm-y)+-WaYfhfCJuL!6NW6xVS^5>Pmtkr;@PV zb2y;~vgPk_2%arbxWel=J%DNa6-@RMOD19Fd3j4kN+kcn;Bp z(q9(E)MqT8=^GC4WWRW$OkGw=XfZym4Eo0ciqz#<2`?t39^|FSH=8d?h%qtcAjcv7*fWwzkvZ0ho{<yRynqb zrQD*8ljF8={Kr^ZV~)9zId*zx7VB!nF;BeFO6AxkdPZU#X(pL(93hb`h|IA^^ei^$ z2>MN1TB;m-CATa#Ccv>za?fIuaiouAv3R3`n-QLDqGho;>OFMje>onM*s~vDO;?sf zxSxj~&RX>4EbbrYYubw%&H46U%d_;8nq^VUFrNJFd$rd&MPG_?Toy5$7k*pb=5dBn zEHP#&kpKVy literal 1009 zcmV4R|9DomP)slu*wbjMa)*eDFK|~_FNHh|mZ~O^fgz)Y`JQA@aB0?-}NQG#dS|23# zot7%K)m}?@q4IgqJNL}Yotk^^oHL_2-+lbe+~0gNXU_H;Aq)nC!C){L3_3YWOZS(@0+8VbVIn8j=S^Nl@B=s7csYMP~3 zH>X$Kgl4JifMtiELY+ea2&4JOL4S+$|y;t)}gX0np2d-v{R;81^S2z>Uct_MiqYb5tXDi z9#UBlmq;ooRG|U2Jf_&nRjW{ib*Sc1OodG9Tq-Mr5-Ce-)$Uhiqz;vO)YD3lauupH zJQHZqp|TAfv`GDzGL@me7PRT|AimA5OopLc)1s0usT_BytO!D77}qtZG)Wl;)9Q%+ z2&RGMazlg4LMh{FXE3O)IFFmkMK(+MiWG?mK_0gii|mlH4NxW`1jD(bRAi%+t3siO z5ae@LnMQZKsv-m%l!^$!2<|Bo*&<~rr^`9*4}RrXzaLe*ALAuWN5#5G1bD#21|LXAq1YwS&(gOWz8SKUjUiu>NB#vw91Z%(I{ z$~?sZXdJOL3SDpB8@WSPtJ0RHMlG418gH4T^D~bpX=v108U;LX#NIJkZ#BM*_7pXa z#WaL)jZE*EBJ{&3o+T-9f-KKz&j+T8uwXPDNobs8fagT?Bhy5fFqY>&HBQ+y>`Q}B zOc!B8IWK%@oF-dZ;oP#tx|kuN02RFaheo5Mk?UAw%oI_A zah~OfW}Ak6i|GrqMbuzCoe4C~FsPSJzd0g`Fo8FY3q2=kJp!+r00000NkvXXu0mjftsu{M diff --git a/resources/builtin/projects/fa-trash-o.png b/resources/builtin/projects/fa-trash-o.png index 909c1e4135f3d6803eb31c6ec083832b09166af2..03c0f0362a97a3f762aa867c2df6b67fc21c85d7 100644 GIT binary patch literal 1714 zcmcgseKga17@xI+qzDsnGucnrRN7KrR#V<4?=KTgC7O#ip<16~s#2pXZc-Vi#jzp@&&(oKIr z*-$8&e0WBFC+5wtV(ByM$*hxea&g_n&SWZ2rTWA3*07gA9FQnYNet3$KbaT;Kza|p z?+}ysFhBi(vO2-zG$+9&hGr_Y9!}sxP*}PZseZUM4 zzgvM_;b=`ttfR46E0VQ}NLmMysrjtWzYhM|$!hXhysZc+HAdUsnJat2e6e!o zTLhk2(@(gE-Cw{=a~#vF(qXi@v@(kVO$!zv{&HBmCoV}L0A}(}Fh-vw;*>4vSJ&s@ zJX3WF{;0POH3g%on*f^4uOCVS`elZQBxL7-7J+{APdn;G$jiBq=0bS~O^`KlId-R2 zC?f|F=qc`yJ5fNZP|Uh}w%>R_xBD?cAZB^VnnSb$WiF%%Jq0ARb7B*3Bq}a|`IdC% zQ)yqQou6@M`B(x#KR|Y7P<|nPnVr*PzA*c2a9;^^2<=A_?DY^y#*8+1Sy2Z~Lptq> zoYxke_J}_;+O%mn|Q#-Ga<_6BP_?e-sx}#_}8GL1tA((XMN% z6eph>^oQDc2CemMAL&BddJQ+#_q~*2sQU=_ZIcvERfXl5n&Z1oyr!Sw{<3yYNXR4{ z&33~)o;rwSr24m-Ai9$J)3KI-Phl9p0uvx0a&|Vo7OrS~zb9g2z!KvCTkS5~ zc`(#f@a0nk5tX9-DSkc*Y?8DD9*Xu!U8;ShSJlQlWVB^Ieq81HqPSlISz%?;x|{gr zIo1FCr^3HV|BrxYYA&*d);q?4vln&*{65s=%-SSX&36R<*+E7D^a1>B5i8)~BdN@m zkDnqUB^p+}BZ~6s9rdq69?IMz9KKMFsQs{vK5NGJJUGHgn5Jz%88o_ISQ*U?do)h; z1!}Jy=rI`Koy7)yt&S7*u$NQ~9|;7V7^um7ms%Ok`Nm@TQrd2T*0*EbMi=krdE2cj zGVLzy_+avx(fytiCALd^-flzXua3})WXU_uAF_{f2J2I3cn7Ws_;`$==oD>$ zFr27nLgI5CwA;oghK&D+X{Mg)8`1F$&%a5lh5WMWt{*vd?q_O{)(X(Y}mpLr<~@5mh;T#l1FJbKzI(J&&5R#;Ex4ZdwF3!lQ^ z;-@Ff)-{eMs}_ilEJiYM4~PK>hp92iI@_x4i(R6rZKShy3RCfTrG1BaBU+cVt)2kB z=p$$}JeICkw!b=2Bks6e+)|gf;4OD>jH}|O@R^qa;v!JsxEzCSHK!+Dvn>Z|aP<}v z4dX_#`bLtRRRXOBpNtF3I&Yw7zy%?{q@Uo83^(a^le21|GEg2mo3H2u=~BnwK<+_K&j{ zuvmr!3;Oa3vN&cxc#)v0r|Ypuc^F{KuF7NmP=E}aqtB9i);UzNNFJ0abEMp(s~@uXj;{;!v_ zdFLx;m%P|Mp=tdDLpg~h?nZS^UOcy!&7a`yQ|?oC_f%2e%Tw+rgans)oj)u3DB>G` zQOnDlzwYioTJlCZrAyvt_qDgOKDx{PHoZywm2zm8?K$>ke*+y>x$Mw-q-5*Sa(dAh zg>{#OH~OA^nZM-KgZR^*e#q7>QfT5(>QLA`Wo1BG+kqmf`9C>Ve!j2W_|(Miv#^l) zk7W>fu%af8OaDQNL7aD6OD?bQ&T(Yf=qnv;C+H>@d|CI2Y_OrAhv4PO(H^{)O?NJo zw9GS@yR$WCa@gxU#mG31#nnc6ij1svp1Z_WFRp0L>o)Vew!~yrIHS1bQpXb;T1_kx j8xLq6IS8`@$?E!go?p&2{Px>`vBco%>gTe~DWM4f;YPqG diff --git a/resources/builtin/projects/fa-truck.png b/resources/builtin/projects/fa-truck.png index 2a0333c3ae09c7456f5425dce59e129da1260c88..bb67c3157a17997476a0a0ad32a923d254f40191 100644 GIT binary patch literal 1326 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k1xT_7rin5zuzdA&aSW+od~>i7D8|sR;O|QD zl}sQe5|}Y}x7%c;oD zPq2{@{$rye*{%?2u`XPuX~{DI75jFDr^#IFxh+^$miIi@GfXkp=5v&izRd*`sP=iN zZs@XI3n(CC4N_5GqxnE!$veZv4bBsO9p_4#kSAWi5oB~txY^{ke)RHRiw*bxwM$FR z*AsB`d&VUAL}#L=qo3eRp(hqV2A}Y>H(J`kO>fkE5FUoGP&^F`j3X?PR*pUs779Zd zioz-KffxMu3B3Gu=)72yL1%M~lG{~tzRgR1CBDdickZC)G?k9S``5jlyY=ne&AGSt zUAVdJXWWCE&u(tZ{TFD_O9t=W7GK7WMlKpW^1z^yd37-!GQm|34t` zXF=7wEAywTmrT*{*lm-z`g!1YhO6wyit}pcPf(vB#A^7dh23UP?$YqDEn&ZArs;o6 z=+jjDpZ`CiX|Lsnt5W^Ol2_#Tt2sHsqn9twe0FoP?aU?9LwdRH-{OmJRDL4EdT=L@ zO6>l6y^HzY22pjU`$6SRO%GgFU+1elr5$i7Zu z+2Q}m{WSNr=(W|NEPKP&zkbTv9<^3KP-eq}9|AKzZkW66)<4fh3LY{?zhvs)KEGyL zaTjyY@ogWh`dR<#u70|i>)6MaAIuF~y_P3bHLi1x&lQuOtih!7TPS;XzwOEi9um7O+H!aN|0aHE)!N+skN(-;wrJDqadB$3 z-O*nESAVN(!*BOmkbc^RlNAdb;rAH6RhqWI+^1ejN&BDOqtG?&zI04@O zhkn;}iRy89{SmJUDSh$u`hpeb!p;<=Hpn!u;_PAZC|a4+ewo`Z%yyOJ7qK}z{KAY6 znB0FJd&)Drt}r+B+>CvxL1&rP+Du4ZWfisbfT88Gb=4kMV+@WwI?A&MtlGO literal 553 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 literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-user-secret.png b/resources/builtin/projects/fa-user-secret.png new file mode 100644 index 0000000000000000000000000000000000000000..c84267103cdad1f4be3012538fa1e6d37b93b49a GIT binary patch literal 2108 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 Vb~KQP8{+@~002ovPDHLkV1g_bn?e8p literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/fa-wheelchair.png b/resources/builtin/projects/fa-wheelchair.png new file mode 100644 index 0000000000000000000000000000000000000000..602f744a46c9e3bf7e9de07f86770a0914306715 GIT binary patch literal 1905 zcmV-%2afoOP)9s8 zwU!>?7(8KqZ|MtAb>LPOilR`HfXztqPI>X7VW>%;{Ev=_*KuheQK;*eWm#59F83>1R4k{(*=y z@o++0v~=Ks%rI#LO5B3iNSjsQ$H4DdXVQ>z+);Z>2JKdX=d>r1RyppeQH=YUY(K-L zf!}$tNy?*N-)FG}ae($jvY!!m0;NPlm4CGU5VlmE<}u`QL$FSY&<6CS|9N$o^q~dthEB# zVrNueO_cnGIn~U!fsaG+V4kI9ea69f2Kkas8`$WHz4V@>H_e&kFdNvo5D#XdCBhs$ zll(}R4P1pR`de7RYv{^!w_(46=PjutK>|P(4Bvygfb8@}VA~r%+q2>Jet)fpl77v3el)NOeBYz71T~Tq_v%FtSB@gzuW+5E{F(5n9W~sz|3O>J~wtzeLX_Nl9=Zor#HhfpmKo^x(@qU$=BgA&Pm|H7iLDHr6uy3UuhTUhNLIe{K)E*y&o z^Av3v-(q}$2eZ{`APTO`Po&414{fn;LAZmGWrPyX;laF2)Td9wFDw4kN%UB=VhJ9T z%ZV~7$L)Ab#`d|xPUTyiFFA~!fjiOq^7Oleb{@rJa!AtB+CV@%AL9A^$3+(};xT!F zlC>tLRQsBma*89=-oaz?ErYFfvAgQ<$+;QsTjsbHD(ntPAcs=22BOT}c$NI#S{)HL z;8pS#GaL4kHt;oGB}bT;QQ}^_YOZ8>1GdIqz^mp=`xl|DW=WiD7+ZH|EaF+bMouHL z|D!Is5wDpS*iJd&{nWmJFGuQMdFZuyfjq{am`X>D5AOvW8D8fE(rY0?Z^D`EcXBMf zY-R-uS;#Wh^E*!D-b6z&zhIih5vKAno^}!}KZOpi!86LfL{^)yjL-0t^CDwR`igc= z!c)t)>`vSp!Z5DIQ^*N)T787ET;9<6?MKjK{UZ$FK)%5HnYZXwXEY2Eb2x|Z@H+At z$1>g|m9k9aH{99hkM8T)$q17S3NwUR?BsARC5@WoRe4!Io+PcG%az6Y09sQZ_*C3({qM}^k0=zpH6zs|}{tuGD- ztz+{Kn{Z^>0*PLUV{URR{{9nK{%dC+W%>3|slusACH4mki=c~uBO0;D3S9(E0nuE` zIjy&+{|bNdxM0upU-yl{z%2FQwPpWA?Kf%O`#gJ>{ag;E4uvMF6O*0_yG&@hvP@ok z$GlVl$3rJR*x3iP>YaJGMS;;{oAO!f8sEq$<4)#10xFv-y3cF63A=4*ZEtcB%l}~5 zy29B$tSETG38lmAe>_BY8TM}mN@PN!I7Z%aQ3ojY_pd)6CdV!G_?L))%A<nyYAoglPHE#wW&WoAv$2ysi?CYwAh@*O!Z&l{~ID? '85ee8ce6', 'rsrc/css/application/owners/owners-path-editor.css' => '2f00933b', 'rsrc/css/application/paste/paste.css' => 'a5157c48', - 'rsrc/css/application/people/people-profile.css' => '8f894dee', + 'rsrc/css/application/people/people-profile.css' => 'fa2069ec', 'rsrc/css/application/phame/phame.css' => 'dac8fdf2', 'rsrc/css/application/pholio/pholio-edit.css' => '3ad9d1ee', 'rsrc/css/application/pholio/pholio-inline-comments.css' => '8e545e49', @@ -730,7 +730,7 @@ return array( 'owners-path-editor-css' => '2f00933b', 'paste-css' => 'a5157c48', 'path-typeahead' => 'f7fc67ec', - 'people-profile-css' => '8f894dee', + 'people-profile-css' => 'fa2069ec', 'phabricator-action-list-view-css' => 'c5eba19d', 'phabricator-application-launch-view-css' => '95351601', 'phabricator-busy' => '59a7976a', diff --git a/src/applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php b/src/applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php index 5e12832cac..0298053d01 100644 --- a/src/applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php +++ b/src/applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php @@ -130,9 +130,9 @@ final class PhabricatorFilesComposeIconBuiltinFile $icon_img = imagecreatefromstring($data); - $canvas = imagecreatetruecolor(100, 100); + $canvas = imagecreatetruecolor(200, 200); imagefill($canvas, 0, 0, $color_const); - imagecopy($canvas, $icon_img, 0, 0, 0, 0, 100, 100); + imagecopy($canvas, $icon_img, 0, 0, 0, 0, 200, 200); return PhabricatorImageTransformer::saveImageDataInAnyFormat( $canvas, @@ -141,78 +141,71 @@ final class PhabricatorFilesComposeIconBuiltinFile private static function getIconQuips() { return array( - '8ball' => pht('Take a Risk'), - 'alien' => pht('Foreign Interface'), - 'announce' => pht('Louder is Better'), - 'art' => pht('Unique Snowflake'), - 'award' => pht('Shooting Star'), - 'bacon' => pht('Healthy Vegetables'), - 'bandaid' => pht('Durable Infrastructure'), - 'beer' => pht('Healthy Vegetable Juice'), - 'bomb' => pht('Imminent Success'), - 'briefcase' => pht('Adventure Pack'), - 'bug' => pht('Costumed Egg'), - 'calendar' => pht('Everyone Loves Meetings'), - 'cloud' => pht('Water Cycle'), - 'coffee' => pht('Half-Whip Nonfat Soy Latte'), - 'creditcard' => pht('Expense It'), - 'death' => pht('Calcium Promotes Bone Health'), - 'desktop' => pht('Magical Portal'), - 'dropbox' => pht('Cardboard Box'), - 'education' => pht('Debt'), - 'experimental' => pht('CAUTION: Dangerous Chemicals'), - 'facebook' => pht('Popular Social Network'), - 'facility' => pht('Pollution Solves Problems'), - 'film' => pht('Actual Physical Film'), - 'forked' => pht('You Can\'t Eat Soup'), - 'games' => pht('Serious Business'), - 'ghost' => pht('Haunted'), - 'gift' => pht('Surprise!'), - 'globe' => pht('Scanner Sweep'), - 'golf' => pht('Business Meeting'), - 'heart' => pht('Undergoing a Major Surgery'), - 'intergalactic' => pht('Jupiter'), - 'lock' => pht('Extremely Secret'), - 'mail' => pht('Oragami'), - 'martini' => pht('Healthy Olive Drink'), - 'medical' => pht('Medic!'), - 'mobile' => pht('Cellular Telephone'), - 'music' => pht("\xE2\x99\xAB"), - 'news' => pht('Actual Physical Newspaper'), - 'orgchart' => pht('It\'s Good to be King'), - 'peoples' => pht('Angel and Devil'), - 'piechart' => pht('Actual Physical Pie'), - 'poison' => pht('Healthy Bone Juice'), - 'putabirdonit' => pht('Put a Bird On It'), - 'radiate' => pht('Radiant Beauty'), - 'savings' => pht('Oink Oink'), - 'search' => pht('Sleuthing'), - 'shield' => pht('Royal Crest'), - 'speed' => pht('Slow and Steady'), - 'sprint' => pht('Fire Exit'), - 'star' => pht('The More You Know'), - 'storage' => pht('Stack of Pancakes'), - 'tablet' => pht('Cellular Telephone For Giants'), - 'travel' => pht('Pretty Clearly an Airplane'), - 'twitter' => pht('Bird Stencil'), - 'warning' => pht('No Caution Required, Everything Looks Safe'), - 'whale' => pht('Friendly Walrus'), - 'fa-flask' => pht('Experimental'), + 'fa-android' => pht('Friendly Robot'), + 'fa-apple' => pht('Friendly Fruit'), + 'fa-beer' => pht('Liquid Carbs'), + 'fa-bomb' => pht('Boom!'), + 'fa-book' => pht('Read Me'), 'fa-briefcase' => pht('Briefcase'), 'fa-bug' => pht('Bug'), 'fa-building' => pht('Company'), 'fa-calendar' => pht('Deadline'), + 'fa-camera-retro' => pht('Leica Enth1usiast'), + 'fa-chrome' => pht('Shiny'), 'fa-cloud' => pht('The Cloud'), + 'fa-coffee' => pht('Go Juice'), + 'fa-comments' => pht('Cartoon Captions'), 'fa-credit-card' => pht('Accounting'), + 'fa-database' => pht('Stack of Pancakes'), + 'fa-desktop' => pht('Cardboard Box'), + 'fa-diamond' => pht('Isometric-Hexoctahedral'), + 'fa-empire' => pht('Bad Guys'), 'fa-envelope' => pht('Communication'), + 'fa-facebook' => pht('College Site'), + 'fa-fax' => pht('Communication Device'), + 'fa-film' => pht('Physical Film'), + 'fa-firefox' => pht('Blake Ross'), 'fa-flag-checkered' => pht('Goal'), + 'fa-flask' => pht('Experimental'), 'fa-folder' => pht('Folder'), - 'fa-group' => pht('Team'), + 'fa-gamepad' => pht('Half-Life 3 Confirmed'), + 'fa-gears' => pht('Mechanical'), + 'fa-google' => pht('Car Company'), + 'fa-hand-peace-o' => pht('Peace'), + 'fa-hashtag' => pht('Not Slack'), + 'fa-heart' => pht('Myocardial Infarction'), + 'fa-internet-explorer' => pht('Now Just Edge'), + 'fa-key' => pht('Primitive Security'), + 'fa-legal' => pht('Hired Protection'), + 'fa-linux' => pht('M\`Lady'), 'fa-lock' => pht('Policy'), - 'fa-tags' => pht('Tag'), + 'fa-microphone' => pht('Podcasting'), + 'fa-mobile' => pht('Tiny Pocket Cat Meme Machine'), + 'fa-money' => pht('1 of 99 Problems'), + 'fa-phone' => pht('Grandma Uses This'), + 'fa-pie-chart' => pht('Not Actually Edible'), + 'fa-rebel' => pht('Good Guys'), + 'fa-reddit-alien' => pht('Updoot In 5 Seconds'), + 'fa-safari' => pht('Fruit Exploration'), + 'fa-search' => pht('Dust Detector'), + 'fa-server' => pht('Heating Units'), + 'fa-shopping-cart' => pht('Buy Stuff'), + 'fa-sitemap' => pht('Sitemap'), + 'fa-star' => pht('The More You Know'), + 'fa-tablet' => pht('Cellular Telephone For Giants'), + 'fa-tag' => pht('You\'re It'), + 'fa-tags' => pht('Tags'), 'fa-trash-o' => pht('Garbage'), 'fa-truck' => pht('Release'), + 'fa-twitter' => pht('Bird Stencil'), 'fa-umbrella' => pht('An Umbrella'), + 'fa-university' => pht('School'), + 'fa-user-secret' => pht('Shhh'), + 'fa-user' => pht('Individual'), + 'fa-users' => pht('Team'), + 'fa-warning' => pht('No Caution Required, Everything Looks Safe'), + 'fa-wheelchair' => pht('Accessability'), + 'fa-windows' => pht('Windows'), ); } diff --git a/webroot/rsrc/css/application/people/people-profile.css b/webroot/rsrc/css/application/people/people-profile.css index c22cceb8e5..d73b94fb97 100644 --- a/webroot/rsrc/css/application/people/people-profile.css +++ b/webroot/rsrc/css/application/people/people-profile.css @@ -38,7 +38,7 @@ form.compose-dialog { } .compose-dialog .compose-icon-bg { - color: #fff; + color: rgba(255,255,255,0.8); line-height: 50px; width: 50px; text-align: center; From 26500f0545cc89bdeb5e11ed9db5bfb3b4b30b23 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Tue, 19 Jan 2016 13:57:53 -0800 Subject: [PATCH 36/66] Rename group icon for Projects Summary: This should fa-users, not fa-group. Test Plan: Open a Project that is set to "Group" aka "Users", set picture, see "Team" automatically. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D15058 --- .../builtin/projects/{fa-group.png => fa-users.png} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename resources/builtin/projects/{fa-group.png => fa-users.png} (100%) diff --git a/resources/builtin/projects/fa-group.png b/resources/builtin/projects/fa-users.png similarity index 100% rename from resources/builtin/projects/fa-group.png rename to resources/builtin/projects/fa-users.png From 6b1b21c999da983395ee563d0657e1bf58d8c62a Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 19 Jan 2016 16:27:36 -0800 Subject: [PATCH 37/66] Move member/watch actions to "Members/Watchers" page Summary: Ref T10054. This tries to make the members page a bit more consistent and provide hints to users about subproject/milestone membership rules. In particular: - You now join, leave, watch, unwatch, add and remove members, and lock and unlock membership from the members screen. - We now explain the membership rule for the project on this screen. There are currently four rules: - Normal Project: Join/leave normally. - Parent Project: Uses subprojects to determine members. - Milestone: Uses parent project to determine members. - Locked: Membership is locked. - (Future) Imported from LDAP/other external sources: Membership is determined by something else. Test Plan: {F1064878} Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15059 --- resources/celerity/map.php | 6 +- src/__phutil_library_map__.php | 12 +- .../PhabricatorProjectApplication.php | 4 +- .../PhabricatorProjectLockController.php | 11 +- ...PhabricatorProjectMembersAddController.php | 72 ++++++ ...habricatorProjectMembersEditController.php | 156 ------------- ...habricatorProjectMembersViewController.php | 205 ++++++++++++++++++ .../PhabricatorProjectProfileController.php | 67 ------ .../PhabricatorProjectUpdateController.php | 84 +++---- .../PhabricatorProjectWatchController.php | 8 +- .../view/PhabricatorProjectMemberListView.php | 34 +++ .../view/PhabricatorProjectUserListView.php | 78 +++++++ .../PhabricatorProjectWatcherListView.php | 22 ++ src/view/phui/PHUIStatusItemView.php | 1 - webroot/rsrc/css/phui/phui-profile-menu.css | 27 ++- 15 files changed, 501 insertions(+), 286 deletions(-) create mode 100644 src/applications/project/controller/PhabricatorProjectMembersAddController.php delete mode 100644 src/applications/project/controller/PhabricatorProjectMembersEditController.php create mode 100644 src/applications/project/controller/PhabricatorProjectMembersViewController.php create mode 100644 src/applications/project/view/PhabricatorProjectMemberListView.php create mode 100644 src/applications/project/view/PhabricatorProjectUserListView.php create mode 100644 src/applications/project/view/PhabricatorProjectWatcherListView.php diff --git a/resources/celerity/map.php b/resources/celerity/map.php index d58b545881..d7ae6285ef 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => '7fce81fc', + 'core.pkg.css' => 'bd4f3259', 'core.pkg.js' => '573e6664', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -143,7 +143,7 @@ return array( 'rsrc/css/phui/phui-object-item-list-view.css' => '26c30d3f', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', - 'rsrc/css/phui/phui-profile-menu.css' => '72d69773', + 'rsrc/css/phui/phui-profile-menu.css' => '84966ae9', 'rsrc/css/phui/phui-property-list-view.css' => '27b2849e', 'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591', 'rsrc/css/phui/phui-spacing.css' => '042804d6', @@ -819,7 +819,7 @@ return array( 'phui-object-item-list-view-css' => '26c30d3f', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', - 'phui-profile-menu-css' => '72d69773', + 'phui-profile-menu-css' => '84966ae9', 'phui-property-list-view-css' => '27b2849e', 'phui-remarkup-preview-css' => '1a8f2591', 'phui-spacing-css' => '042804d6', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index ff47a4e360..a7e6796ef2 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2895,12 +2895,14 @@ phutil_register_library_map(array( 'PhabricatorProjectLogicalUserDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalUserDatasource.php', 'PhabricatorProjectLogicalViewerDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalViewerDatasource.php', 'PhabricatorProjectMaterializedMemberEdgeType' => 'applications/project/edge/PhabricatorProjectMaterializedMemberEdgeType.php', + 'PhabricatorProjectMemberListView' => 'applications/project/view/PhabricatorProjectMemberListView.php', 'PhabricatorProjectMemberOfProjectEdgeType' => 'applications/project/edge/PhabricatorProjectMemberOfProjectEdgeType.php', + 'PhabricatorProjectMembersAddController' => 'applications/project/controller/PhabricatorProjectMembersAddController.php', 'PhabricatorProjectMembersDatasource' => 'applications/project/typeahead/PhabricatorProjectMembersDatasource.php', - 'PhabricatorProjectMembersEditController' => 'applications/project/controller/PhabricatorProjectMembersEditController.php', 'PhabricatorProjectMembersPolicyRule' => 'applications/project/policyrule/PhabricatorProjectMembersPolicyRule.php', 'PhabricatorProjectMembersProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectMembersProfilePanel.php', 'PhabricatorProjectMembersRemoveController' => 'applications/project/controller/PhabricatorProjectMembersRemoveController.php', + 'PhabricatorProjectMembersViewController' => 'applications/project/controller/PhabricatorProjectMembersViewController.php', 'PhabricatorProjectMilestonesController' => 'applications/project/controller/PhabricatorProjectMilestonesController.php', 'PhabricatorProjectMoveController' => 'applications/project/controller/PhabricatorProjectMoveController.php', 'PhabricatorProjectNameContextFreeGrammar' => 'applications/project/lipsum/PhabricatorProjectNameContextFreeGrammar.php', @@ -2932,8 +2934,10 @@ phutil_register_library_map(array( 'PhabricatorProjectUIEventListener' => 'applications/project/events/PhabricatorProjectUIEventListener.php', 'PhabricatorProjectUpdateController' => 'applications/project/controller/PhabricatorProjectUpdateController.php', 'PhabricatorProjectUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectUserFunctionDatasource.php', + 'PhabricatorProjectUserListView' => 'applications/project/view/PhabricatorProjectUserListView.php', 'PhabricatorProjectViewController' => 'applications/project/controller/PhabricatorProjectViewController.php', 'PhabricatorProjectWatchController' => 'applications/project/controller/PhabricatorProjectWatchController.php', + 'PhabricatorProjectWatcherListView' => 'applications/project/view/PhabricatorProjectWatcherListView.php', 'PhabricatorProjectWorkboardProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php', 'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php', 'PhabricatorProjectsEditField' => 'applications/transactions/editfield/PhabricatorProjectsEditField.php', @@ -7292,12 +7296,14 @@ phutil_register_library_map(array( 'PhabricatorProjectLogicalUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectLogicalViewerDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorProjectMaterializedMemberEdgeType' => 'PhabricatorEdgeType', + 'PhabricatorProjectMemberListView' => 'PhabricatorProjectUserListView', 'PhabricatorProjectMemberOfProjectEdgeType' => 'PhabricatorEdgeType', + 'PhabricatorProjectMembersAddController' => 'PhabricatorProjectController', 'PhabricatorProjectMembersDatasource' => 'PhabricatorTypeaheadCompositeDatasource', - 'PhabricatorProjectMembersEditController' => 'PhabricatorProjectController', 'PhabricatorProjectMembersPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorProjectMembersProfilePanel' => 'PhabricatorProfilePanel', 'PhabricatorProjectMembersRemoveController' => 'PhabricatorProjectController', + 'PhabricatorProjectMembersViewController' => 'PhabricatorProjectController', 'PhabricatorProjectMilestonesController' => 'PhabricatorProjectController', 'PhabricatorProjectMoveController' => 'PhabricatorProjectController', 'PhabricatorProjectNameContextFreeGrammar' => 'PhutilContextFreeGrammar', @@ -7332,8 +7338,10 @@ phutil_register_library_map(array( 'PhabricatorProjectUIEventListener' => 'PhabricatorEventListener', 'PhabricatorProjectUpdateController' => 'PhabricatorProjectController', 'PhabricatorProjectUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', + 'PhabricatorProjectUserListView' => 'AphrontView', 'PhabricatorProjectViewController' => 'PhabricatorProjectController', 'PhabricatorProjectWatchController' => 'PhabricatorProjectController', + 'PhabricatorProjectWatcherListView' => 'PhabricatorProjectUserListView', 'PhabricatorProjectWorkboardProfilePanel' => 'PhabricatorProfilePanel', 'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorProjectsEditField' => 'PhabricatorTokenizerEditField', diff --git a/src/applications/project/application/PhabricatorProjectApplication.php b/src/applications/project/application/PhabricatorProjectApplication.php index e3732f2b31..d2990f527a 100644 --- a/src/applications/project/application/PhabricatorProjectApplication.php +++ b/src/applications/project/application/PhabricatorProjectApplication.php @@ -48,7 +48,9 @@ final class PhabricatorProjectApplication extends PhabricatorApplication { 'lock/(?P[1-9]\d*)/' => 'PhabricatorProjectLockController', 'members/(?P[1-9]\d*)/' - => 'PhabricatorProjectMembersEditController', + => 'PhabricatorProjectMembersViewController', + 'members/(?P[1-9]\d*)/add/' + => 'PhabricatorProjectMembersAddController', 'members/(?P[1-9]\d*)/remove/' => 'PhabricatorProjectMembersRemoveController', 'profile/(?P[1-9]\d*)/' diff --git a/src/applications/project/controller/PhabricatorProjectLockController.php b/src/applications/project/controller/PhabricatorProjectLockController.php index 744be32f99..b9b56bde10 100644 --- a/src/applications/project/controller/PhabricatorProjectLockController.php +++ b/src/applications/project/controller/PhabricatorProjectLockController.php @@ -27,7 +27,16 @@ final class PhabricatorProjectLockController return new Aphront404Response(); } - $done_uri = $project->getURI(); + $done_uri = "/project/members/{$id}/"; + + if (!$project->supportsEditMembers()) { + return $this->newDialog() + ->setTitle(pht('Membership Immutable')) + ->appendChild( + pht('This project does not support editing membership.')) + ->addCancelButton($done_uri); + } + $is_locked = $project->getIsMembershipLocked(); if ($request->isFormPost()) { diff --git a/src/applications/project/controller/PhabricatorProjectMembersAddController.php b/src/applications/project/controller/PhabricatorProjectMembersAddController.php new file mode 100644 index 0000000000..bd1631ee92 --- /dev/null +++ b/src/applications/project/controller/PhabricatorProjectMembersAddController.php @@ -0,0 +1,72 @@ +getViewer(); + $id = $request->getURIData('id'); + + $project = id(new PhabricatorProjectQuery()) + ->setViewer($viewer) + ->withIDs(array($id)) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); + if (!$project) { + return new Aphront404Response(); + } + + $this->setProject($project); + + if (!$project->supportsEditMembers()) { + return new Aphront404Response(); + } + + $done_uri = "/project/members/{$id}/"; + + if ($request->isFormPost()) { + $member_phids = $request->getArr('memberPHIDs'); + + $type_member = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; + + $xactions = array(); + + $xactions[] = id(new PhabricatorProjectTransaction()) + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) + ->setMetadataValue('edge:type', $type_member) + ->setNewValue( + array( + '+' => array_fuse($member_phids), + )); + + $editor = id(new PhabricatorProjectTransactionEditor($project)) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnNoEffect(true) + ->setContinueOnMissingFields(true) + ->applyTransactions($project, $xactions); + + return id(new AphrontRedirectResponse()) + ->setURI($done_uri); + } + + $form = id(new AphrontFormView()) + ->setUser($viewer) + ->appendControl( + id(new AphrontFormTokenizerControl()) + ->setName('memberPHIDs') + ->setLabel(pht('Members')) + ->setDatasource(new PhabricatorPeopleDatasource())); + + return $this->newDialog() + ->setTitle(pht('Add Members')) + ->appendForm($form) + ->addCancelButton($done_uri) + ->addSubmitButton(pht('Add Members')); + } + +} diff --git a/src/applications/project/controller/PhabricatorProjectMembersEditController.php b/src/applications/project/controller/PhabricatorProjectMembersEditController.php deleted file mode 100644 index f485e2997a..0000000000 --- a/src/applications/project/controller/PhabricatorProjectMembersEditController.php +++ /dev/null @@ -1,156 +0,0 @@ -getViewer(); - $id = $request->getURIData('id'); - - $project = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->withIDs(array($id)) - ->needMembers(true) - ->needImages(true) - ->executeOne(); - if (!$project) { - return new Aphront404Response(); - } - - $this->setProject($project); - - $member_phids = $project->getMemberPHIDs(); - - if ($request->isFormPost()) { - $member_spec = array(); - - $remove = $request->getStr('remove'); - if ($remove) { - $member_spec['-'] = array_fuse(array($remove)); - } - - $add_members = $request->getArr('phids'); - if ($add_members) { - $member_spec['+'] = array_fuse($add_members); - } - - $type_member = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; - - $xactions = array(); - - $xactions[] = id(new PhabricatorProjectTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) - ->setMetadataValue('edge:type', $type_member) - ->setNewValue($member_spec); - - $editor = id(new PhabricatorProjectTransactionEditor($project)) - ->setActor($viewer) - ->setContentSourceFromRequest($request) - ->setContinueOnNoEffect(true) - ->setContinueOnMissingFields(true) - ->applyTransactions($project, $xactions); - - return id(new AphrontRedirectResponse()) - ->setURI($request->getRequestURI()); - } - - $member_phids = array_reverse($member_phids); - $handles = $this->loadViewerHandles($member_phids); - - $state = array(); - foreach ($handles as $handle) { - $state[] = array( - 'phid' => $handle->getPHID(), - 'name' => $handle->getFullName(), - ); - } - - $can_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - $project, - PhabricatorPolicyCapability::CAN_EDIT); - - $supports_edit = $project->supportsEditMembers(); - - $form_box = null; - $title = pht('Add Members'); - if ($can_edit && $supports_edit) { - $header_name = pht('Edit Members'); - $view_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); - - $form = new AphrontFormView(); - $form - ->setUser($viewer) - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setName('phids') - ->setLabel(pht('Add Members')) - ->setDatasource(new PhabricatorPeopleDatasource())) - ->appendChild( - id(new AphrontFormSubmitControl()) - ->addCancelButton($view_uri) - ->setValue(pht('Add Members'))); - $form_box = id(new PHUIObjectBoxView()) - ->setHeaderText($title) - ->setForm($form); - } - - $member_list = $this->renderMemberList($project, $handles); - - $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorProject::PANEL_MEMBERS); - - $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addTextCrumb(pht('Members')); - - return $this->newPage() - ->setNavigation($nav) - ->setCrumbs($crumbs) - ->setTitle(array($project->getName(), $title)) - ->appendChild($form_box) - ->appendChild($member_list); - } - - private function renderMemberList( - PhabricatorProject $project, - array $handles) { - - $request = $this->getRequest(); - $viewer = $request->getUser(); - - $can_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - $project, - PhabricatorPolicyCapability::CAN_EDIT); - - $list = id(new PHUIObjectItemListView()) - ->setNoDataString(pht('This project does not have any members.')); - - foreach ($handles as $handle) { - $remove_uri = $this->getApplicationURI( - '/members/'.$project->getID().'/remove/?phid='.$handle->getPHID()); - - $item = id(new PHUIObjectItemView()) - ->setHeader($handle->getFullName()) - ->setHref($handle->getURI()) - ->setImageURI($handle->getImageURI()); - - if ($can_edit) { - $item->addAction( - id(new PHUIListItemView()) - ->setIcon('fa-times') - ->setName(pht('Remove')) - ->setHref($remove_uri) - ->setWorkflow(true)); - } - - $list->addItem($item); - } - - $box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Members')) - ->setObjectList($list); - - return $box; - } -} diff --git a/src/applications/project/controller/PhabricatorProjectMembersViewController.php b/src/applications/project/controller/PhabricatorProjectMembersViewController.php new file mode 100644 index 0000000000..dd9f263e5d --- /dev/null +++ b/src/applications/project/controller/PhabricatorProjectMembersViewController.php @@ -0,0 +1,205 @@ +getViewer(); + $id = $request->getURIData('id'); + + $project = id(new PhabricatorProjectQuery()) + ->setViewer($viewer) + ->withIDs(array($id)) + ->needMembers(true) + ->needWatchers(true) + ->needImages(true) + ->executeOne(); + if (!$project) { + return new Aphront404Response(); + } + + $this->setProject($project); + $title = pht('Members and Watchers'); + + $properties = $this->buildProperties($project); + $actions = $this->buildActions($project); + $properties->setActionList($actions); + + $object_box = id(new PHUIObjectBoxView()) + ->setHeaderText($title) + ->addPropertyList($properties); + + $member_list = id(new PhabricatorProjectMemberListView()) + ->setUser($viewer) + ->setProject($project) + ->setUserPHIDs($project->getMemberPHIDs()); + + $watcher_list = id(new PhabricatorProjectWatcherListView()) + ->setUser($viewer) + ->setProject($project) + ->setUserPHIDs($project->getWatcherPHIDs()); + + $nav = $this->getProfileMenu(); + $nav->selectFilter(PhabricatorProject::PANEL_MEMBERS); + + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb(pht('Members')); + + return $this->newPage() + ->setNavigation($nav) + ->setCrumbs($crumbs) + ->setTitle(array($project->getName(), $title)) + ->appendChild( + array( + $object_box, + $member_list, + $watcher_list, + )); + } + + private function buildProperties(PhabricatorProject $project) { + $viewer = $this->getViewer(); + + $view = id(new PHUIPropertyListView()) + ->setUser($viewer) + ->setObject($project); + + if ($project->isMilestone()) { + $icon_key = PhabricatorProjectIconSet::getMilestoneIconKey(); + $icon = PhabricatorProjectIconSet::getIconIcon($icon_key); + $target = PhabricatorProjectIconSet::getIconName($icon_key); + $note = pht( + 'Members of the parent project are members of this project.'); + $show_join = false; + } else if ($project->getHasSubprojects()) { + $icon = 'fa-sitemap'; + $target = pht('Parent Project'); + $note = pht( + 'Members of all subprojects are members of this project.'); + $show_join = false; + } else if ($project->getIsMembershipLocked()) { + $icon = 'fa-lock'; + $target = pht('Locked Project'); + $note = pht( + 'Users with access may join this project, but may not leave.'); + $show_join = true; + } else { + $icon = 'fa-briefcase'; + $target = pht('Normal Project'); + $note = pht('Users with access may join and leave this project.'); + $show_join = true; + } + + $item = id(new PHUIStatusItemView()) + ->setIcon($icon) + ->setTarget(phutil_tag('strong', array(), $target)) + ->setNote($note); + + $status = id(new PHUIStatusListView()) + ->addItem($item); + + $view->addProperty(pht('Membership'), $status); + + if ($show_join) { + $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( + $viewer, + $project); + + $view->addProperty( + pht('Joinable By'), + $descriptions[PhabricatorPolicyCapability::CAN_JOIN]); + } + + return $view; + } + + private function buildActions(PhabricatorProject $project) { + $viewer = $this->getViewer(); + $id = $project->getID(); + + $view = id(new PhabricatorActionListView()) + ->setUser($viewer); + + $is_locked = $project->getIsMembershipLocked(); + + $can_edit = PhabricatorPolicyFilter::hasCapability( + $viewer, + $project, + PhabricatorPolicyCapability::CAN_EDIT); + + $supports_edit = $project->supportsEditMembers(); + + $can_join = $supports_edit && PhabricatorPolicyFilter::hasCapability( + $viewer, + $project, + PhabricatorPolicyCapability::CAN_JOIN); + + $can_leave = $supports_edit && (!$is_locked || $can_edit); + + if (!$project->isUserMember($viewer->getPHID())) { + $view->addAction( + id(new PhabricatorActionView()) + ->setHref('/project/update/'.$project->getID().'/join/') + ->setIcon('fa-plus') + ->setDisabled(!$can_join) + ->setWorkflow(true) + ->setName(pht('Join Project'))); + } else { + $view->addAction( + id(new PhabricatorActionView()) + ->setHref('/project/update/'.$project->getID().'/leave/') + ->setIcon('fa-times') + ->setDisabled(!$can_leave) + ->setWorkflow(true) + ->setName(pht('Leave Project'))); + + if (!$project->isUserWatcher($viewer->getPHID())) { + $view->addAction( + id(new PhabricatorActionView()) + ->setWorkflow(true) + ->setHref('/project/watch/'.$project->getID().'/') + ->setIcon('fa-eye') + ->setName(pht('Watch Project'))); + } else { + $view->addAction( + id(new PhabricatorActionView()) + ->setWorkflow(true) + ->setHref('/project/unwatch/'.$project->getID().'/') + ->setIcon('fa-eye-slash') + ->setName(pht('Unwatch Project'))); + } + } + + $can_add = $can_edit && $supports_edit; + + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Add Members')) + ->setIcon('fa-user-plus') + ->setHref("/project/members/{$id}/add/") + ->setWorkflow(true) + ->setDisabled(!$can_add)); + + $can_lock = $can_edit && $supports_edit && $this->hasApplicationCapability( + ProjectCanLockProjectsCapability::CAPABILITY); + + if ($is_locked) { + $lock_name = pht('Unlock Project'); + $lock_icon = 'fa-unlock'; + } else { + $lock_name = pht('Lock Project'); + $lock_icon = 'fa-lock'; + } + + $view->addAction( + id(new PhabricatorActionView()) + ->setName($lock_name) + ->setIcon($lock_icon) + ->setHref($this->getApplicationURI("lock/{$id}/")) + ->setDisabled(!$can_lock) + ->setWorkflow(true)); + + return $view; + } + +} diff --git a/src/applications/project/controller/PhabricatorProjectProfileController.php b/src/applications/project/controller/PhabricatorProjectProfileController.php index a2eb5eebe6..89600e97d7 100644 --- a/src/applications/project/controller/PhabricatorProjectProfileController.php +++ b/src/applications/project/controller/PhabricatorProjectProfileController.php @@ -106,65 +106,6 @@ final class PhabricatorProjectProfileController ->setWorkflow(true)); } - $can_lock = $can_edit && $this->hasApplicationCapability( - ProjectCanLockProjectsCapability::CAPABILITY); - - if ($project->getIsMembershipLocked()) { - $lock_name = pht('Unlock Project'); - $lock_icon = 'fa-unlock'; - } else { - $lock_name = pht('Lock Project'); - $lock_icon = 'fa-lock'; - } - - $view->addAction( - id(new PhabricatorActionView()) - ->setName($lock_name) - ->setIcon($lock_icon) - ->setHref($this->getApplicationURI("lock/{$id}/")) - ->setDisabled(!$can_lock) - ->setWorkflow(true)); - - $action = null; - if (!$project->isUserMember($viewer->getPHID())) { - $can_join = PhabricatorPolicyFilter::hasCapability( - $viewer, - $project, - PhabricatorPolicyCapability::CAN_JOIN); - - $action = id(new PhabricatorActionView()) - ->setUser($viewer) - ->setRenderAsForm(true) - ->setHref('/project/update/'.$project->getID().'/join/') - ->setIcon('fa-plus') - ->setDisabled(!$can_join) - ->setName(pht('Join Project')); - $view->addAction($action); - } else { - $action = id(new PhabricatorActionView()) - ->setWorkflow(true) - ->setHref('/project/update/'.$project->getID().'/leave/') - ->setIcon('fa-times') - ->setName(pht('Leave Project...')); - $view->addAction($action); - - if (!$project->isUserWatcher($viewer->getPHID())) { - $action = id(new PhabricatorActionView()) - ->setWorkflow(true) - ->setHref('/project/watch/'.$project->getID().'/') - ->setIcon('fa-eye') - ->setName(pht('Watch Project')); - $view->addAction($action); - } else { - $action = id(new PhabricatorActionView()) - ->setWorkflow(true) - ->setHref('/project/unwatch/'.$project->getID().'/') - ->setIcon('fa-eye-slash') - ->setName(pht('Unwatch Project')); - $view->addAction($action); - } - } - return $view; } @@ -206,18 +147,10 @@ final class PhabricatorProjectProfileController ->setAsInline(true) : phutil_tag('em', array(), pht('None'))); - $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( - $viewer, - $project); - $view->addProperty( pht('Looks Like'), $viewer->renderHandle($project->getPHID())->setAsTag(true)); - $view->addProperty( - pht('Joinable By'), - $descriptions[PhabricatorPolicyCapability::CAN_JOIN]); - $field_list = PhabricatorCustomField::getObjectFields( $project, PhabricatorCustomField::ROLE_VIEW); diff --git a/src/applications/project/controller/PhabricatorProjectUpdateController.php b/src/applications/project/controller/PhabricatorProjectUpdateController.php index cfdeb4fd09..762343f485 100644 --- a/src/applications/project/controller/PhabricatorProjectUpdateController.php +++ b/src/applications/project/controller/PhabricatorProjectUpdateController.php @@ -12,14 +12,11 @@ final class PhabricatorProjectUpdateController PhabricatorPolicyCapability::CAN_VIEW, ); - $process_action = false; switch ($action) { case 'join': $capabilities[] = PhabricatorPolicyCapability::CAN_JOIN; - $process_action = $request->isFormPost(); break; case 'leave': - $process_action = $request->isDialogFormPost(); break; default: return new Aphront404Response(); @@ -35,10 +32,13 @@ final class PhabricatorProjectUpdateController return new Aphront404Response(); } - $project_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); + if (!$project->supportsEditMembers()) { + return new Aphront404Response(); + } - if ($process_action) { + $done_uri = "/project/members/{$id}/"; + if ($request->isFormPost()) { $edge_action = null; switch ($action) { case 'join': @@ -50,6 +50,7 @@ final class PhabricatorProjectUpdateController } $type_member = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; + $member_spec = array( $edge_action => array($viewer->getPHID() => $viewer->getPHID()), ); @@ -67,46 +68,47 @@ final class PhabricatorProjectUpdateController ->setContinueOnMissingFields(true) ->applyTransactions($project, $xactions); - return id(new AphrontRedirectResponse())->setURI($project_uri); + return id(new AphrontRedirectResponse())->setURI($done_uri); } - $dialog = null; - switch ($action) { - case 'leave': - $dialog = new AphrontDialogView(); - $dialog->setUser($viewer); - if ($this->userCannotLeave($project)) { - $dialog->setTitle(pht('You can not leave this project.')); - $body = pht('The membership is locked for this project.'); - } else { - $dialog->setTitle(pht('Really leave project?')); - $body = pht( - 'Your tremendous contributions to this project will be sorely '. - 'missed. Are you sure you want to leave?'); - $dialog->addSubmitButton(pht('Leave Project')); - } - $dialog->appendParagraph($body); - $dialog->addCancelButton($project_uri); - break; - default: - return new Aphront404Response(); + $is_locked = $project->getIsMembershipLocked(); + $can_edit = PhabricatorPolicyFilter::hasCapability( + $viewer, + $project, + PhabricatorPolicyCapability::CAN_EDIT); + $can_leave = ($can_edit || !$is_locked); + + $button = null; + if ($action == 'leave') { + if ($can_leave) { + $title = pht('Leave Project'); + $body = pht( + 'Your tremendous contributions to this project will be sorely '. + 'missed. Are you sure you want to leave?'); + $button = pht('Leave Project'); + } else { + $title = pht('Membership Locked'); + $body = pht( + 'Membership for this project is locked. You can not leave.'); + } + } else { + $title = pht('Join Project'); + $body = pht( + 'Join this project? You will become a member and enjoy whatever '. + 'benefits membership may confer.'); + $button = pht('Join Project'); } - return id(new AphrontDialogResponse())->setDialog($dialog); + $dialog = $this->newDialog() + ->setTitle($title) + ->appendParagraph($body) + ->addCancelButton($done_uri); + + if ($button) { + $dialog->addSubmitButton($button); + } + + return $dialog; } - /** - * This is enforced in @{class:PhabricatorProjectTransactionEditor}. We use - * this logic to render a better form for users hitting this case. - */ - private function userCannotLeave(PhabricatorProject $project) { - $viewer = $this->getViewer(); - - return - $project->getIsMembershipLocked() && - !PhabricatorPolicyFilter::hasCapability( - $viewer, - $project, - PhabricatorPolicyCapability::CAN_EDIT); - } } diff --git a/src/applications/project/controller/PhabricatorProjectWatchController.php b/src/applications/project/controller/PhabricatorProjectWatchController.php index 53538f8393..c39e7dd510 100644 --- a/src/applications/project/controller/PhabricatorProjectWatchController.php +++ b/src/applications/project/controller/PhabricatorProjectWatchController.php @@ -18,9 +18,9 @@ final class PhabricatorProjectWatchController return new Aphront404Response(); } - $project_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); + $done_uri = "/project/members/{$id}/"; - // You must be a member of a project to + // You must be a member of a project to watch it. if (!$project->isUserMember($viewer->getPHID())) { return new Aphront400Response(); } @@ -56,7 +56,7 @@ final class PhabricatorProjectWatchController ->setContinueOnMissingFields(true) ->applyTransactions($project, $xactions); - return id(new AphrontRedirectResponse())->setURI($project_uri); + return id(new AphrontRedirectResponse())->setURI($done_uri); } $dialog = null; @@ -83,7 +83,7 @@ final class PhabricatorProjectWatchController return $this->newDialog() ->setTitle($title) ->appendParagraph($body) - ->addCancelButton($project_uri) + ->addCancelButton($done_uri) ->addSubmitButton($submit); } diff --git a/src/applications/project/view/PhabricatorProjectMemberListView.php b/src/applications/project/view/PhabricatorProjectMemberListView.php new file mode 100644 index 0000000000..12b7cc7a76 --- /dev/null +++ b/src/applications/project/view/PhabricatorProjectMemberListView.php @@ -0,0 +1,34 @@ +getUser(); + $project = $this->getProject(); + + if (!$project->supportsEditMembers()) { + return false; + } + + return PhabricatorPolicyFilter::hasCapability( + $viewer, + $project, + PhabricatorPolicyCapability::CAN_EDIT); + } + + protected function getNoDataString() { + return pht('This project does not have any members.'); + } + + protected function getRemoveURI($phid) { + $project = $this->getProject(); + $id = $project->getID(); + return "/project/members/{$id}/remove/?phid={$phid}"; + } + + protected function getHeaderText() { + return pht('Members'); + } + +} diff --git a/src/applications/project/view/PhabricatorProjectUserListView.php b/src/applications/project/view/PhabricatorProjectUserListView.php new file mode 100644 index 0000000000..e42b427ed3 --- /dev/null +++ b/src/applications/project/view/PhabricatorProjectUserListView.php @@ -0,0 +1,78 @@ +project = $project; + return $this; + } + + public function getProject() { + return $this->project; + } + + public function setUserPHIDs(array $user_phids) { + $this->userPHIDs = $user_phids; + return $this; + } + + public function getUserPHIDs() { + return $this->userPHIDs; + } + + abstract protected function canEditList(); + abstract protected function getNoDataString(); + abstract protected function getRemoveURI($phid); + abstract protected function getHeaderText(); + + public function render() { + $viewer = $this->getUser(); + $project = $this->getProject(); + $user_phids = $this->getUserPHIDs(); + + $can_edit = $this->canEditList(); + $no_data = $this->getNoDataString(); + + $list = id(new PHUIObjectItemListView()) + ->setNoDataString($no_data); + + $user_phids = array_reverse($user_phids); + $handles = $viewer->loadHandles($user_phids); + + // Always put the viewer first if they are on the list. + $user_phids = array_fuse($user_phids); + $user_phids = + array_select_keys($user_phids, array($viewer->getPHID())) + + $user_phids; + + foreach ($user_phids as $user_phid) { + $handle = $handles[$user_phid]; + + $item = id(new PHUIObjectItemView()) + ->setHeader($handle->getFullName()) + ->setHref($handle->getURI()) + ->setImageURI($handle->getImageURI()); + + if ($can_edit) { + $remove_uri = $this->getRemoveURI($user_phid); + + $item->addAction( + id(new PHUIListItemView()) + ->setIcon('fa-times') + ->setName(pht('Remove')) + ->setHref($remove_uri) + ->setWorkflow(true)); + } + + $list->addItem($item); + } + + return id(new PHUIObjectBoxView()) + ->setHeaderText($this->getHeaderText()) + ->setObjectList($list); + } + +} diff --git a/src/applications/project/view/PhabricatorProjectWatcherListView.php b/src/applications/project/view/PhabricatorProjectWatcherListView.php new file mode 100644 index 0000000000..ec993f031c --- /dev/null +++ b/src/applications/project/view/PhabricatorProjectWatcherListView.php @@ -0,0 +1,22 @@ +icon = $icon; $this->iconLabel = $label; diff --git a/webroot/rsrc/css/phui/phui-profile-menu.css b/webroot/rsrc/css/phui/phui-profile-menu.css index b2475a5457..c749c7f3d4 100644 --- a/webroot/rsrc/css/phui/phui-profile-menu.css +++ b/webroot/rsrc/css/phui/phui-profile-menu.css @@ -73,21 +73,24 @@ background-size: 100%; } -.phui-profile-menu .phui-profile-menu-collapsed .phui-list-item-href { +.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu + .phui-list-item-href { text-align: center; padding: 42px 8px 12px; font-size: 11px; line-height: 13px; } -.phui-profile-menu .phui-profile-menu-collapsed .phui-list-item-name { +.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu + .phui-list-item-name { display: block; overflow: hidden; text-overflow: ellipsis; } -.phui-profile-menu .phui-profile-menu-collapsed .phui-list-item-icon, -.phui-profile-menu .phui-profile-menu-collapsed +.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu + .phui-list-item-icon, +.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu .phui-list-item-href .phui-icon-view { top: 10px; left: 29px; @@ -166,27 +169,31 @@ left: 120px; } -.phui-profile-menu .phui-profile-menu-collapsed .phui-profile-menu-footer { +.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu + .phui-profile-menu-footer { width: 40px; height: {$menu.profile.item.height}; bottom: 0px; } -.phui-profile-menu .phui-profile-menu-collapsed .phui-profile-menu-footer-1 { +.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu + .phui-profile-menu-footer-1 { left: 0; } -.phui-profile-menu .phui-profile-menu-collapsed .phui-profile-menu-footer-2 { +.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu + .phui-profile-menu-footer-2 { left: 40px; } - -.phui-profile-menu .phui-profile-menu-collapsed .phui-profile-menu-footer +.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu + .phui-profile-menu-footer .phui-list-item-name { display: none; } -.phui-profile-menu .phui-profile-menu-collapsed .phui-profile-menu-footer +.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu + .phui-profile-menu-footer .phui-list-item-icon { top: 10px; left: 10px; From 9f36594100af7f708a33596a5b3c8b8aab4d6573 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 19 Jan 2016 17:02:29 -0800 Subject: [PATCH 38/66] Put feed on project home, move history to a separate page Summary: Ref T10054. This shuffles some stuff around to move us closer to mocks in M1450 in terms of what information is on which pages. Home now has feed, members, watchers, link to "edit project / project edit history". History now has edit history, edit details, edit picture, archive/unarchive. Test Plan: New home page: {F1064889} New edit/history page: {F1064890} Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15060 --- src/__phutil_library_map__.php | 4 +- .../PhabricatorFileComposeController.php | 2 +- .../PhabricatorProjectApplication.php | 2 - .../PhabricatorProjectArchiveController.php | 2 +- ...habricatorProjectEditPictureController.php | 4 +- .../PhabricatorProjectFeedController.php | 62 -------- .../PhabricatorProjectHistoryController.php | 133 ++++++++++++++++++ .../PhabricatorProjectProfileController.php | 124 +++++++--------- .../engine/PhabricatorProjectEditEngine.php | 7 +- .../PhabricatorProjectProfilePanelEngine.php | 9 -- .../view/PhabricatorProjectUserListView.php | 38 ++++- 11 files changed, 234 insertions(+), 153 deletions(-) delete mode 100644 src/applications/project/controller/PhabricatorProjectFeedController.php create mode 100644 src/applications/project/controller/PhabricatorProjectHistoryController.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index a7e6796ef2..a204da62da 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2881,9 +2881,9 @@ phutil_register_library_map(array( 'PhabricatorProjectEditController' => 'applications/project/controller/PhabricatorProjectEditController.php', 'PhabricatorProjectEditEngine' => 'applications/project/engine/PhabricatorProjectEditEngine.php', 'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php', - 'PhabricatorProjectFeedController' => 'applications/project/controller/PhabricatorProjectFeedController.php', 'PhabricatorProjectFulltextEngine' => 'applications/project/search/PhabricatorProjectFulltextEngine.php', 'PhabricatorProjectHeraldAction' => 'applications/project/herald/PhabricatorProjectHeraldAction.php', + 'PhabricatorProjectHistoryController' => 'applications/project/controller/PhabricatorProjectHistoryController.php', 'PhabricatorProjectIconSet' => 'applications/project/icon/PhabricatorProjectIconSet.php', 'PhabricatorProjectInterface' => 'applications/project/interface/PhabricatorProjectInterface.php', 'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php', @@ -7283,9 +7283,9 @@ phutil_register_library_map(array( 'PhabricatorProjectEditController' => 'PhabricatorProjectController', 'PhabricatorProjectEditEngine' => 'PhabricatorEditEngine', 'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController', - 'PhabricatorProjectFeedController' => 'PhabricatorProjectController', 'PhabricatorProjectFulltextEngine' => 'PhabricatorFulltextEngine', 'PhabricatorProjectHeraldAction' => 'HeraldAction', + 'PhabricatorProjectHistoryController' => 'PhabricatorProjectController', 'PhabricatorProjectIconSet' => 'PhabricatorIconSet', 'PhabricatorProjectListController' => 'PhabricatorProjectController', 'PhabricatorProjectListView' => 'AphrontView', diff --git a/src/applications/files/controller/PhabricatorFileComposeController.php b/src/applications/files/controller/PhabricatorFileComposeController.php index 17e605f3a9..404cf44aca 100644 --- a/src/applications/files/controller/PhabricatorFileComposeController.php +++ b/src/applications/files/controller/PhabricatorFileComposeController.php @@ -44,7 +44,7 @@ final class PhabricatorFileComposeController )); if ($project_phid) { - $edit_uri = '/project/profile/'.$project->getID().'/'; + $edit_uri = '/project/history/'.$project->getID().'/'; $xactions = array(); $xactions[] = id(new PhabricatorProjectTransaction()) diff --git a/src/applications/project/application/PhabricatorProjectApplication.php b/src/applications/project/application/PhabricatorProjectApplication.php index d2990f527a..e1b484ffe2 100644 --- a/src/applications/project/application/PhabricatorProjectApplication.php +++ b/src/applications/project/application/PhabricatorProjectApplication.php @@ -55,8 +55,6 @@ final class PhabricatorProjectApplication extends PhabricatorApplication { => 'PhabricatorProjectMembersRemoveController', 'profile/(?P[1-9]\d*)/' => 'PhabricatorProjectProfileController', - 'feed/(?P[1-9]\d*)/' - => 'PhabricatorProjectFeedController', 'view/(?P[1-9]\d*)/' => 'PhabricatorProjectViewController', 'picture/(?P[1-9]\d*)/' diff --git a/src/applications/project/controller/PhabricatorProjectArchiveController.php b/src/applications/project/controller/PhabricatorProjectArchiveController.php index d6470ca1eb..505af27ef1 100644 --- a/src/applications/project/controller/PhabricatorProjectArchiveController.php +++ b/src/applications/project/controller/PhabricatorProjectArchiveController.php @@ -20,7 +20,7 @@ final class PhabricatorProjectArchiveController return new Aphront404Response(); } - $edit_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); + $edit_uri = $this->getApplicationURI('history/'.$project->getID().'/'); if ($request->isFormPost()) { if ($project->isArchived()) { diff --git a/src/applications/project/controller/PhabricatorProjectEditPictureController.php b/src/applications/project/controller/PhabricatorProjectEditPictureController.php index 41ccb94eb3..b0c013dadc 100644 --- a/src/applications/project/controller/PhabricatorProjectEditPictureController.php +++ b/src/applications/project/controller/PhabricatorProjectEditPictureController.php @@ -23,8 +23,8 @@ final class PhabricatorProjectEditPictureController $this->setProject($project); - $edit_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); - $view_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); + $edit_uri = $this->getApplicationURI('history/'.$project->getID().'/'); + $view_uri = $this->getApplicationURI('history/'.$project->getID().'/'); $supported_formats = PhabricatorFile::getTransformableImageFormats(); $e_file = true; diff --git a/src/applications/project/controller/PhabricatorProjectFeedController.php b/src/applications/project/controller/PhabricatorProjectFeedController.php deleted file mode 100644 index a108384088..0000000000 --- a/src/applications/project/controller/PhabricatorProjectFeedController.php +++ /dev/null @@ -1,62 +0,0 @@ -getUser(); - - $response = $this->loadProject(); - if ($response) { - return $response; - } - - $project = $this->getProject(); - $id = $project->getID(); - - $stories = id(new PhabricatorFeedQuery()) - ->setViewer($viewer) - ->setFilterPHIDs( - array( - $project->getPHID(), - )) - ->setLimit(50) - ->execute(); - - $feed = $this->renderStories($stories); - - $box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Project Activity')) - ->appendChild($feed); - - $nav = $this->getProfileMenu(); - $nav->selectFilter('feed'); - - $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addTextCrumb(pht('Feed')); - - return $this->newPage() - ->setNavigation($nav) - ->setCrumbs($crumbs) - ->setTitle(array($project->getName(), pht('Feed'))) - ->appendChild($box); - } - - private function renderStories(array $stories) { - assert_instances_of($stories, 'PhabricatorFeedStory'); - - $builder = new PhabricatorFeedBuilder($stories); - $builder->setUser($this->getRequest()->getUser()); - $builder->setShowHovercards(true); - $view = $builder->buildView(); - - return phutil_tag_div( - 'profile-feed', - $view->render()); - } - -} diff --git a/src/applications/project/controller/PhabricatorProjectHistoryController.php b/src/applications/project/controller/PhabricatorProjectHistoryController.php new file mode 100644 index 0000000000..aa58e081f4 --- /dev/null +++ b/src/applications/project/controller/PhabricatorProjectHistoryController.php @@ -0,0 +1,133 @@ +loadProject(); + if ($response) { + return $response; + } + + $viewer = $request->getUser(); + $project = $this->getProject(); + $id = $project->getID(); + $picture = $project->getProfileImageURI(); + + $header = id(new PHUIHeaderView()) + ->setHeader(pht('Project History')) + ->setUser($viewer) + ->setPolicyObject($project) + ->setImage($picture); + + if ($project->getStatus() == PhabricatorProjectStatus::STATUS_ACTIVE) { + $header->setStatus('fa-check', 'bluegrey', pht('Active')); + } else { + $header->setStatus('fa-ban', 'red', pht('Archived')); + } + + $actions = $this->buildActionListView($project); + $properties = $this->buildPropertyListView($project, $actions); + + $object_box = id(new PHUIObjectBoxView()) + ->setHeader($header) + ->addPropertyList($properties); + + $timeline = $this->buildTransactionTimeline( + $project, + new PhabricatorProjectTransactionQuery()); + $timeline->setShouldTerminate(true); + + $nav = $this->getProfileMenu(); + $nav->selectFilter(PhabricatorProject::PANEL_PROFILE); + + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb(pht('History')); + + return $this->newPage() + ->setNavigation($nav) + ->setCrumbs($crumbs) + ->setTitle($project->getName()) + ->appendChild( + array( + $object_box, + $timeline, + )); + } + + private function buildActionListView(PhabricatorProject $project) { + $request = $this->getRequest(); + $viewer = $request->getUser(); + + $id = $project->getID(); + + $view = id(new PhabricatorActionListView()) + ->setUser($viewer); + + $can_edit = PhabricatorPolicyFilter::hasCapability( + $viewer, + $project, + PhabricatorPolicyCapability::CAN_EDIT); + + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Back to Profile')) + ->setIcon('fa-chevron-left') + ->setHref($project->getURI())); + + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Edit Details')) + ->setIcon('fa-pencil') + ->setHref($this->getApplicationURI("edit/{$id}/")) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit)); + + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Edit Picture')) + ->setIcon('fa-picture-o') + ->setHref($this->getApplicationURI("picture/{$id}/")) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit)); + + if ($project->isArchived()) { + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Activate Project')) + ->setIcon('fa-check') + ->setHref($this->getApplicationURI("archive/{$id}/")) + ->setDisabled(!$can_edit) + ->setWorkflow(true)); + } else { + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Archive Project')) + ->setIcon('fa-ban') + ->setHref($this->getApplicationURI("archive/{$id}/")) + ->setDisabled(!$can_edit) + ->setWorkflow(true)); + } + + return $view; + } + + private function buildPropertyListView( + PhabricatorProject $project, + PhabricatorActionListView $actions) { + $request = $this->getRequest(); + $viewer = $request->getUser(); + + $view = id(new PHUIPropertyListView()) + ->setUser($viewer) + ->setActionList($actions); + + return $view; + } + + +} diff --git a/src/applications/project/controller/PhabricatorProjectProfileController.php b/src/applications/project/controller/PhabricatorProjectProfileController.php index 89600e97d7..9bb694d9ba 100644 --- a/src/applications/project/controller/PhabricatorProjectProfileController.php +++ b/src/applications/project/controller/PhabricatorProjectProfileController.php @@ -8,13 +8,12 @@ final class PhabricatorProjectProfileController } public function handleRequest(AphrontRequest $request) { - $viewer = $request->getUser(); - $response = $this->loadProject(); if ($response) { return $response; } + $viewer = $request->getUser(); $project = $this->getProject(); $id = $project->getID(); $picture = $project->getProfileImageURI(); @@ -38,14 +37,46 @@ final class PhabricatorProjectProfileController ->setHeader($header) ->addPropertyList($properties); - $timeline = $this->buildTransactionTimeline( - $project, - new PhabricatorProjectTransactionQuery()); - $timeline->setShouldTerminate(true); + $member_list = id(new PhabricatorProjectMemberListView()) + ->setUser($viewer) + ->setProject($project) + ->setLimit(5) + ->setUserPHIDs($project->getMemberPHIDs()); + + $watcher_list = id(new PhabricatorProjectWatcherListView()) + ->setUser($viewer) + ->setProject($project) + ->setLimit(5) + ->setUserPHIDs($project->getWatcherPHIDs()); $nav = $this->getProfileMenu(); $nav->selectFilter(PhabricatorProject::PANEL_PROFILE); + + $stories = id(new PhabricatorFeedQuery()) + ->setViewer($viewer) + ->setFilterPHIDs( + array( + $project->getPHID(), + )) + ->setLimit(50) + ->execute(); + + $feed = $this->renderStories($stories); + + $feed = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Recent Activity')) + ->appendChild($feed); + + $columns = id(new AphrontMultiColumnView()) + ->setFluidLayout(true) + ->addColumn($feed) + ->addColumn( + array( + $member_list, + $watcher_list, + )); + $crumbs = $this->buildApplicationCrumbs(); return $this->newPage() @@ -53,8 +84,11 @@ final class PhabricatorProjectProfileController ->setCrumbs($crumbs) ->setTitle($project->getName()) ->setPageObjectPHIDs(array($project->getPHID())) - ->appendChild($object_box) - ->appendChild($timeline); + ->appendChild( + array( + $object_box, + $columns, + )); } private function buildActionListView(PhabricatorProject $project) { @@ -67,44 +101,11 @@ final class PhabricatorProjectProfileController ->setUser($viewer) ->setObject($project); - $can_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - $project, - PhabricatorPolicyCapability::CAN_EDIT); - $view->addAction( id(new PhabricatorActionView()) - ->setName(pht('Edit Details')) + ->setName(pht('Edit Project')) ->setIcon('fa-pencil') - ->setHref($this->getApplicationURI("edit/{$id}/")) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit)); - - $view->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Edit Picture')) - ->setIcon('fa-picture-o') - ->setHref($this->getApplicationURI("picture/{$id}/")) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit)); - - if ($project->isArchived()) { - $view->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Activate Project')) - ->setIcon('fa-check') - ->setHref($this->getApplicationURI("archive/{$id}/")) - ->setDisabled(!$can_edit) - ->setWorkflow(true)); - } else { - $view->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Archive Project')) - ->setIcon('fa-ban') - ->setHref($this->getApplicationURI("archive/{$id}/")) - ->setDisabled(!$can_edit) - ->setWorkflow(true)); - } + ->setHref($this->getApplicationURI("history/{$id}/"))); return $view; } @@ -120,33 +121,6 @@ final class PhabricatorProjectProfileController ->setObject($project) ->setActionList($actions); - $hashtags = array(); - foreach ($project->getSlugs() as $slug) { - $hashtags[] = id(new PHUITagView()) - ->setType(PHUITagView::TYPE_OBJECT) - ->setName('#'.$slug->getSlug()); - } - - if ($hashtags) { - $view->addProperty(pht('Hashtags'), phutil_implode_html(' ', $hashtags)); - } - - $view->addProperty( - pht('Members'), - $project->getMemberPHIDs() - ? $viewer - ->renderHandleList($project->getMemberPHIDs()) - ->setAsInline(true) - : phutil_tag('em', array(), pht('None'))); - - $view->addProperty( - pht('Watchers'), - $project->getWatcherPHIDs() - ? $viewer - ->renderHandleList($project->getWatcherPHIDs()) - ->setAsInline(true) - : phutil_tag('em', array(), pht('None'))); - $view->addProperty( pht('Looks Like'), $viewer->renderHandle($project->getPHID())->setAsTag(true)); @@ -159,5 +133,15 @@ final class PhabricatorProjectProfileController return $view; } + private function renderStories(array $stories) { + assert_instances_of($stories, 'PhabricatorFeedStory'); + + $builder = new PhabricatorFeedBuilder($stories); + $builder->setUser($this->getRequest()->getUser()); + $builder->setShowHovercards(true); + $view = $builder->buildView(); + + return phutil_tag_div('profile-feed', $view->render()); + } } diff --git a/src/applications/project/engine/PhabricatorProjectEditEngine.php b/src/applications/project/engine/PhabricatorProjectEditEngine.php index 389c585fce..42a2000c86 100644 --- a/src/applications/project/engine/PhabricatorProjectEditEngine.php +++ b/src/applications/project/engine/PhabricatorProjectEditEngine.php @@ -78,7 +78,12 @@ final class PhabricatorProjectEditEngine } protected function getObjectViewURI($object) { - return $object->getURI(); + if ($this->getIsCreate()) { + return $object->getURI(); + } else { + $id = $object->getID(); + return "/project/history/{$id}/"; + } } protected function getObjectCreateCancelURI($object) { diff --git a/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php b/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php index d37caeecf8..f88faa15c4 100644 --- a/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php +++ b/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php @@ -32,15 +32,6 @@ final class PhabricatorProjectProfilePanelEngine ->setPanelProperty('name', pht('Open Tasks')) ->setPanelProperty('uri', $uri); - // TODO: This is temporary. - $id = $object->getID(); - $panels[] = $this->newPanel() - ->setBuiltinKey('feed') - ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) - ->setPanelProperty('icon', 'feed') - ->setPanelProperty('name', pht('Feed')) - ->setPanelProperty('uri', "/project/feed/{$id}/"); - $panels[] = $this->newPanel() ->setBuiltinKey(PhabricatorProject::PANEL_MEMBERS) ->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY); diff --git a/src/applications/project/view/PhabricatorProjectUserListView.php b/src/applications/project/view/PhabricatorProjectUserListView.php index e42b427ed3..f93b9da695 100644 --- a/src/applications/project/view/PhabricatorProjectUserListView.php +++ b/src/applications/project/view/PhabricatorProjectUserListView.php @@ -4,6 +4,7 @@ abstract class PhabricatorProjectUserListView extends AphrontView { private $project; private $userPHIDs; + private $limit; public function setProject(PhabricatorProject $project) { $this->project = $project; @@ -23,6 +24,15 @@ abstract class PhabricatorProjectUserListView extends AphrontView { return $this->userPHIDs; } + public function setLimit($limit) { + $this->limit = $limit; + return $this; + } + + public function getLimit() { + return $this->limit; + } + abstract protected function canEditList(); abstract protected function getNoDataString(); abstract protected function getRemoveURI($phid); @@ -39,7 +49,14 @@ abstract class PhabricatorProjectUserListView extends AphrontView { $list = id(new PHUIObjectItemListView()) ->setNoDataString($no_data); - $user_phids = array_reverse($user_phids); + $limit = $this->getLimit(); + + // If we're showing everything, show oldest to newest. If we're showing + // only a slice, show newest to oldest. + if (!$limit) { + $user_phids = array_reverse($user_phids); + } + $handles = $viewer->loadHandles($user_phids); // Always put the viewer first if they are on the list. @@ -48,7 +65,13 @@ abstract class PhabricatorProjectUserListView extends AphrontView { array_select_keys($user_phids, array($viewer->getPHID())) + $user_phids; - foreach ($user_phids as $user_phid) { + if ($limit) { + $render_phids = array_slice($user_phids, 0, $limit); + } else { + $render_phids = $user_phids; + } + + foreach ($render_phids as $user_phid) { $handle = $handles[$user_phid]; $item = id(new PHUIObjectItemView()) @@ -70,8 +93,17 @@ abstract class PhabricatorProjectUserListView extends AphrontView { $list->addItem($item); } + if ($user_phids) { + $header = pht( + '%s (%s)', + $this->getHeaderText(), + phutil_count($user_phids)); + } else { + $header = $this->getHeaderText(); + } + return id(new PHUIObjectBoxView()) - ->setHeaderText($this->getHeaderText()) + ->setHeaderText($header) ->setObjectList($list); } From a8dd74d292ebfcae77aaa6c0fac6081d86cb4724 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 19 Jan 2016 17:18:17 -0800 Subject: [PATCH 39/66] Add Herald support for projects Summary: Ref T10054. Ref T6113. I'm going to remove subscribers from projects to fix the confusion between "watch" and "subscribe". Users who have unusual use cases where they legitimately want to know when a project's description is updated or members change can use Herald to follow it. This is also useful in general and improves consistency, although I don't have too many use cases for it. Test Plan: Wrote a Herald rule, edited a project, saw the rule fire and send me email about the change. Reviewers: chad Reviewed By: chad Maniphest Tasks: T6113, T10054 Differential Revision: https://secure.phabricator.com/D15061 --- resources/celerity/map.php | 4 +- src/__phutil_library_map__.php | 6 ++ .../PhabricatorProjectTransactionEditor.php | 15 +++++ .../herald/HeraldExactProjectsField.php | 31 +++++++++ .../PhabricatorProjectHeraldAdapter.php | 66 +++++++++++++++++++ .../PhabricatorProjectHeraldFieldGroup.php | 15 +++++ webroot/rsrc/css/phui/phui-workboard-view.css | 5 ++ 7 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 src/applications/project/herald/HeraldExactProjectsField.php create mode 100644 src/applications/project/herald/PhabricatorProjectHeraldAdapter.php create mode 100644 src/applications/project/herald/PhabricatorProjectHeraldFieldGroup.php diff --git a/resources/celerity/map.php b/resources/celerity/map.php index d7ae6285ef..5fc600a356 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -152,7 +152,7 @@ return array( 'rsrc/css/phui/phui-text.css' => 'cf019f54', 'rsrc/css/phui/phui-timeline-view.css' => '2efceff8', 'rsrc/css/phui/phui-two-column-view.css' => '39ecafb1', - 'rsrc/css/phui/phui-workboard-view.css' => '95a54f74', + 'rsrc/css/phui/phui-workboard-view.css' => '8330bca5', 'rsrc/css/phui/phui-workpanel-view.css' => 'adec7699', 'rsrc/css/sprite-login.css' => '60e8560e', 'rsrc/css/sprite-menu.css' => '9dd65b92', @@ -829,7 +829,7 @@ return array( 'phui-theme-css' => '981a58f8', 'phui-timeline-view-css' => '2efceff8', 'phui-two-column-view-css' => '39ecafb1', - 'phui-workboard-view-css' => '95a54f74', + 'phui-workboard-view-css' => '8330bca5', 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index a204da62da..5fc682cfd0 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1147,6 +1147,7 @@ phutil_register_library_map(array( 'HeraldEffect' => 'applications/herald/engine/HeraldEffect.php', 'HeraldEmptyFieldValue' => 'applications/herald/value/HeraldEmptyFieldValue.php', 'HeraldEngine' => 'applications/herald/engine/HeraldEngine.php', + 'HeraldExactProjectsField' => 'applications/project/herald/HeraldExactProjectsField.php', 'HeraldField' => 'applications/herald/field/HeraldField.php', 'HeraldFieldGroup' => 'applications/herald/field/HeraldFieldGroup.php', 'HeraldFieldTestCase' => 'applications/herald/field/__tests__/HeraldFieldTestCase.php', @@ -2883,6 +2884,8 @@ phutil_register_library_map(array( 'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php', 'PhabricatorProjectFulltextEngine' => 'applications/project/search/PhabricatorProjectFulltextEngine.php', 'PhabricatorProjectHeraldAction' => 'applications/project/herald/PhabricatorProjectHeraldAction.php', + 'PhabricatorProjectHeraldAdapter' => 'applications/project/herald/PhabricatorProjectHeraldAdapter.php', + 'PhabricatorProjectHeraldFieldGroup' => 'applications/project/herald/PhabricatorProjectHeraldFieldGroup.php', 'PhabricatorProjectHistoryController' => 'applications/project/controller/PhabricatorProjectHistoryController.php', 'PhabricatorProjectIconSet' => 'applications/project/icon/PhabricatorProjectIconSet.php', 'PhabricatorProjectInterface' => 'applications/project/interface/PhabricatorProjectInterface.php', @@ -5247,6 +5250,7 @@ phutil_register_library_map(array( 'HeraldEffect' => 'Phobject', 'HeraldEmptyFieldValue' => 'HeraldFieldValue', 'HeraldEngine' => 'Phobject', + 'HeraldExactProjectsField' => 'HeraldField', 'HeraldField' => 'Phobject', 'HeraldFieldGroup' => 'HeraldGroup', 'HeraldFieldTestCase' => 'PhutilTestCase', @@ -7285,6 +7289,8 @@ phutil_register_library_map(array( 'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController', 'PhabricatorProjectFulltextEngine' => 'PhabricatorFulltextEngine', 'PhabricatorProjectHeraldAction' => 'HeraldAction', + 'PhabricatorProjectHeraldAdapter' => 'HeraldAdapter', + 'PhabricatorProjectHeraldFieldGroup' => 'HeraldFieldGroup', 'PhabricatorProjectHistoryController' => 'PhabricatorProjectController', 'PhabricatorProjectIconSet' => 'PhabricatorIconSet', 'PhabricatorProjectListController' => 'PhabricatorProjectController', diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php index 6db9b774e6..215db165ae 100644 --- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php +++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php @@ -917,4 +917,19 @@ final class PhabricatorProjectTransactionEditor ->save(); } + + protected function shouldApplyHeraldRules( + PhabricatorLiskDAO $object, + array $xactions) { + return true; + } + + protected function buildHeraldAdapter( + PhabricatorLiskDAO $object, + array $xactions) { + + return id(new PhabricatorProjectHeraldAdapter()) + ->setProject($object); + } + } diff --git a/src/applications/project/herald/HeraldExactProjectsField.php b/src/applications/project/herald/HeraldExactProjectsField.php new file mode 100644 index 0000000000..73f91e36dc --- /dev/null +++ b/src/applications/project/herald/HeraldExactProjectsField.php @@ -0,0 +1,31 @@ +getPHID()); + } + + protected function getHeraldFieldStandardType() { + return self::STANDARD_PHID_LIST; + } + + protected function getDatasource() { + return new PhabricatorProjectDatasource(); + } + +} diff --git a/src/applications/project/herald/PhabricatorProjectHeraldAdapter.php b/src/applications/project/herald/PhabricatorProjectHeraldAdapter.php new file mode 100644 index 0000000000..f6d0984cb6 --- /dev/null +++ b/src/applications/project/herald/PhabricatorProjectHeraldAdapter.php @@ -0,0 +1,66 @@ +project = $this->newObject(); + } + + public function supportsApplicationEmail() { + return true; + } + + public function getRepetitionOptions() { + return array( + HeraldRepetitionPolicyConfig::EVERY, + HeraldRepetitionPolicyConfig::FIRST, + ); + } + + public function supportsRuleType($rule_type) { + switch ($rule_type) { + case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: + case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: + return true; + case HeraldRuleTypeConfig::RULE_TYPE_OBJECT: + default: + return false; + } + } + + public function setProject(PhabricatorProject $project) { + $this->project = $project; + return $this; + } + + public function getProject() { + return $this->project; + } + + public function getObject() { + return $this->project; + } + + public function getAdapterContentName() { + return pht('Projects'); + } + + public function getHeraldName() { + return pht('Project %s', $this->getProject()->getName()); + } + +} diff --git a/src/applications/project/herald/PhabricatorProjectHeraldFieldGroup.php b/src/applications/project/herald/PhabricatorProjectHeraldFieldGroup.php new file mode 100644 index 0000000000..ba219f64b5 --- /dev/null +++ b/src/applications/project/herald/PhabricatorProjectHeraldFieldGroup.php @@ -0,0 +1,15 @@ + Date: Tue, 19 Jan 2016 17:33:11 -0800 Subject: [PATCH 40/66] Allow project editors to remove watchers Summary: Ref T10054. There is no technical or product reason not to support this, and it is largely analogous to removing subscribers. Test Plan: - Removed watchers. - Removed members. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15062 --- .../PhabricatorProjectApplication.php | 2 +- ...bricatorProjectMembersRemoveController.php | 63 ++++++++++++------- .../PhabricatorProjectWatcherListView.php | 12 +++- 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/src/applications/project/application/PhabricatorProjectApplication.php b/src/applications/project/application/PhabricatorProjectApplication.php index e1b484ffe2..c25a1b223f 100644 --- a/src/applications/project/application/PhabricatorProjectApplication.php +++ b/src/applications/project/application/PhabricatorProjectApplication.php @@ -51,7 +51,7 @@ final class PhabricatorProjectApplication extends PhabricatorApplication { => 'PhabricatorProjectMembersViewController', 'members/(?P[1-9]\d*)/add/' => 'PhabricatorProjectMembersAddController', - 'members/(?P[1-9]\d*)/remove/' + '(?Pmembers|watchers)/(?P[1-9]\d*)/remove/' => 'PhabricatorProjectMembersRemoveController', 'profile/(?P[1-9]\d*)/' => 'PhabricatorProjectProfileController', diff --git a/src/applications/project/controller/PhabricatorProjectMembersRemoveController.php b/src/applications/project/controller/PhabricatorProjectMembersRemoveController.php index cad3f35c05..ea41ea7113 100644 --- a/src/applications/project/controller/PhabricatorProjectMembersRemoveController.php +++ b/src/applications/project/controller/PhabricatorProjectMembersRemoveController.php @@ -6,11 +6,13 @@ final class PhabricatorProjectMembersRemoveController public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); $id = $request->getURIData('id'); + $type = $request->getURIData('type'); $project = id(new PhabricatorProjectQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needMembers(true) + ->needWatchers(true) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, @@ -21,27 +23,31 @@ final class PhabricatorProjectMembersRemoveController return new Aphront404Response(); } - $member_phids = $project->getMemberPHIDs(); - $remove_phid = $request->getStr('phid'); + if ($type == 'watchers') { + $is_watcher = true; + $edge_type = PhabricatorObjectHasWatcherEdgeType::EDGECONST; + } else { + if (!$project->supportsEditMembers()) { + return new Aphront404Response(); + } - if (!in_array($remove_phid, $member_phids)) { - return new Aphront404Response(); + $is_watcher = false; + $edge_type = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; } $members_uri = $this->getApplicationURI('members/'.$project->getID().'/'); + $remove_phid = $request->getStr('phid'); if ($request->isFormPost()) { - $member_spec = array(); - $member_spec['-'] = array($remove_phid => $remove_phid); - - $type_member = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; - $xactions = array(); $xactions[] = id(new PhabricatorProjectTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) - ->setMetadataValue('edge:type', $type_member) - ->setNewValue($member_spec); + ->setMetadataValue('edge:type', $edge_type) + ->setNewValue( + array( + '-' => array($remove_phid => $remove_phid), + )); $editor = id(new PhabricatorProjectTransactionEditor($project)) ->setActor($viewer) @@ -59,18 +65,31 @@ final class PhabricatorProjectMembersRemoveController ->withPHIDs(array($remove_phid)) ->executeOne(); - $dialog = id(new AphrontDialogView()) - ->setUser($viewer) - ->setTitle(pht('Really Remove Member?')) - ->appendParagraph( - pht( - 'Really remove %s from the project %s?', - phutil_tag('strong', array(), $handle->getName()), - phutil_tag('strong', array(), $project->getName()))) - ->addCancelButton($members_uri) - ->addSubmitButton(pht('Remove Project Member')); + $target_name = phutil_tag('strong', array(), $handle->getName()); + $project_name = phutil_tag('strong', array(), $project->getName()); - return id(new AphrontDialogResponse())->setDialog($dialog); + if ($is_watcher) { + $title = pht('Remove Watcher'); + $body = pht( + 'Remove %s as a watcher of %s?', + $target_name, + $project_name); + $button = pht('Remove Watcher'); + } else { + $title = pht('Remove Member'); + $body = pht( + 'Remove %s as a project member of %s?', + $target_name, + $project_name); + $button = pht('Remove Member'); + } + + return $this->newDialog() + ->setTitle($title) + ->addHiddenInput('phid', $remove_phid) + ->appendParagraph($body) + ->addCancelButton($members_uri) + ->addSubmitButton($button); } } diff --git a/src/applications/project/view/PhabricatorProjectWatcherListView.php b/src/applications/project/view/PhabricatorProjectWatcherListView.php index ec993f031c..7aa9638afc 100644 --- a/src/applications/project/view/PhabricatorProjectWatcherListView.php +++ b/src/applications/project/view/PhabricatorProjectWatcherListView.php @@ -4,7 +4,13 @@ final class PhabricatorProjectWatcherListView extends PhabricatorProjectUserListView { protected function canEditList() { - return false; + $viewer = $this->getUser(); + $project = $this->getProject(); + + return PhabricatorPolicyFilter::hasCapability( + $viewer, + $project, + PhabricatorPolicyCapability::CAN_EDIT); } protected function getNoDataString() { @@ -12,7 +18,9 @@ final class PhabricatorProjectWatcherListView } protected function getRemoveURI($phid) { - return null; + $project = $this->getProject(); + $id = $project->getID(); + return "/project/watchers/{$id}/remove/?phid={$phid}"; } protected function getHeaderText() { From 5c2e49a81223368aab906fafd47087432ac9f740 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 19 Jan 2016 17:43:14 -0800 Subject: [PATCH 41/66] Allow any user to watch any project they can see Summary: Ref T6183. Ref T10054. Historically, only members could watch projects because there were some weird special cases with policies. These policy issues have been resolved and Herald is generally powerful enough to do equivalent watches on most objects anyway. Also puts a "Watch Project" button on the feed panel to make the behavior and meaning more obvious. Test Plan: - Watched a project I was not a member of. - Clicked the feed watch/unwatch button. {F1064909} Reviewers: chad Reviewed By: chad Maniphest Tasks: T6183, T10054 Differential Revision: https://secure.phabricator.com/D15063 --- .../badges/storage/PhabricatorBadgesBadge.php | 4 -- .../storage/PhabricatorCalendarEvent.php | 4 -- .../storage/PhabricatorCountdown.php | 4 -- .../storage/DifferentialRevision.php | 4 -- .../files/storage/PhabricatorFile.php | 4 -- .../fund/storage/FundInitiative.php | 4 -- .../configuration/HarbormasterBuildPlan.php | 4 -- .../herald/storage/HeraldRule.php | 4 -- .../legalpad/storage/LegalpadDocument.php | 4 -- .../storage/PhabricatorFileImageMacro.php | 4 -- .../maniphest/storage/ManiphestTask.php | 4 -- .../storage/PassphraseCredential.php | 4 -- .../paste/storage/PhabricatorPaste.php | 4 -- src/applications/phame/storage/PhameBlog.php | 4 -- src/applications/phame/storage/PhamePost.php | 4 -- .../pholio/storage/PholioMock.php | 4 -- .../phriction/storage/PhrictionDocument.php | 4 -- .../phurl/storage/PhabricatorPhurlURL.php | 4 -- .../ponder/storage/PonderAnswer.php | 4 -- .../ponder/storage/PonderQuestion.php | 4 -- ...habricatorProjectMembersViewController.php | 30 +++++++-------- .../PhabricatorProjectProfileController.php | 37 ++++++++++++++++++- .../PhabricatorProjectWatchController.php | 15 ++++---- .../PhabricatorProjectTransactionEditor.php | 34 ++++------------- .../project/storage/PhabricatorProject.php | 5 --- .../view/PhabricatorProjectUserListView.php | 24 ++++++++++-- .../storage/PhabricatorRepositoryCommit.php | 4 -- .../storage/PhabricatorSlowvotePoll.php | 4 -- ...PhabricatorSubscriptionsEditController.php | 7 ---- ...habricatorSubscriptionsUIEventListener.php | 5 --- .../PhabricatorSubscribableInterface.php | 15 -------- .../storage/PhabricatorWorkerBulkJob.php | 4 -- 32 files changed, 87 insertions(+), 177 deletions(-) diff --git a/src/applications/badges/storage/PhabricatorBadgesBadge.php b/src/applications/badges/storage/PhabricatorBadgesBadge.php index 29cccb9f44..254b02a6eb 100644 --- a/src/applications/badges/storage/PhabricatorBadgesBadge.php +++ b/src/applications/badges/storage/PhabricatorBadgesBadge.php @@ -185,10 +185,6 @@ final class PhabricatorBadgesBadge extends PhabricatorBadgesDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorTokenReceiverInterface )---------------------------------- */ diff --git a/src/applications/calendar/storage/PhabricatorCalendarEvent.php b/src/applications/calendar/storage/PhabricatorCalendarEvent.php index 1b4c1a760c..36aa905b3e 100644 --- a/src/applications/calendar/storage/PhabricatorCalendarEvent.php +++ b/src/applications/calendar/storage/PhabricatorCalendarEvent.php @@ -535,10 +535,6 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorTokenReceiverInterface )---------------------------------- */ diff --git a/src/applications/countdown/storage/PhabricatorCountdown.php b/src/applications/countdown/storage/PhabricatorCountdown.php index 8753c66223..1a864907eb 100644 --- a/src/applications/countdown/storage/PhabricatorCountdown.php +++ b/src/applications/countdown/storage/PhabricatorCountdown.php @@ -74,10 +74,6 @@ final class PhabricatorCountdown extends PhabricatorCountdownDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorApplicationTransactionInterface )------------------------- */ diff --git a/src/applications/differential/storage/DifferentialRevision.php b/src/applications/differential/storage/DifferentialRevision.php index e534ad9ca7..ff72b46de7 100644 --- a/src/applications/differential/storage/DifferentialRevision.php +++ b/src/applications/differential/storage/DifferentialRevision.php @@ -485,10 +485,6 @@ final class DifferentialRevision extends DifferentialDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorCustomFieldInterface )------------------------------------ */ diff --git a/src/applications/files/storage/PhabricatorFile.php b/src/applications/files/storage/PhabricatorFile.php index 92dd0bcf88..7d2780778f 100644 --- a/src/applications/files/storage/PhabricatorFile.php +++ b/src/applications/files/storage/PhabricatorFile.php @@ -1352,10 +1352,6 @@ final class PhabricatorFile extends PhabricatorFileDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorTokenReceiverInterface )---------------------------------- */ diff --git a/src/applications/fund/storage/FundInitiative.php b/src/applications/fund/storage/FundInitiative.php index 57e86beccf..3375551443 100644 --- a/src/applications/fund/storage/FundInitiative.php +++ b/src/applications/fund/storage/FundInitiative.php @@ -182,10 +182,6 @@ final class FundInitiative extends FundDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorTokenRecevierInterface )---------------------------------- */ diff --git a/src/applications/harbormaster/storage/configuration/HarbormasterBuildPlan.php b/src/applications/harbormaster/storage/configuration/HarbormasterBuildPlan.php index 11cb6260b7..5ac9696813 100644 --- a/src/applications/harbormaster/storage/configuration/HarbormasterBuildPlan.php +++ b/src/applications/harbormaster/storage/configuration/HarbormasterBuildPlan.php @@ -129,10 +129,6 @@ final class HarbormasterBuildPlan extends HarbormasterDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorApplicationTransactionInterface )------------------------- */ diff --git a/src/applications/herald/storage/HeraldRule.php b/src/applications/herald/storage/HeraldRule.php index 51707fcc8a..8d585263c0 100644 --- a/src/applications/herald/storage/HeraldRule.php +++ b/src/applications/herald/storage/HeraldRule.php @@ -332,10 +332,6 @@ final class HeraldRule extends HeraldDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorDestructibleInterface )----------------------------------- */ diff --git a/src/applications/legalpad/storage/LegalpadDocument.php b/src/applications/legalpad/storage/LegalpadDocument.php index 4c6e04a26a..51f158a978 100644 --- a/src/applications/legalpad/storage/LegalpadDocument.php +++ b/src/applications/legalpad/storage/LegalpadDocument.php @@ -167,10 +167,6 @@ final class LegalpadDocument extends LegalpadDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorPolicyInterface )----------------------------------------- */ diff --git a/src/applications/macro/storage/PhabricatorFileImageMacro.php b/src/applications/macro/storage/PhabricatorFileImageMacro.php index 72a6577924..5cf23133a3 100644 --- a/src/applications/macro/storage/PhabricatorFileImageMacro.php +++ b/src/applications/macro/storage/PhabricatorFileImageMacro.php @@ -115,10 +115,6 @@ final class PhabricatorFileImageMacro extends PhabricatorFileDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorTokenRecevierInterface )---------------------------------- */ diff --git a/src/applications/maniphest/storage/ManiphestTask.php b/src/applications/maniphest/storage/ManiphestTask.php index 9f8dad1cd8..cc9a5bd80a 100644 --- a/src/applications/maniphest/storage/ManiphestTask.php +++ b/src/applications/maniphest/storage/ManiphestTask.php @@ -227,10 +227,6 @@ final class ManiphestTask extends ManiphestDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( Markup Interface )--------------------------------------------------- */ diff --git a/src/applications/passphrase/storage/PassphraseCredential.php b/src/applications/passphrase/storage/PassphraseCredential.php index 4d705aff83..f263523b49 100644 --- a/src/applications/passphrase/storage/PassphraseCredential.php +++ b/src/applications/passphrase/storage/PassphraseCredential.php @@ -161,10 +161,6 @@ final class PassphraseCredential extends PassphraseDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorDestructibleInterface )----------------------------------- */ diff --git a/src/applications/paste/storage/PhabricatorPaste.php b/src/applications/paste/storage/PhabricatorPaste.php index 022b998bac..624c70c410 100644 --- a/src/applications/paste/storage/PhabricatorPaste.php +++ b/src/applications/paste/storage/PhabricatorPaste.php @@ -159,10 +159,6 @@ final class PhabricatorPaste extends PhabricatorPasteDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorTokenReceiverInterface )---------------------------------- */ diff --git a/src/applications/phame/storage/PhameBlog.php b/src/applications/phame/storage/PhameBlog.php index 5b5b128ae6..d9b9bdb41d 100644 --- a/src/applications/phame/storage/PhameBlog.php +++ b/src/applications/phame/storage/PhameBlog.php @@ -340,10 +340,6 @@ final class PhameBlog extends PhameDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorConduitResultInterface )---------------------------------- */ diff --git a/src/applications/phame/storage/PhamePost.php b/src/applications/phame/storage/PhamePost.php index 57519bd2f1..01dd71e88d 100644 --- a/src/applications/phame/storage/PhamePost.php +++ b/src/applications/phame/storage/PhamePost.php @@ -286,10 +286,6 @@ final class PhamePost extends PhameDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorConduitResultInterface )---------------------------------- */ diff --git a/src/applications/pholio/storage/PholioMock.php b/src/applications/pholio/storage/PholioMock.php index 6316d92cb9..c817b7f32b 100644 --- a/src/applications/pholio/storage/PholioMock.php +++ b/src/applications/pholio/storage/PholioMock.php @@ -188,10 +188,6 @@ final class PholioMock extends PholioDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorPolicyInterface Implementation )-------------------------- */ diff --git a/src/applications/phriction/storage/PhrictionDocument.php b/src/applications/phriction/storage/PhrictionDocument.php index 3c883625b0..915cfed1eb 100644 --- a/src/applications/phriction/storage/PhrictionDocument.php +++ b/src/applications/phriction/storage/PhrictionDocument.php @@ -198,10 +198,6 @@ final class PhrictionDocument extends PhrictionDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorApplicationTransactionInterface )------------------------- */ diff --git a/src/applications/phurl/storage/PhabricatorPhurlURL.php b/src/applications/phurl/storage/PhabricatorPhurlURL.php index 7df1d241a7..30a3b0b93b 100644 --- a/src/applications/phurl/storage/PhabricatorPhurlURL.php +++ b/src/applications/phurl/storage/PhabricatorPhurlURL.php @@ -173,10 +173,6 @@ final class PhabricatorPhurlURL extends PhabricatorPhurlDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorTokenReceiverInterface )---------------------------------- */ diff --git a/src/applications/ponder/storage/PonderAnswer.php b/src/applications/ponder/storage/PonderAnswer.php index 722fee8eec..4da222d5a5 100644 --- a/src/applications/ponder/storage/PonderAnswer.php +++ b/src/applications/ponder/storage/PonderAnswer.php @@ -253,10 +253,6 @@ final class PonderAnswer extends PonderDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorDestructibleInterface )----------------------------------- */ diff --git a/src/applications/ponder/storage/PonderQuestion.php b/src/applications/ponder/storage/PonderQuestion.php index bbce081d88..5ab719e3ac 100644 --- a/src/applications/ponder/storage/PonderQuestion.php +++ b/src/applications/ponder/storage/PonderQuestion.php @@ -252,10 +252,6 @@ final class PonderQuestion extends PonderDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorTokenReceiverInterface )---------------------------------- */ diff --git a/src/applications/project/controller/PhabricatorProjectMembersViewController.php b/src/applications/project/controller/PhabricatorProjectMembersViewController.php index dd9f263e5d..9189b1ad8d 100644 --- a/src/applications/project/controller/PhabricatorProjectMembersViewController.php +++ b/src/applications/project/controller/PhabricatorProjectMembersViewController.php @@ -152,22 +152,22 @@ final class PhabricatorProjectMembersViewController ->setDisabled(!$can_leave) ->setWorkflow(true) ->setName(pht('Leave Project'))); + } - if (!$project->isUserWatcher($viewer->getPHID())) { - $view->addAction( - id(new PhabricatorActionView()) - ->setWorkflow(true) - ->setHref('/project/watch/'.$project->getID().'/') - ->setIcon('fa-eye') - ->setName(pht('Watch Project'))); - } else { - $view->addAction( - id(new PhabricatorActionView()) - ->setWorkflow(true) - ->setHref('/project/unwatch/'.$project->getID().'/') - ->setIcon('fa-eye-slash') - ->setName(pht('Unwatch Project'))); - } + if (!$project->isUserWatcher($viewer->getPHID())) { + $view->addAction( + id(new PhabricatorActionView()) + ->setWorkflow(true) + ->setHref('/project/watch/'.$project->getID().'/') + ->setIcon('fa-eye') + ->setName(pht('Watch Project'))); + } else { + $view->addAction( + id(new PhabricatorActionView()) + ->setWorkflow(true) + ->setHref('/project/unwatch/'.$project->getID().'/') + ->setIcon('fa-eye-slash') + ->setName(pht('Unwatch Project'))); } $can_add = $can_edit && $supports_edit; diff --git a/src/applications/project/controller/PhabricatorProjectProfileController.php b/src/applications/project/controller/PhabricatorProjectProfileController.php index 9bb694d9ba..721193c469 100644 --- a/src/applications/project/controller/PhabricatorProjectProfileController.php +++ b/src/applications/project/controller/PhabricatorProjectProfileController.php @@ -52,6 +52,7 @@ final class PhabricatorProjectProfileController $nav = $this->getProfileMenu(); $nav->selectFilter(PhabricatorProject::PANEL_PROFILE); + $watch_action = $this->renderWatchAction($project); $stories = id(new PhabricatorFeedQuery()) ->setViewer($viewer) @@ -62,10 +63,15 @@ final class PhabricatorProjectProfileController ->setLimit(50) ->execute(); + $feed = $this->renderStories($stories); + $feed_header = id(new PHUIHeaderView()) + ->setHeader(pht('Recent Activity')) + ->addActionLink($watch_action); + $feed = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Recent Activity')) + ->setHeader($feed_header) ->appendChild($feed); $columns = id(new AphrontMultiColumnView()) @@ -144,4 +150,33 @@ final class PhabricatorProjectProfileController return phutil_tag_div('profile-feed', $view->render()); } + private function renderWatchAction(PhabricatorProject $project) { + $viewer = $this->getViewer(); + $viewer_phid = $viewer->getPHID(); + $id = $project->getID(); + + $is_watcher = ($viewer_phid && $project->isUserWatcher($viewer_phid)); + + if (!$is_watcher) { + $watch_icon = 'fa-eye'; + $watch_text = pht('Watch Project'); + $watch_href = "/project/watch/{$id}/?via=profile"; + } else { + $watch_icon = 'fa-eye-slash'; + $watch_text = pht('Unwatch Project'); + $watch_href = "/project/unwatch/{$id}/?via=profile"; + } + + $watch_icon = id(new PHUIIconView()) + ->setIconFont($watch_icon); + + return id(new PHUIButtonView()) + ->setTag('a') + ->setWorkflow(true) + ->setIcon($watch_icon) + ->setText($watch_text) + ->setHref($watch_href); + } + + } diff --git a/src/applications/project/controller/PhabricatorProjectWatchController.php b/src/applications/project/controller/PhabricatorProjectWatchController.php index c39e7dd510..d8b818cb63 100644 --- a/src/applications/project/controller/PhabricatorProjectWatchController.php +++ b/src/applications/project/controller/PhabricatorProjectWatchController.php @@ -18,11 +18,11 @@ final class PhabricatorProjectWatchController return new Aphront404Response(); } - $done_uri = "/project/members/{$id}/"; - - // You must be a member of a project to watch it. - if (!$project->isUserMember($viewer->getPHID())) { - return new Aphront400Response(); + $via = $request->getStr('via'); + if ($via == 'profile') { + $done_uri = $project->getURI(); + } else { + $done_uri = "/project/members/{$id}/"; } if ($request->isDialogFormPost()) { @@ -38,7 +38,7 @@ final class PhabricatorProjectWatchController break; } - $type_member = PhabricatorObjectHasWatcherEdgeType::EDGECONST; + $type_watcher = PhabricatorObjectHasWatcherEdgeType::EDGECONST; $member_spec = array( $edge_action => array($viewer->getPHID() => $viewer->getPHID()), ); @@ -46,7 +46,7 @@ final class PhabricatorProjectWatchController $xactions = array(); $xactions[] = id(new PhabricatorProjectTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) - ->setMetadataValue('edge:type', $type_member) + ->setMetadataValue('edge:type', $type_watcher) ->setNewValue($member_spec); $editor = id(new PhabricatorProjectTransactionEditor($project)) @@ -82,6 +82,7 @@ final class PhabricatorProjectWatchController return $this->newDialog() ->setTitle($title) + ->addHiddenInput('via', $via) ->appendParagraph($body) ->addCancelButton($done_uri) ->addSubmitButton($submit); diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php index 215db165ae..ef3f165356 100644 --- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php +++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php @@ -188,21 +188,18 @@ final class PhabricatorProjectTransactionEditor switch ($edge_type) { case PhabricatorProjectProjectHasMemberEdgeType::EDGECONST: case PhabricatorObjectHasWatcherEdgeType::EDGECONST: + $edge_const = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; + if ($edge_type != $edge_const) { + break; + } + $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); - // When adding members or watchers, we add subscriptions. + // When adding members, we add subscriptions. When removing + // members, we remove subscriptions. $add = array_keys(array_diff_key($new, $old)); - - // When removing members, we remove their subscription too. - // When unwatching, we leave subscriptions, since it's fine to be - // subscribed to a project but not be a member of it. - $edge_const = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; - if ($edge_type == $edge_const) { - $rem = array_keys(array_diff_key($old, $new)); - } else { - $rem = array(); - } + $rem = array_keys(array_diff_key($old, $new)); // NOTE: The subscribe is "explicit" because there's no implicit // unsubscribe, so Join -> Leave -> Join doesn't resubscribe you @@ -212,27 +209,12 @@ final class PhabricatorProjectTransactionEditor // this, which is a fairly weird edge case and pretty arguable both // ways. - // Subscriptions caused by watches should also clearly be explicit, - // and that case is unambiguous. - id(new PhabricatorSubscriptionsEditor()) ->setActor($this->requireActor()) ->setObject($object) ->subscribeExplicit($add) ->unsubscribe($rem) ->save(); - - if ($rem) { - // When removing members, also remove any watches on the project. - $edge_editor = new PhabricatorEdgeEditor(); - foreach ($rem as $rem_phid) { - $edge_editor->removeEdge( - $object->getPHID(), - PhabricatorObjectHasWatcherEdgeType::EDGECONST, - $rem_phid); - } - $edge_editor->save(); - } break; } break; diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php index ceaac1a16d..2ea3a2c131 100644 --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -548,11 +548,6 @@ final class PhabricatorProject extends PhabricatorProjectDAO return false; } - public function shouldAllowSubscription($phid) { - return $this->isUserMember($phid) && - !$this->isUserWatcher($phid); - } - /* -( PhabricatorCustomFieldInterface )------------------------------------ */ diff --git a/src/applications/project/view/PhabricatorProjectUserListView.php b/src/applications/project/view/PhabricatorProjectUserListView.php index f93b9da695..138d51cbf3 100644 --- a/src/applications/project/view/PhabricatorProjectUserListView.php +++ b/src/applications/project/view/PhabricatorProjectUserListView.php @@ -79,7 +79,7 @@ abstract class PhabricatorProjectUserListView extends AphrontView { ->setHref($handle->getURI()) ->setImageURI($handle->getImageURI()); - if ($can_edit) { + if ($can_edit && !$limit) { $remove_uri = $this->getRemoveURI($user_phid); $item->addAction( @@ -94,16 +94,32 @@ abstract class PhabricatorProjectUserListView extends AphrontView { } if ($user_phids) { - $header = pht( + $header_text = pht( '%s (%s)', $this->getHeaderText(), phutil_count($user_phids)); } else { - $header = $this->getHeaderText(); + $header_text = $this->getHeaderText(); + } + + $id = $project->getID(); + + $header = id(new PHUIHeaderView()) + ->setHeader($header_text); + + if ($limit) { + $header->addActionLink( + id(new PHUIButtonView()) + ->setTag('a') + ->setIcon( + id(new PHUIIconView()) + ->setIconFont('fa-list-ul')) + ->setText(pht('View All')) + ->setHref("/project/members/{$id}/")); } return id(new PHUIObjectBoxView()) - ->setHeaderText($header) + ->setHeader($header) ->setObjectList($list); } diff --git a/src/applications/repository/storage/PhabricatorRepositoryCommit.php b/src/applications/repository/storage/PhabricatorRepositoryCommit.php index fc67d8b7b3..348b94d021 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryCommit.php +++ b/src/applications/repository/storage/PhabricatorRepositoryCommit.php @@ -443,10 +443,6 @@ final class PhabricatorRepositoryCommit return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorApplicationTransactionInterface )------------------------- */ diff --git a/src/applications/slowvote/storage/PhabricatorSlowvotePoll.php b/src/applications/slowvote/storage/PhabricatorSlowvotePoll.php index 12f4f9e984..2240c510aa 100644 --- a/src/applications/slowvote/storage/PhabricatorSlowvotePoll.php +++ b/src/applications/slowvote/storage/PhabricatorSlowvotePoll.php @@ -183,10 +183,6 @@ final class PhabricatorSlowvotePoll extends PhabricatorSlowvoteDAO return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorTokenReceiverInterface )---------------------------------- */ diff --git a/src/applications/subscriptions/controller/PhabricatorSubscriptionsEditController.php b/src/applications/subscriptions/controller/PhabricatorSubscriptionsEditController.php index 3723a755be..ad089d8f3d 100644 --- a/src/applications/subscriptions/controller/PhabricatorSubscriptionsEditController.php +++ b/src/applications/subscriptions/controller/PhabricatorSubscriptionsEditController.php @@ -61,13 +61,6 @@ final class PhabricatorSubscriptionsEditController $handle->getURI()); } - if (!$object->shouldAllowSubscription($viewer->getPHID())) { - return $this->buildErrorResponse( - pht('You Can Not Subscribe'), - pht('You can not subscribe to this object.'), - $handle->getURI()); - } - if ($object instanceof PhabricatorApplicationTransactionInterface) { if ($is_add) { $xaction_value = array( diff --git a/src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php b/src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php index fb7c32892f..b69ce4243f 100644 --- a/src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php +++ b/src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php @@ -34,11 +34,6 @@ final class PhabricatorSubscriptionsUIEventListener return; } - if (!$object->shouldAllowSubscription($user_phid)) { - // This object doesn't allow the viewer to subscribe. - return; - } - if ($user_phid && $object->isAutomaticallySubscribed($user_phid)) { $sub_action = id(new PhabricatorActionView()) ->setWorkflow(true) diff --git a/src/applications/subscriptions/interface/PhabricatorSubscribableInterface.php b/src/applications/subscriptions/interface/PhabricatorSubscribableInterface.php index 95275e53bb..e54e2cd42e 100644 --- a/src/applications/subscriptions/interface/PhabricatorSubscribableInterface.php +++ b/src/applications/subscriptions/interface/PhabricatorSubscribableInterface.php @@ -22,17 +22,6 @@ interface PhabricatorSubscribableInterface { */ public function shouldShowSubscribersProperty(); - - /** - * Return `true` to indicate that the "Subscribe" action should be shown and - * enabled when rendering action lists for this object, or `false` to omit - * the action. - * - * @param phid Viewing or acting user PHID. - * @return bool True to allow the user to subscribe. - */ - public function shouldAllowSubscription($phid); - } // TEMPLATE IMPLEMENTATION ///////////////////////////////////////////////////// @@ -48,8 +37,4 @@ interface PhabricatorSubscribableInterface { return true; } - public function shouldAllowSubscription($phid) { - return true; - } - */ diff --git a/src/infrastructure/daemon/workers/storage/PhabricatorWorkerBulkJob.php b/src/infrastructure/daemon/workers/storage/PhabricatorWorkerBulkJob.php index 20d981c576..0b70268cb4 100644 --- a/src/infrastructure/daemon/workers/storage/PhabricatorWorkerBulkJob.php +++ b/src/infrastructure/daemon/workers/storage/PhabricatorWorkerBulkJob.php @@ -222,10 +222,6 @@ final class PhabricatorWorkerBulkJob return true; } - public function shouldAllowSubscription($phid) { - return true; - } - /* -( PhabricatorApplicationTransactionInterface )------------------------- */ From 8463ad2659607886a9cea7d5596ce51a068059c5 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 19 Jan 2016 18:56:15 -0800 Subject: [PATCH 42/66] Replace subscribe/unsubscribe for projects with explicit mail setting Summary: Ref T10054. Ref T6113. Users can currently subscribe to projects, which causes them to receive: # mail about project membership changes, description changes, etc; and # mail to the project, e.g. when the project is added as a subscriber on a task, or a reviewer on a revision. Almost no one cares about (1), and after D15061 you can use Herald to get this stuff if you really want it. (It will get progressively more annoying in the future with external membership sources causing automated project membership updates.) A lot of users are confused about (2) and how it relates to membership, watching, etc, and most users who want (2) don't want (1). Instead, add an explicit option for this and explain what it does. This is fairly verbose but I've hidden it on the member/watch screen, which is now the "explain how projects work" screen, I guess. Test Plan: {F1064929} {F1064930} {F1064931} - Disabled/enabled mail for a project. - Sent mail to a project with mail disabled, verified I didn't get a copy. Reviewers: chad Reviewed By: chad Maniphest Tasks: T6113, T10054 Differential Revision: https://secure.phabricator.com/D15065 --- .../20160119.project.1.silence.sql | 8 ++ src/__phutil_library_map__.php | 5 +- .../query/PhabricatorMetaMTAMemberQuery.php | 38 ++++++-- .../PhabricatorProjectApplication.php | 2 + ...habricatorProjectMembersViewController.php | 80 ++++++++++++++++- .../PhabricatorProjectSilenceController.php | 87 +++++++++++++++++++ .../PhabricatorProjectWatchController.php | 2 - .../PhabricatorProjectSilencedEdgeType.php | 8 ++ .../PhabricatorProjectTransactionEditor.php | 51 +---------- .../engine/PhabricatorProjectEditEngine.php | 1 - .../project/storage/PhabricatorProject.php | 15 ---- .../storage/PhabricatorProjectTransaction.php | 4 - 12 files changed, 225 insertions(+), 76 deletions(-) create mode 100644 resources/sql/autopatches/20160119.project.1.silence.sql create mode 100644 src/applications/project/controller/PhabricatorProjectSilenceController.php create mode 100644 src/applications/project/edge/PhabricatorProjectSilencedEdgeType.php diff --git a/resources/sql/autopatches/20160119.project.1.silence.sql b/resources/sql/autopatches/20160119.project.1.silence.sql new file mode 100644 index 0000000000..3a4dd07fd2 --- /dev/null +++ b/resources/sql/autopatches/20160119.project.1.silence.sql @@ -0,0 +1,8 @@ +/* PhabricatorObjectHasUnsubscriberEdgeType::EDGECONST = 23 */ +/* PhabricatorProjectSilencedEdgeType::EDGECONST = 61 */ + +/* This is converting existing unsubscribes into disabled mail. */ + +INSERT IGNORE INTO {$NAMESPACE}_project.edge (src, type, dst, dateCreated) + SELECT src, 61, dst, dateCreated FROM {$NAMESPACE}_project.edge + WHERE type = 23; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 5fc682cfd0..d606f6c298 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2925,6 +2925,8 @@ phutil_register_library_map(array( 'PhabricatorProjectSchemaSpec' => 'applications/project/storage/PhabricatorProjectSchemaSpec.php', 'PhabricatorProjectSearchEngine' => 'applications/project/query/PhabricatorProjectSearchEngine.php', 'PhabricatorProjectSearchField' => 'applications/project/searchfield/PhabricatorProjectSearchField.php', + 'PhabricatorProjectSilenceController' => 'applications/project/controller/PhabricatorProjectSilenceController.php', + 'PhabricatorProjectSilencedEdgeType' => 'applications/project/edge/PhabricatorProjectSilencedEdgeType.php', 'PhabricatorProjectSlug' => 'applications/project/storage/PhabricatorProjectSlug.php', 'PhabricatorProjectStandardCustomField' => 'applications/project/customfield/PhabricatorProjectStandardCustomField.php', 'PhabricatorProjectStatus' => 'applications/project/constants/PhabricatorProjectStatus.php', @@ -7237,7 +7239,6 @@ phutil_register_library_map(array( 'PhabricatorFlaggableInterface', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', - 'PhabricatorSubscribableInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorDestructibleInterface', 'PhabricatorFulltextInterface', @@ -7329,6 +7330,8 @@ phutil_register_library_map(array( 'PhabricatorProjectSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorProjectSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorProjectSearchField' => 'PhabricatorSearchTokenizerField', + 'PhabricatorProjectSilenceController' => 'PhabricatorProjectController', + 'PhabricatorProjectSilencedEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectSlug' => 'PhabricatorProjectDAO', 'PhabricatorProjectStandardCustomField' => array( 'PhabricatorProjectCustomField', diff --git a/src/applications/metamta/query/PhabricatorMetaMTAMemberQuery.php b/src/applications/metamta/query/PhabricatorMetaMTAMemberQuery.php index f565baf595..e06da5f4e3 100644 --- a/src/applications/metamta/query/PhabricatorMetaMTAMemberQuery.php +++ b/src/applications/metamta/query/PhabricatorMetaMTAMemberQuery.php @@ -42,20 +42,48 @@ final class PhabricatorMetaMTAMemberQuery extends PhabricatorQuery { $projects = id(new PhabricatorProjectQuery()) ->setViewer($this->getViewer()) ->withPHIDs($phids) + ->needMembers(true) + ->needWatchers(true) ->execute(); - $subscribers = id(new PhabricatorSubscribersQuery()) - ->withObjectPHIDs($phids) - ->execute(); + $edge_type = PhabricatorProjectSilencedEdgeType::EDGECONST; + + $edge_query = id(new PhabricatorEdgeQuery()) + ->withSourcePHIDs($phids) + ->withEdgeTypes( + array( + $edge_type, + )); + + $edge_query->execute(); $projects = mpull($projects, null, 'getPHID'); foreach ($phids as $phid) { $project = idx($projects, $phid); + if (!$project) { $results[$phid] = array(); - } else { - $results[$phid] = idx($subscribers, $phid, array()); + continue; } + + // Recipients are members who haven't silenced the project, plus + // watchers. + + $members = $project->getMemberPHIDs(); + $members = array_fuse($members); + + $watchers = $project->getWatcherPHIDs(); + $watchers = array_fuse($watchers); + + $silenced = $edge_query->getDestinationPHIDs( + array($phid), + array($edge_type)); + $silenced = array_fuse($silenced); + + $result_map = array_diff_key($members, $silenced); + $result_map = $result_map + $watchers; + + $results[$phid] = array_values($result_map); } break; default: diff --git a/src/applications/project/application/PhabricatorProjectApplication.php b/src/applications/project/application/PhabricatorProjectApplication.php index c25a1b223f..5f6f7add9f 100644 --- a/src/applications/project/application/PhabricatorProjectApplication.php +++ b/src/applications/project/application/PhabricatorProjectApplication.php @@ -89,6 +89,8 @@ final class PhabricatorProjectApplication extends PhabricatorApplication { 'history/(?P[1-9]\d*)/' => 'PhabricatorProjectHistoryController', '(?Pwatch|unwatch)/(?P[1-9]\d*)/' => 'PhabricatorProjectWatchController', + 'silence/(?P[1-9]\d*)/' + => 'PhabricatorProjectSilenceController', ), '/tag/' => array( '(?P[^/]+)/' => 'PhabricatorProjectViewController', diff --git a/src/applications/project/controller/PhabricatorProjectMembersViewController.php b/src/applications/project/controller/PhabricatorProjectMembersViewController.php index 9189b1ad8d..efe2106a26 100644 --- a/src/applications/project/controller/PhabricatorProjectMembersViewController.php +++ b/src/applications/project/controller/PhabricatorProjectMembersViewController.php @@ -110,6 +110,49 @@ final class PhabricatorProjectMembersViewController $descriptions[PhabricatorPolicyCapability::CAN_JOIN]); } + $viewer_phid = $viewer->getPHID(); + + if ($project->isUserWatcher($viewer_phid)) { + $watch_item = id(new PHUIStatusItemView()) + ->setIcon('fa-eye green') + ->setTarget(phutil_tag('strong', array(), pht('Watching'))) + ->setNote( + pht( + 'You will receive mail about changes made to any related '. + 'object.')); + + $watch_status = id(new PHUIStatusListView()) + ->addItem($watch_item); + + $view->addProperty(pht('Watching'), $watch_status); + } + + if ($project->isUserMember($viewer_phid)) { + $is_silenced = $this->isProjectSilenced($project); + if ($is_silenced) { + $mail_icon = 'fa-envelope-o grey'; + $mail_target = pht('Disabled'); + $mail_note = pht( + 'When mail is sent to project members, you will not receive '. + 'a copy.'); + } else { + $mail_icon = 'fa-envelope-o green'; + $mail_target = pht('Enabled'); + $mail_note = pht( + 'You will receive mail that is sent to project members.'); + } + + $mail_item = id(new PHUIStatusItemView()) + ->setIcon($mail_icon) + ->setTarget(phutil_tag('strong', array(), $mail_target)) + ->setNote($mail_note); + + $mail_status = id(new PHUIStatusListView()) + ->addItem($mail_item); + + $view->addProperty(pht('Mail to Members'), $mail_status); + } + return $view; } @@ -136,7 +179,9 @@ final class PhabricatorProjectMembersViewController $can_leave = $supports_edit && (!$is_locked || $can_edit); - if (!$project->isUserMember($viewer->getPHID())) { + $viewer_phid = $viewer->getPHID(); + + if (!$project->isUserMember($viewer_phid)) { $view->addAction( id(new PhabricatorActionView()) ->setHref('/project/update/'.$project->getID().'/join/') @@ -170,6 +215,23 @@ final class PhabricatorProjectMembersViewController ->setName(pht('Unwatch Project'))); } + $can_silence = $project->isUserMember($viewer_phid); + $is_silenced = $this->isProjectSilenced($project); + + if ($is_silenced) { + $silence_text = pht('Enable Mail'); + } else { + $silence_text = pht('Disable Mail'); + } + + $view->addAction( + id(new PhabricatorActionView()) + ->setName($silence_text) + ->setIcon('fa-envelope-o') + ->setHref("/project/silence/{$id}/") + ->setWorkflow(true) + ->setDisabled(!$can_silence)); + $can_add = $can_edit && $supports_edit; $view->addAction( @@ -202,4 +264,20 @@ final class PhabricatorProjectMembersViewController return $view; } + private function isProjectSilenced(PhabricatorProject $project) { + $viewer = $this->getViewer(); + + $viewer_phid = $viewer->getPHID(); + if (!$viewer_phid) { + return false; + } + + $edge_type = PhabricatorProjectSilencedEdgeType::EDGECONST; + $silenced = PhabricatorEdgeQuery::loadDestinationPHIDs( + $project->getPHID(), + $edge_type); + $silenced = array_fuse($silenced); + return isset($silenced[$viewer_phid]); + } + } diff --git a/src/applications/project/controller/PhabricatorProjectSilenceController.php b/src/applications/project/controller/PhabricatorProjectSilenceController.php new file mode 100644 index 0000000000..6edd9bab39 --- /dev/null +++ b/src/applications/project/controller/PhabricatorProjectSilenceController.php @@ -0,0 +1,87 @@ +getViewer(); + $id = $request->getURIData('id'); + $action = $request->getURIData('action'); + + $project = id(new PhabricatorProjectQuery()) + ->setViewer($viewer) + ->withIDs(array($id)) + ->needMembers(true) + ->executeOne(); + if (!$project) { + return new Aphront404Response(); + } + + $edge_type = PhabricatorProjectSilencedEdgeType::EDGECONST; + $done_uri = "/project/members/{$id}/"; + $viewer_phid = $viewer->getPHID(); + + if (!$project->isUserMember($viewer_phid)) { + return $this->newDialog() + ->setTitle(pht('Not a Member')) + ->appendParagraph( + pht( + 'You are not a project member, so you do not receive mail sent '. + 'to members of this project.')) + ->addCancelButton($done_uri); + } + + $silenced = PhabricatorEdgeQuery::loadDestinationPHIDs( + $project->getPHID(), + $edge_type); + $silenced = array_fuse($silenced); + $is_silenced = isset($silenced[$viewer_phid]); + + if ($request->isDialogFormPost()) { + if ($is_silenced) { + $edge_action = '-'; + } else { + $edge_action = '+'; + } + + $xactions = array(); + $xactions[] = id(new PhabricatorProjectTransaction()) + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) + ->setMetadataValue('edge:type', $edge_type) + ->setNewValue( + array( + $edge_action => array($viewer_phid => $viewer_phid), + )); + + $editor = id(new PhabricatorProjectTransactionEditor($project)) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnNoEffect(true) + ->setContinueOnMissingFields(true) + ->applyTransactions($project, $xactions); + + return id(new AphrontRedirectResponse())->setURI($done_uri); + } + + if ($is_silenced) { + $title = pht('Enable Mail'); + $body = pht( + 'When mail is sent to members of this project, you will receive a '. + 'copy.'); + $button = pht('Enable Project Mail'); + } else { + $title = pht('Disable Mail'); + $body = pht( + 'When mail is sent to members of this project, you will no longer '. + 'receive a copy.'); + $button = pht('Disable Project Mail'); + } + + return $this->newDialog() + ->setTitle($title) + ->appendParagraph($body) + ->addCancelButton($done_uri) + ->addSubmitButton($button); + } + +} diff --git a/src/applications/project/controller/PhabricatorProjectWatchController.php b/src/applications/project/controller/PhabricatorProjectWatchController.php index d8b818cb63..263c508441 100644 --- a/src/applications/project/controller/PhabricatorProjectWatchController.php +++ b/src/applications/project/controller/PhabricatorProjectWatchController.php @@ -30,11 +30,9 @@ final class PhabricatorProjectWatchController switch ($action) { case 'watch': $edge_action = '+'; - $force_subscribe = true; break; case 'unwatch': $edge_action = '-'; - $force_subscribe = false; break; } diff --git a/src/applications/project/edge/PhabricatorProjectSilencedEdgeType.php b/src/applications/project/edge/PhabricatorProjectSilencedEdgeType.php new file mode 100644 index 0000000000..1fbc1a9ab7 --- /dev/null +++ b/src/applications/project/edge/PhabricatorProjectSilencedEdgeType.php @@ -0,0 +1,8 @@ +getTransactionType()) { - case PhabricatorTransactions::TYPE_EDGE: - $edge_type = $xaction->getMetadataValue('edge:type'); - switch ($edge_type) { - case PhabricatorProjectProjectHasMemberEdgeType::EDGECONST: - case PhabricatorObjectHasWatcherEdgeType::EDGECONST: - $edge_const = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; - if ($edge_type != $edge_const) { - break; - } - - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - // When adding members, we add subscriptions. When removing - // members, we remove subscriptions. - $add = array_keys(array_diff_key($new, $old)); - $rem = array_keys(array_diff_key($old, $new)); - - // NOTE: The subscribe is "explicit" because there's no implicit - // unsubscribe, so Join -> Leave -> Join doesn't resubscribe you - // if we use an implicit subscribe, even though you never willfully - // unsubscribed. Not sure if adding implicit unsubscribe (which - // would not write the unsubscribe row) is justified to deal with - // this, which is a fairly weird edge case and pretty arguable both - // ways. - - id(new PhabricatorSubscriptionsEditor()) - ->setActor($this->requireActor()) - ->setObject($object) - ->subscribeExplicit($add) - ->unsubscribe($rem) - ->save(); - break; - } - break; - } - - return parent::applyBuiltinExternalTransaction($object, $xaction); - } - protected function validateAllTransactions( PhabricatorLiskDAO $object, array $xactions) { @@ -584,6 +539,10 @@ final class PhabricatorProjectTransactionEditor ); } + protected function getMailCc(PhabricatorLiskDAO $object) { + return array(); + } + public function getMailTagsMap() { return array( PhabricatorProjectTransaction::MAILTAG_METADATA => @@ -592,8 +551,6 @@ final class PhabricatorProjectTransactionEditor pht('Project membership changes.'), PhabricatorProjectTransaction::MAILTAG_WATCHERS => pht('Project watcher list changes.'), - PhabricatorProjectTransaction::MAILTAG_SUBSCRIBERS => - pht('Project subscribers change.'), PhabricatorProjectTransaction::MAILTAG_OTHER => pht('Other project activity not listed above occurs.'), ); diff --git a/src/applications/project/engine/PhabricatorProjectEditEngine.php b/src/applications/project/engine/PhabricatorProjectEditEngine.php index 42a2000c86..c9861e96a6 100644 --- a/src/applications/project/engine/PhabricatorProjectEditEngine.php +++ b/src/applications/project/engine/PhabricatorProjectEditEngine.php @@ -148,7 +148,6 @@ final class PhabricatorProjectEditEngine 'icon', 'color', 'slugs', - 'subscriberPHIDs', )); return array( diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php index 2ea3a2c131..5f4d511158 100644 --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -6,7 +6,6 @@ final class PhabricatorProject extends PhabricatorProjectDAO PhabricatorFlaggableInterface, PhabricatorPolicyInterface, PhabricatorExtendedPolicyInterface, - PhabricatorSubscribableInterface, PhabricatorCustomFieldInterface, PhabricatorDestructibleInterface, PhabricatorFulltextInterface, @@ -179,7 +178,6 @@ final class PhabricatorProject extends PhabricatorProjectDAO return $extended; } - public function isUserMember($user_phid) { if ($this->memberPHIDs !== self::ATTACHABLE) { return in_array($user_phid, $this->memberPHIDs); @@ -536,19 +534,6 @@ final class PhabricatorProject extends PhabricatorProjectDAO } - -/* -( PhabricatorSubscribableInterface )----------------------------------- */ - - - public function isAutomaticallySubscribed($phid) { - return false; - } - - public function shouldShowSubscribersProperty() { - return false; - } - - /* -( PhabricatorCustomFieldInterface )------------------------------------ */ diff --git a/src/applications/project/storage/PhabricatorProjectTransaction.php b/src/applications/project/storage/PhabricatorProjectTransaction.php index b16a4e30ca..1186e9c4f7 100644 --- a/src/applications/project/storage/PhabricatorProjectTransaction.php +++ b/src/applications/project/storage/PhabricatorProjectTransaction.php @@ -18,7 +18,6 @@ final class PhabricatorProjectTransaction const MAILTAG_METADATA = 'project-metadata'; const MAILTAG_MEMBERS = 'project-members'; - const MAILTAG_SUBSCRIBERS = 'project-subscribers'; const MAILTAG_WATCHERS = 'project-watchers'; const MAILTAG_OTHER = 'project-other'; @@ -382,9 +381,6 @@ final class PhabricatorProjectTransaction case self::TYPE_COLOR: $tags[] = self::MAILTAG_METADATA; break; - case PhabricatorTransactions::TYPE_SUBSCRIBERS: - $tags[] = self::MAILTAG_SUBSCRIBERS; - break; case PhabricatorTransactions::TYPE_EDGE: $type = $this->getMetadata('edge:type'); $type = head($type); From 3f36e498b7b3127c46fcdb4507eac941e8c540a8 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 19 Jan 2016 19:32:12 -0800 Subject: [PATCH 43/66] Document the new watcher/member/edit notification mail rules Summary: Ref T10054. This is mostly for completness so I can reference it when closing all the related tasks. Test Plan: Read documentation. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15066 --- .../PhabricatorProjectApplication.php | 9 ++++ src/docs/user/userguide/projects.diviner | 53 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 src/docs/user/userguide/projects.diviner diff --git a/src/applications/project/application/PhabricatorProjectApplication.php b/src/applications/project/application/PhabricatorProjectApplication.php index 5f6f7add9f..60e4412273 100644 --- a/src/applications/project/application/PhabricatorProjectApplication.php +++ b/src/applications/project/application/PhabricatorProjectApplication.php @@ -135,4 +135,13 @@ final class PhabricatorProjectApplication extends PhabricatorApplication { ); } + public function getHelpDocumentationArticles(PhabricatorUser $viewer) { + return array( + array( + 'name' => pht('Projects User Guide'), + 'href' => PhabricatorEnv::getDoclink('Projects User Guide'), + ), + ); + } + } diff --git a/src/docs/user/userguide/projects.diviner b/src/docs/user/userguide/projects.diviner new file mode 100644 index 0000000000..77bc3523c7 --- /dev/null +++ b/src/docs/user/userguide/projects.diviner @@ -0,0 +1,53 @@ +@title Projects User Guide +@group userguide + +Organize users and objects with projects. + +Overview +======== + +NOTE: This document is only partially complete. + +Phabricator projects are flexible groups of users and objects. + + +Joining Projects +================ + +Once you join a project, you become a member and will receive mail sent to the +project, like a mailing list. For example, if a project is added as a +subscriber on a task or a reviewer on a revision, you will receive mail about +that task or revision. + +If you'd prefer not to receive mail sent to a project, you can go to +{nav Members} and select {nav Disable Mail}. If you disable mail for a project, +you will no longer receive mail sent to the project. + + +Watching Projects +================= + +Watching a project allows you to closely follow all activity related to a +project. + +You can **watch** a project by clicking {nav Watch Project} on the project +page. To stop watching a project, click {nav Unwatch Project}. + +When you watch a project, you will receive a copy of mail about any objects +(like tasks or revisions) that are tagged with the project, or that the project +is a subscriber, reviewer, or auditor for. For moderately active projects, this +may be a large volume of mail. + + +Edit Notifications +================== + +Edit notifications are generated when project details (like the project +description, name, or icon) are updated, or when users join or leave projects. + +By default, these notifications are are only sent to the acting user. These +notifications are usually not very interesting, and project mail is already +complicated by members and watchers. + +If you'd like to receive edit notifications for a project, you can write a +Herald rule to keep you in the loop. From 958333c46dd9c06c9a98cf7079b58717622c3643 Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Wed, 20 Jan 2016 13:41:01 +0100 Subject: [PATCH 44/66] Preserve newlines in remarkup previews Summary: Fixes T10177 Test Plan: Saw that the preview of the rendered task description showed newlines proper. Reviewers: epriestley, #blessed_reviewers Reviewed By: epriestley, #blessed_reviewers Subscribers: Korvin Maniphest Tasks: T10177 Differential Revision: https://secure.phabricator.com/D15068 --- src/infrastructure/markup/view/PHUIRemarkupView.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/infrastructure/markup/view/PHUIRemarkupView.php b/src/infrastructure/markup/view/PHUIRemarkupView.php index 0272c9c3a9..8a11653589 100644 --- a/src/infrastructure/markup/view/PHUIRemarkupView.php +++ b/src/infrastructure/markup/view/PHUIRemarkupView.php @@ -24,6 +24,7 @@ final class PHUIRemarkupView extends AphrontView { return PhabricatorMarkupEngine::renderOneObject( id(new PhabricatorMarkupOneOff()) + ->setPreserveLinebreaks(true) ->setContent($corpus), 'default', $viewer); From 92ee3e76425308910c04b1da368cc127b00c63d6 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Wed, 20 Jan 2016 12:18:01 -0800 Subject: [PATCH 45/66] Add basic grey and blue styles for PHUIBoxView Summary: We plan to use these more in future mocks. Adds base colors and re-uses in Phame. Test Plan: Phame, mobile and desktop. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D15069 --- resources/celerity/map.php | 10 +++++----- .../phame/view/PhameBlogListView.php | 7 ++++++- .../phame/view/PhameDraftListView.php | 6 +++++- src/view/phui/PHUIBoxView.php | 17 +++++++++++++++++ webroot/rsrc/css/application/phame/phame.css | 9 +++------ webroot/rsrc/css/phui/phui-box.css | 10 ++++++++++ 6 files changed, 46 insertions(+), 13 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 5fc600a356..2ec42af6d4 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => 'bd4f3259', + 'core.pkg.css' => '39dc2caa', 'core.pkg.js' => '573e6664', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -81,7 +81,7 @@ return array( 'rsrc/css/application/owners/owners-path-editor.css' => '2f00933b', 'rsrc/css/application/paste/paste.css' => 'a5157c48', 'rsrc/css/application/people/people-profile.css' => 'fa2069ec', - 'rsrc/css/application/phame/phame.css' => 'dac8fdf2', + 'rsrc/css/application/phame/phame.css' => '6d5b3682', 'rsrc/css/application/pholio/pholio-edit.css' => '3ad9d1ee', 'rsrc/css/application/pholio/pholio-inline-comments.css' => '8e545e49', 'rsrc/css/application/pholio/pholio.css' => '95174bdd', @@ -122,7 +122,7 @@ return array( 'rsrc/css/phui/phui-action-panel.css' => '91c7b835', 'rsrc/css/phui/phui-badge.css' => 'f25c3476', 'rsrc/css/phui/phui-big-info-view.css' => 'bd903741', - 'rsrc/css/phui/phui-box.css' => 'a5bb366d', + 'rsrc/css/phui/phui-box.css' => '10939564', 'rsrc/css/phui/phui-button.css' => '16020a60', 'rsrc/css/phui/phui-crumbs-view.css' => '414406b5', 'rsrc/css/phui/phui-document-pro.css' => '8799acf7', @@ -780,7 +780,7 @@ return array( 'phabricator-uiexample-reactor-sendclass' => '1def2711', 'phabricator-uiexample-reactor-sendproperties' => 'b1f0ccee', 'phabricator-zindex-css' => 'a36a45da', - 'phame-css' => 'dac8fdf2', + 'phame-css' => '6d5b3682', 'pholio-css' => '95174bdd', 'pholio-edit-css' => '3ad9d1ee', 'pholio-inline-comments-css' => '8e545e49', @@ -792,7 +792,7 @@ return array( 'phui-action-panel-css' => '91c7b835', 'phui-badge-view-css' => 'f25c3476', 'phui-big-info-view-css' => 'bd903741', - 'phui-box-css' => 'a5bb366d', + 'phui-box-css' => '10939564', 'phui-button-css' => '16020a60', 'phui-calendar-css' => 'ccabe893', 'phui-calendar-day-css' => 'd1cf6f93', diff --git a/src/applications/phame/view/PhameBlogListView.php b/src/applications/phame/view/PhameBlogListView.php index 6f42da77fe..ae936442b0 100644 --- a/src/applications/phame/view/PhameBlogListView.php +++ b/src/applications/phame/view/PhameBlogListView.php @@ -89,7 +89,12 @@ final class PhameBlogListView extends AphrontTagView { ), pht('Blogs'))); - return array($header, $list); + return id(new PHUIBoxView()) + ->appendChild($header) + ->appendChild($list) + ->addClass('pl') + ->setColor(PHUIBoxView::BLUE); + } } diff --git a/src/applications/phame/view/PhameDraftListView.php b/src/applications/phame/view/PhameDraftListView.php index 558bf19b52..68bb56cabf 100644 --- a/src/applications/phame/view/PhameDraftListView.php +++ b/src/applications/phame/view/PhameDraftListView.php @@ -92,7 +92,11 @@ final class PhameDraftListView extends AphrontTagView { ), pht('Drafts'))); - return array($header, $list); + return id(new PHUIBoxView()) + ->appendChild($header) + ->appendChild($list) + ->addClass('pl') + ->setColor(PHUIBoxView::BLUE); } } diff --git a/src/view/phui/PHUIBoxView.php b/src/view/phui/PHUIBoxView.php index bc805515f0..7068f8811c 100644 --- a/src/view/phui/PHUIBoxView.php +++ b/src/view/phui/PHUIBoxView.php @@ -5,6 +5,10 @@ final class PHUIBoxView extends AphrontTagView { private $margin = array(); private $padding = array(); private $border = false; + private $color; + + const BLUE = 'phui-box-blue'; + const GREY = 'phui-box-grey'; public function addMargin($margin) { $this->margin[] = $margin; @@ -21,19 +25,32 @@ final class PHUIBoxView extends AphrontTagView { return $this; } + public function setColor($color) { + $this->color = $color; + return $this; + } + protected function getTagAttributes() { require_celerity_resource('phui-box-css'); $outer_classes = array(); $outer_classes[] = 'phui-box'; + if ($this->border) { $outer_classes[] = 'phui-box-border'; } + foreach ($this->margin as $margin) { $outer_classes[] = $margin; } + foreach ($this->padding as $padding) { $outer_classes[] = $padding; } + + if ($this->color) { + $outer_classes[] = $this->color; + } + return array('class' => $outer_classes); } diff --git a/webroot/rsrc/css/application/phame/phame.css b/webroot/rsrc/css/application/phame/phame.css index 65604a6dd6..be161c1ede 100644 --- a/webroot/rsrc/css/application/phame/phame.css +++ b/webroot/rsrc/css/application/phame/phame.css @@ -49,17 +49,14 @@ .phame-blog-list { margin: 24px 16px 16px 16px; - padding: 16px; - background-color: {$bluebackground}; - border-radius: 3px; } .device .phame-blog-list { - padding: 16px 8px; - background-color: #F1F1F4; + padding: 0; + background-color: {$bluebackground}; margin: 0; border-radius: 0; - border-bottom: 1px solid {$lightblueborder}; + border-bottom: 1px solid {$thinblueborder}; } .phame-blog-list-item:last-child { diff --git a/webroot/rsrc/css/phui/phui-box.css b/webroot/rsrc/css/phui/phui-box.css index da9b85e765..e31c4bcae4 100644 --- a/webroot/rsrc/css/phui/phui-box.css +++ b/webroot/rsrc/css/phui/phui-box.css @@ -11,3 +11,13 @@ .phui-box.focus { box-shadow: 0 0 5px 5px rgba(255, 255, 0, 0.90); } + +.phui-box-grey { + background-color: rgba(71,87,120,0.1); + border-radius: 3px; +} + +.phui-box-blue { + background-color: {$bluebackground}; + border-radius: 3px; +} From e0fef74be7829ff79f6a7448d42c891408814ef2 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Wed, 20 Jan 2016 13:30:34 -0800 Subject: [PATCH 46/66] Minor CSS tweaks to autocomplete Summary: Tweaky Test Plan: Lots of testing projects and people {F1065397} Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D15070 --- resources/celerity/map.php | 6 +++--- webroot/rsrc/css/core/remarkup.css | 24 +++++++++++++++--------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 2ec42af6d4..a8f0d881ce 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => '39dc2caa', + 'core.pkg.css' => '005bc22f', 'core.pkg.js' => '573e6664', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -102,7 +102,7 @@ return array( 'rsrc/css/application/tokens/tokens.css' => '3d0f239e', 'rsrc/css/application/uiexample/example.css' => '528b19de', 'rsrc/css/core/core.css' => 'a76cefc9', - 'rsrc/css/core/remarkup.css' => 'b748dc17', + 'rsrc/css/core/remarkup.css' => '64277c02', 'rsrc/css/core/syntax.css' => '9fd11da8', 'rsrc/css/core/z-index.css' => 'a36a45da', 'rsrc/css/diviner/diviner-shared.css' => 'aa3656aa', @@ -758,7 +758,7 @@ return array( 'phabricator-object-selector-css' => '85ee8ce6', 'phabricator-phtize' => 'd254d646', 'phabricator-prefab' => 'e67df814', - 'phabricator-remarkup-css' => 'b748dc17', + 'phabricator-remarkup-css' => '64277c02', 'phabricator-search-results-css' => '7dea472c', 'phabricator-shaped-request' => '7cbe244b', 'phabricator-side-menu-view-css' => '3a3d9f41', diff --git a/webroot/rsrc/css/core/remarkup.css b/webroot/rsrc/css/core/remarkup.css index da04fe2b68..bec9c3e29e 100644 --- a/webroot/rsrc/css/core/remarkup.css +++ b/webroot/rsrc/css/core/remarkup.css @@ -565,23 +565,25 @@ var.remarkup-assist-textarea { .phuix-autocomplete { position: absolute; width: 300px; - box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.300); + box-shadow: {$dropshadow}; background: #ffffff; - border: 1px solid {$blueborder}; + border: 1px solid {$lightgreyborder}; + border-radius: 3px; } .phuix-autocomplete-head { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - padding: 4px 8px; + padding: 6px 8px; background: {$lightgreybackground}; - color: {$greytext}; + color: {$darkgreytext}; + border-radius: 3px; } .phuix-autocomplete-head .phui-icon-view { margin-right: 4px; - color: {$greytext}; + color: {$lightgreytext}; } .phuix-autocomplete-echo { @@ -591,22 +593,26 @@ var.remarkup-assist-textarea { .phuix-autocomplete-list a.jx-result { display: block; - padding: 4px 8px; + padding: 5px 8px; font-size: {$normalfontsize}; - border-top: 1px solid {$hoverborder}; + border-top: 1px solid {$thinblueborder}; + font-weight: bold; color: {$darkgreytext}; } .phuix-autocomplete-list a.jx-result .phui-icon-view { margin-right: 4px; + color: {$lightbluetext}; } .phuix-autocomplete-list a.jx-result:hover { text-decoration: none; - background: {$hoverblue}; + background: {$sh-bluebackground}; + color: #000; } .phuix-autocomplete-list a.jx-result.focused, .phuix-autocomplete-list a.jx-result.focused:hover { - background: {$hoverblue}; + background: {$sh-bluebackground}; + color: #000; } From b51a859636ac19bbcc160391b35e946ceaac4cba Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 21 Jan 2016 04:25:38 -0800 Subject: [PATCH 47/66] Allow diffusion.filecontentquery to load data for arbitrarily large files Summary: Fixes T10186. After D14970, `diffusion.filecontentquery` puts the content in a file and returns the file PHID. However, it does this in a way that doesn't go through the chunking engine, so it will fail for files larger than the chunk threshold (generally, 8MB). Instead, stream the file from the underlying command directly into chunked storage. Test Plan: - Made a commit including a really big file: https://github.com/epriestley/poems/commit/4dcd4c492b31d82f0fec6f447cf3719b9cc079e0 - Used `diffusion.filecontentquery` to load file content. - Parsed/imported commit locally. - Used `diffusion.filecontentquery` to load content for smaller files (README, etc). Reviewers: chad Reviewed By: chad Maniphest Tasks: T10186 Differential Revision: https://secure.phabricator.com/D15072 --- src/__phutil_library_map__.php | 4 + ...fusionFileContentQueryConduitAPIMethod.php | 32 +-- .../filecontent/DiffusionFileContentQuery.php | 33 ++- ...atorFilesApplicationStorageEnginePanel.php | 20 +- .../PhabricatorExecFutureFileUploadSource.php | 28 +++ .../PhabricatorFileUploadSource.php | 235 ++++++++++++++++++ 6 files changed, 309 insertions(+), 43 deletions(-) create mode 100644 src/applications/files/uploadsource/PhabricatorExecFutureFileUploadSource.php create mode 100644 src/applications/files/uploadsource/PhabricatorFileUploadSource.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index d606f6c298..2b995de20d 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2223,6 +2223,7 @@ phutil_register_library_map(array( 'PhabricatorEventListener' => 'infrastructure/events/PhabricatorEventListener.php', 'PhabricatorEventType' => 'infrastructure/events/constant/PhabricatorEventType.php', 'PhabricatorExampleEventListener' => 'infrastructure/events/PhabricatorExampleEventListener.php', + 'PhabricatorExecFutureFileUploadSource' => 'applications/files/uploadsource/PhabricatorExecFutureFileUploadSource.php', 'PhabricatorExtendedPolicyInterface' => 'applications/policy/interface/PhabricatorExtendedPolicyInterface.php', 'PhabricatorExtendingPhabricatorConfigOptions' => 'applications/config/option/PhabricatorExtendingPhabricatorConfigOptions.php', 'PhabricatorExtensionsSetupCheck' => 'applications/config/check/PhabricatorExtensionsSetupCheck.php', @@ -2312,6 +2313,7 @@ phutil_register_library_map(array( 'PhabricatorFileUploadController' => 'applications/files/controller/PhabricatorFileUploadController.php', 'PhabricatorFileUploadDialogController' => 'applications/files/controller/PhabricatorFileUploadDialogController.php', 'PhabricatorFileUploadException' => 'applications/files/exception/PhabricatorFileUploadException.php', + 'PhabricatorFileUploadSource' => 'applications/files/uploadsource/PhabricatorFileUploadSource.php', 'PhabricatorFileinfoSetupCheck' => 'applications/config/check/PhabricatorFileinfoSetupCheck.php', 'PhabricatorFilesApplication' => 'applications/files/application/PhabricatorFilesApplication.php', 'PhabricatorFilesApplicationStorageEnginePanel' => 'applications/files/applicationpanel/PhabricatorFilesApplicationStorageEnginePanel.php', @@ -6504,6 +6506,7 @@ phutil_register_library_map(array( 'PhabricatorEventListener' => 'PhutilEventListener', 'PhabricatorEventType' => 'PhutilEventType', 'PhabricatorExampleEventListener' => 'PhabricatorEventListener', + 'PhabricatorExecFutureFileUploadSource' => 'PhabricatorFileUploadSource', 'PhabricatorExtendingPhabricatorConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorExtensionsSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorExternalAccount' => array( @@ -6621,6 +6624,7 @@ phutil_register_library_map(array( 'PhabricatorFileUploadController' => 'PhabricatorFileController', 'PhabricatorFileUploadDialogController' => 'PhabricatorFileController', 'PhabricatorFileUploadException' => 'Exception', + 'PhabricatorFileUploadSource' => 'Phobject', 'PhabricatorFileinfoSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorFilesApplication' => 'PhabricatorApplication', 'PhabricatorFilesApplicationStorageEnginePanel' => 'PhabricatorApplicationConfigurationPanel', diff --git a/src/applications/diffusion/conduit/DiffusionFileContentQueryConduitAPIMethod.php b/src/applications/diffusion/conduit/DiffusionFileContentQueryConduitAPIMethod.php index 8088aa66b8..10e4d00b83 100644 --- a/src/applications/diffusion/conduit/DiffusionFileContentQueryConduitAPIMethod.php +++ b/src/applications/diffusion/conduit/DiffusionFileContentQueryConduitAPIMethod.php @@ -39,14 +39,20 @@ final class DiffusionFileContentQueryConduitAPIMethod $file_query->setByteLimit($byte_limit); } - $content = $file_query->execute(); + $file = $file_query->execute(); $too_slow = (bool)$file_query->getExceededTimeLimit(); $too_huge = (bool)$file_query->getExceededByteLimit(); $file_phid = null; if (!$too_slow && !$too_huge) { - $file = $this->newFile($drequest, $content); + $repository = $drequest->getRepository(); + $repository_phid = $repository->getPHID(); + + $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); + $file->attachToObject($repository_phid); + unset($unguarded); + $file_phid = $file->getPHID(); } @@ -57,26 +63,4 @@ final class DiffusionFileContentQueryConduitAPIMethod ); } - private function newFile(DiffusionRequest $drequest, $content) { - $path = $drequest->getPath(); - $name = basename($path); - - $repository = $drequest->getRepository(); - $repository_phid = $repository->getPHID(); - - $file = PhabricatorFile::buildFromFileDataOrHash( - $content, - array( - 'name' => $name, - 'ttl' => time() + phutil_units('48 hours in seconds'), - 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE, - )); - - $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); - $file->attachToObject($repository_phid); - unset($unguarded); - - return $file; - } - } diff --git a/src/applications/diffusion/query/filecontent/DiffusionFileContentQuery.php b/src/applications/diffusion/query/filecontent/DiffusionFileContentQuery.php index 3ea0e12ba1..df14b49235 100644 --- a/src/applications/diffusion/query/filecontent/DiffusionFileContentQuery.php +++ b/src/applications/diffusion/query/filecontent/DiffusionFileContentQuery.php @@ -54,23 +54,46 @@ abstract class DiffusionFileContentQuery extends DiffusionQuery { $future->setStdoutSizeLimit($byte_limit + 1); } + $drequest = $this->getRequest(); + + $name = basename($drequest->getPath()); + $ttl = PhabricatorTime::getNow() + phutil_units('48 hours in seconds'); + try { - $file_content = $this->resolveFileContentFuture($future); + $threshold = PhabricatorFileStorageEngine::getChunkThreshold(); + $future->setReadBufferSize($threshold); + + $source = id(new PhabricatorExecFutureFileUploadSource()) + ->setName($name) + ->setTTL($ttl) + ->setViewPolicy(PhabricatorPolicies::POLICY_NOONE) + ->setExecFuture($future); + + $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); + $file = $source->uploadFile(); + unset($unguarded); + } catch (CommandException $ex) { if (!$future->getWasKilledByTimeout()) { throw $ex; } $this->didHitTimeLimit = true; - $file_content = null; + $file = null; } - if ($byte_limit && (strlen($file_content) > $byte_limit)) { + if ($byte_limit && ($file->getByteSize() > $byte_limit)) { $this->didHitByteLimit = true; - $file_content = null; + + $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); + id(new PhabricatorDestructionEngine()) + ->destroyObject($file); + unset($unguarded); + + $file = null; } - return $file_content; + return $file; } } diff --git a/src/applications/files/applicationpanel/PhabricatorFilesApplicationStorageEnginePanel.php b/src/applications/files/applicationpanel/PhabricatorFilesApplicationStorageEnginePanel.php index c9a9bad51e..0d3fdc46cc 100644 --- a/src/applications/files/applicationpanel/PhabricatorFilesApplicationStorageEnginePanel.php +++ b/src/applications/files/applicationpanel/PhabricatorFilesApplicationStorageEnginePanel.php @@ -26,11 +26,15 @@ final class PhabricatorFilesApplicationStorageEnginePanel $rows = array(); $rowc = array(); foreach ($engines as $key => $engine) { - $limited = $no; + if ($engine->isTestEngine()) { + continue; + } + $limit = null; if ($engine->hasFilesizeLimit()) { - $limited = $yes; $limit = phutil_format_bytes($engine->getFilesizeLimit()); + } else { + $limit = pht('Unlimited'); } if ($engine->canWriteFiles()) { @@ -39,12 +43,6 @@ final class PhabricatorFilesApplicationStorageEnginePanel $writable = $no; } - if ($engine->isTestEngine()) { - $test = $yes; - } else { - $test = $no; - } - if (isset($writable_engines[$key]) || isset($chunk_engines[$key])) { $rowc[] = 'highlighted'; } else { @@ -54,9 +52,7 @@ final class PhabricatorFilesApplicationStorageEnginePanel $rows[] = array( $key, get_class($engine), - $test, $writable, - $limited, $limit, ); } @@ -67,9 +63,7 @@ final class PhabricatorFilesApplicationStorageEnginePanel array( pht('Key'), pht('Class'), - pht('Unit Test'), pht('Writable'), - pht('Has Limit'), pht('Limit'), )) ->setRowClasses($rowc) @@ -78,8 +72,6 @@ final class PhabricatorFilesApplicationStorageEnginePanel '', 'wide', '', - '', - '', 'n', )); diff --git a/src/applications/files/uploadsource/PhabricatorExecFutureFileUploadSource.php b/src/applications/files/uploadsource/PhabricatorExecFutureFileUploadSource.php new file mode 100644 index 0000000000..2e876c3e7a --- /dev/null +++ b/src/applications/files/uploadsource/PhabricatorExecFutureFileUploadSource.php @@ -0,0 +1,28 @@ +future = $future; + return $this; + } + + public function getExecFuture() { + return $this->future; + } + + protected function newDataIterator() { + $future = $this->getExecFuture(); + + return id(new LinesOfALargeExecFuture($future)) + ->setDelimiter(null); + } + + protected function getDataLength() { + return null; + } + +} diff --git a/src/applications/files/uploadsource/PhabricatorFileUploadSource.php b/src/applications/files/uploadsource/PhabricatorFileUploadSource.php new file mode 100644 index 0000000000..74b8e32389 --- /dev/null +++ b/src/applications/files/uploadsource/PhabricatorFileUploadSource.php @@ -0,0 +1,235 @@ +name = $name; + return $this; + } + + public function getName() { + return $this->name; + } + + public function setTTL($ttl) { + $this->ttl = $ttl; + return $this; + } + + public function getTTL() { + return $this->ttl; + } + + public function setViewPolicy($view_policy) { + $this->viewPolicy = $view_policy; + return $this; + } + + public function getViewPolicy() { + return $this->viewPolicy; + } + + public function uploadFile() { + if (!$this->shouldChunkFile()) { + return $this->writeSingleFile(); + } else { + return $this->writeChunkedFile(); + } + } + + private function getDataIterator() { + if (!$this->data) { + $this->data = $this->newDataIterator(); + } + return $this->data; + } + + private function getRope() { + if (!$this->rope) { + $this->rope = new PhutilRope(); + } + return $this->rope; + } + + abstract protected function newDataIterator(); + abstract protected function getDataLength(); + + private function readFileData() { + $data = $this->getDataIterator(); + + if (!$this->didRewind) { + $data->rewind(); + $this->didRewind = true; + } else { + $data->next(); + } + + if (!$data->valid()) { + return false; + } + + $rope = $this->getRope(); + $rope->append($data->current()); + + return true; + } + + private function shouldChunkFile() { + if ($this->shouldChunk !== null) { + return $this->shouldChunk; + } + + $threshold = PhabricatorFileStorageEngine::getChunkThreshold(); + + // If we don't know how large the file is, we're going to read some data + // from it until we know whether it's a small file or not. This will give + // us enough information to make a decision about chunking. + $length = $this->getDataLength(); + if ($length === null) { + $rope = $this->getRope(); + while ($this->readFileData()) { + $length = $rope->getByteLength(); + if ($length > $threshold) { + break; + } + } + } + + $this->shouldChunk = ($length > $threshold); + + return $this->shouldChunk; + } + + private function writeSingleFile() { + while ($this->readFileData()) { + // Read the entire file. + } + + $rope = $this->getRope(); + $data = $rope->getAsString(); + + $parameters = $this->getNewFileParameters(); + + return PhabricatorFile::newFromFileData($data, $parameters); + } + + private function writeChunkedFile() { + $engine = $this->getChunkEngine(); + + $parameters = $this->getNewFileParameters(); + + $parameters = array( + 'isPartial' => true, + ) + $parameters; + + $data_length = $this->getDataLength(); + if ($data_length !== null) { + $length = $data_length; + } else { + $length = 0; + } + + $file = PhabricatorFile::newChunkedFile($engine, $length, $parameters); + $file->save(); + + $rope = $this->getRope(); + + // Read the source, writing chunks as we get enough data. + while ($this->readFileData()) { + while (true) { + $rope_length = $rope->getByteLength(); + if ($rope_length < $engine->getChunkSize()) { + break; + } + $this->writeChunk($file, $engine); + } + } + + // If we have extra bytes at the end, write them. + if ($rope->getByteLength()) { + $this->writeChunk($file, $engine); + } + + $file->setIsPartial(0); + if ($data_length === null) { + $file->setByteSize($this->getTotalBytesWritten()); + } + $file->save(); + + return $file; + } + + private function writeChunk( + PhabricatorFile $file, + PhabricatorFileStorageEngine $engine) { + + $offset = $this->getTotalBytesWritten(); + $max_length = $engine->getChunkSize(); + $rope = $this->getRope(); + + $data = $rope->getPrefixBytes($max_length); + $actual_length = strlen($data); + $rope->removeBytesFromHead($actual_length); + + $chunk_data = PhabricatorFile::newFromFileData( + $data, + array( + 'name' => $file->getMonogram().'.chunk-'.$offset, + 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE, + )); + + $chunk = PhabricatorFileChunk::initializeNewChunk( + $file->getStorageHandle(), + $offset, + $offset + $actual_length); + + $chunk + ->setDataFilePHID($chunk_data->getPHID()) + ->save(); + + $this->setTotalBytesWritten($offset + $actual_length); + + return $chunk; + } + + private function getNewFileParameters() { + return array( + 'name' => $this->getName(), + 'ttl' => $this->getTTL(), + 'viewPolicy' => $this->getViewPolicy(), + ); + } + + private function getChunkEngine() { + $chunk_engines = PhabricatorFileStorageEngine::loadWritableChunkEngines(); + if (!$chunk_engines) { + throw new Exception( + pht( + 'Unable to upload file: this server is not configured with any '. + 'storage engine which can store large files.')); + } + + return head($chunk_engines); + } + + private function setTotalBytesWritten($total_bytes_written) { + $this->totalBytesWritten = $total_bytes_written; + return $this; + } + + private function getTotalBytesWritten() { + return $this->totalBytesWritten; + } + +} From 88e2929411be1e5d7b86a9b3605009c1febf67de Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 21 Jan 2016 10:02:01 -0800 Subject: [PATCH 48/66] Fix "choose icon" on profile menu items Summary: Ref T10054. This fix is a little rough but the "right" fix involves a ton of rewriting to `AphrontSideNavFilterView` and I don't want to open that can of worms up yet. Specifically, the problem is: - we build the menu in order to populate the mobile/application menu; - as a side effect of building the menu (not rendering the menu), we initialize the menu collapse/expand behavior; - but we never actually render the menu, so the `JX.$()` call fails. The right fix would be to initialize the behavior only when we render the menu, but then `AphorntSideNavFilterView` would need to know about profile menu behaviors. It probably should some day, but I think today is not that day. Test Plan: Set icons on a link on a profile menu. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15073 --- resources/celerity/map.php | 6 +++--- webroot/rsrc/js/phui/behavior-phui-profile-menu.js | 13 ++++++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index a8f0d881ce..23726438a7 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -500,7 +500,7 @@ return array( 'rsrc/js/core/phtize.js' => 'd254d646', 'rsrc/js/phui/behavior-phui-dropdown-menu.js' => '54733475', 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', - 'rsrc/js/phui/behavior-phui-profile-menu.js' => 'bf2c93d6', + 'rsrc/js/phui/behavior-phui-profile-menu.js' => 'bfc2e675', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', 'rsrc/js/phuix/PHUIXAutocomplete.js' => '21dc9144', @@ -649,7 +649,7 @@ return array( 'javelin-behavior-pholio-mock-view' => 'fbe497e7', 'javelin-behavior-phui-dropdown-menu' => '54733475', 'javelin-behavior-phui-object-box-tabs' => '2bfa2836', - 'javelin-behavior-phui-profile-menu' => 'bf2c93d6', + 'javelin-behavior-phui-profile-menu' => 'bfc2e675', 'javelin-behavior-policy-control' => 'ae45872f', 'javelin-behavior-policy-rule-editor' => '5e9f347c', 'javelin-behavior-project-boards' => 'ba4fa35c', @@ -1774,7 +1774,7 @@ return array( 'javelin-util', 'javelin-request', ), - 'bf2c93d6' => array( + 'bfc2e675' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', diff --git a/webroot/rsrc/js/phui/behavior-phui-profile-menu.js b/webroot/rsrc/js/phui/behavior-phui-profile-menu.js index bd305b5cf2..28d01ec122 100644 --- a/webroot/rsrc/js/phui/behavior-phui-profile-menu.js +++ b/webroot/rsrc/js/phui/behavior-phui-profile-menu.js @@ -6,7 +6,18 @@ */ JX.behavior('phui-profile-menu', function(config) { - var menu_node = JX.$(config.menuID); + // NOTE: This behavior is not initialized in the rendering pipeline for the + // menu, so it can get initialized when we build but do not render a menu + // (for example, when a page like the panel edit page only has items in + // the mobile/application menu, and does not show the profile menu). For now, + // just bail if we can't find the menu. + + try { + var menu_node = JX.$(config.menuID); + } catch (ex) { + return; + } + var collapse_node = JX.$(config.collapseID); var is_collapsed = config.isCollapsed; From 7d1809f9352f3b8446e2179a084cc928ba5e6157 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 21 Jan 2016 10:05:48 -0800 Subject: [PATCH 49/66] Remove unused `appIcon` from PHUIListItemView Summary: This is unused and there's no way to even set it. Pretty sure it died a while ago when we switched app icons to FontAwesome. Test Plan: Grepped for `appIcon`, found no related hits. Browsed some pages. Reviewers: chad Reviewed By: chad Differential Revision: https://secure.phabricator.com/D15074 --- src/view/phui/PHUIListItemView.php | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/view/phui/PHUIListItemView.php b/src/view/phui/PHUIListItemView.php index 1173319f4e..abe1c11409 100644 --- a/src/view/phui/PHUIListItemView.php +++ b/src/view/phui/PHUIListItemView.php @@ -19,7 +19,6 @@ final class PHUIListItemView extends AphrontTagView { private $isExternal; private $key; private $icon; - private $appIcon; private $selected; private $disabled; private $renderNameAsTooltip; @@ -179,7 +178,7 @@ final class PHUIListItemView extends AphrontTagView { $classes[] = 'phui-list-item-view'; $classes[] = 'phui-list-item-'.$this->type; - if ($this->icon || $this->appIcon) { + if ($this->icon) { $classes[] = 'phui-list-item-has-icon'; } @@ -279,12 +278,6 @@ final class PHUIListItemView extends AphrontTagView { ->setImage($this->profileImage); } - if ($this->appIcon) { - $icon = id(new PHUIIconView()) - ->addClass('phui-list-item-icon') - ->setIconFont($this->appIcon); - } - $classes = array(); if ($this->href) { $classes[] = 'phui-list-item-href'; From 6ebe8db3809f3e5f1b2073e400f0ef362589dbbc Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 21 Jan 2016 10:18:00 -0800 Subject: [PATCH 50/66] Add a missing key to HarbormasterBuildArtifact Summary: Fixes T10192. This key improves some common queries and is not currently present. Test Plan: See discussion in T10192. Verified current query plan of real queries is garbage and improved by adding this key. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10192 Differential Revision: https://secure.phabricator.com/D15075 --- .../harbormaster/storage/build/HarbormasterBuildArtifact.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuildArtifact.php b/src/applications/harbormaster/storage/build/HarbormasterBuildArtifact.php index 0b195db88f..bb5f8382ba 100644 --- a/src/applications/harbormaster/storage/build/HarbormasterBuildArtifact.php +++ b/src/applications/harbormaster/storage/build/HarbormasterBuildArtifact.php @@ -38,6 +38,9 @@ final class HarbormasterBuildArtifact extends HarbormasterDAO 'key_garbagecollect' => array( 'columns' => array('artifactType', 'dateCreated'), ), + 'key_target' => array( + 'columns' => array('buildTargetPHID', 'artifactType'), + ), ), ) + parent::getConfiguration(); } From 358240b804007228aa4588f4f14172633175c0fc Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 21 Jan 2016 10:35:09 -0800 Subject: [PATCH 51/66] Fix an issue with paginating queries which reverse vector ordering components Summary: Ref T10188. If you issue certain queries which use reverse ordering (like "All tasks, oldest update to newest update") and then try to page forward, we build the paging clause without reversing the column order correctly. For example, the ordering of "oldest update to newest update" is "dateModified ASC, id ASC", so the second page should include an "id > X" query. Currently, this builds as "id < X" incorrectly instead. The cause of this is just a failure to re-reverse a reversing flag when constructing the paging clause. Test Plan: - Queried tasks by update, oldest to newest, with no grouping, etc. - Paged to second page. - After change, got a valid second page with a good query in the Services tab. - Made some other normal queries. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10188 Differential Revision: https://secure.phabricator.com/D15076 --- .../query/policy/PhabricatorCursorPagedPolicyAwareQuery.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php index 1892e53e7c..0efca33b6a 100644 --- a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php +++ b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php @@ -381,6 +381,12 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery $column = $orderable[$key]; $column['value'] = $value_map[$key]; + // If the vector component is reversed, we need to reverse whatever the + // order of the column is. + if ($order->getIsReversed()) { + $column['reverse'] = !idx($column, 'reverse', false); + } + $columns[] = $column; } From 7bf4ef451b3feaa2e63c30360f593f9428639cab Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 21 Jan 2016 11:08:51 -0800 Subject: [PATCH 52/66] Make herald tokenizers copy values more correctly Summary: Fixes T10190. This is still a touch weird (newly typed tokens lose icons when copied) but basically works correctly. Saving/editing rules is fine, just some minor display glitching. Fixing the icon thing is a little more involved. Test Plan: Swapped Herald tokenizer fields around saw values (approximately) preserved. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10190 Differential Revision: https://secure.phabricator.com/D15077 --- resources/celerity/map.php | 22 +++++++++---------- .../js/application/herald/HeraldRuleEditor.js | 12 +++++++++- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 23726438a7..183f0fa7f3 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -395,7 +395,7 @@ return array( 'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef', 'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab', 'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888', - 'rsrc/js/application/herald/HeraldRuleEditor.js' => '5bd8f385', + 'rsrc/js/application/herald/HeraldRuleEditor.js' => '746ca158', 'rsrc/js/application/herald/PathTypeahead.js' => 'f7fc67ec', 'rsrc/js/application/herald/herald-rule-editor.js' => '7ebaeed3', 'rsrc/js/application/maniphest/behavior-batch-editor.js' => '782ab6e7', @@ -552,7 +552,7 @@ return array( 'global-drag-and-drop-css' => '697324ad', 'harbormaster-css' => 'b0758ca5', 'herald-css' => '826075fa', - 'herald-rule-editor' => '5bd8f385', + 'herald-rule-editor' => '746ca158', 'herald-test-css' => 'a52e323e', 'inline-comment-summary-css' => '51efda3a', 'javelin-aphlict' => '5359e785', @@ -1245,15 +1245,6 @@ return array( 'javelin-uri', 'javelin-routable', ), - '5bd8f385' => array( - 'multirow-row-manager', - 'javelin-install', - 'javelin-util', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-json', - 'phabricator-prefab', - ), '5c54cbf3' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1370,6 +1361,15 @@ return array( 'javelin-vector', 'javelin-dom', ), + '746ca158' => array( + 'multirow-row-manager', + 'javelin-install', + 'javelin-util', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-json', + 'phabricator-prefab', + ), '76b9fc3e' => array( 'javelin-behavior', 'javelin-stratcom', diff --git a/webroot/rsrc/js/application/herald/HeraldRuleEditor.js b/webroot/rsrc/js/application/herald/HeraldRuleEditor.js index 6514567e19..ba01c9bef3 100644 --- a/webroot/rsrc/js/application/herald/HeraldRuleEditor.js +++ b/webroot/rsrc/js/application/herald/HeraldRuleEditor.js @@ -293,7 +293,17 @@ JX.install('HeraldRuleEditor', { }, function(map) { for (var k in map) { - var v = JX.Prefab.transformDatasourceResults(map[k]); + var v = map[k]; + + // The control value may be set from wire values from the server, + // or a transformed value from another control, or a bare string + // value from another control. + if (typeof v == 'string') { + v = v; + } else if (!v.hasOwnProperty('id')) { + v = JX.Prefab.transformDatasourceResults(v); + } + build.tokenizer.addToken(k, v); } }]; From d37153f003048cb6608d9c97812e5564d5e7339a Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 21 Jan 2016 12:59:19 -0800 Subject: [PATCH 53/66] Make `bin/storage upgrade` and `bin/storage adjust` emit detailed messages if the user has no access to databases Summary: Ref T10195. Distinguish between "database does not exist" and "database exists, you just don't have permission to access it". We can't easily get this information out of INFORMATION_SCHEMA but can just `SHOW TABLES IN ...` every database that looks like it's missing and then look at the error code. Test Plan: - Created a user `limited` with limited access. - Ran `bin/storage adjust`. - Got hopefully more helpful messages about access problems, instead of "Missing" errors. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10195 Differential Revision: https://secure.phabricator.com/D15079 --- .../PhabricatorConfigDatabaseSchema.php | 24 ++++++++++--- .../schema/PhabricatorConfigSchemaQuery.php | 27 ++++++++++++++ .../schema/PhabricatorConfigStorageSchema.php | 4 +++ .../PhabricatorStorageManagementAPI.php | 10 ++++++ .../PhabricatorStorageManagementWorkflow.php | 35 ++++++++++++++++++- 5 files changed, 94 insertions(+), 6 deletions(-) diff --git a/src/applications/config/schema/PhabricatorConfigDatabaseSchema.php b/src/applications/config/schema/PhabricatorConfigDatabaseSchema.php index bf0af3f480..216a778e56 100644 --- a/src/applications/config/schema/PhabricatorConfigDatabaseSchema.php +++ b/src/applications/config/schema/PhabricatorConfigDatabaseSchema.php @@ -6,6 +6,7 @@ final class PhabricatorConfigDatabaseSchema private $characterSet; private $collation; private $tables = array(); + private $accessDenied; public function addTable(PhabricatorConfigTableSchema $table) { $key = $table->getName(); @@ -33,12 +34,16 @@ final class PhabricatorConfigDatabaseSchema PhabricatorConfigStorageSchema $expect) { $issues = array(); - if ($this->getCharacterSet() != $expect->getCharacterSet()) { - $issues[] = self::ISSUE_CHARSET; - } + if ($this->getAccessDenied()) { + $issues[] = self::ISSUE_ACCESSDENIED; + } else { + if ($this->getCharacterSet() != $expect->getCharacterSet()) { + $issues[] = self::ISSUE_CHARSET; + } - if ($this->getCollation() != $expect->getCollation()) { - $issues[] = self::ISSUE_COLLATION; + if ($this->getCollation() != $expect->getCollation()) { + $issues[] = self::ISSUE_COLLATION; + } } return $issues; @@ -68,4 +73,13 @@ final class PhabricatorConfigDatabaseSchema return $this->characterSet; } + public function setAccessDenied($access_denied) { + $this->accessDenied = $access_denied; + return $this; + } + + public function getAccessDenied() { + return $this->accessDenied; + } + } diff --git a/src/applications/config/schema/PhabricatorConfigSchemaQuery.php b/src/applications/config/schema/PhabricatorConfigSchemaQuery.php index c1e94619ce..ca9b44cc07 100644 --- a/src/applications/config/schema/PhabricatorConfigSchemaQuery.php +++ b/src/applications/config/schema/PhabricatorConfigSchemaQuery.php @@ -47,6 +47,25 @@ final class PhabricatorConfigSchemaQuery extends Phobject { $databases); $database_info = ipull($database_info, null, 'SCHEMA_NAME'); + // Find databases which exist, but which the user does not have permission + // to see. + $invisible_databases = array(); + foreach ($databases as $database_name) { + if (isset($database_info[$database_name])) { + continue; + } + + try { + queryfx($conn, 'SHOW TABLES IN %T', $database_name); + } catch (AphrontAccessDeniedQueryException $ex) { + // This database exists, the user just doesn't have permission to + // see it. + $invisible_databases[] = $database_name; + } catch (AphrontSchemaQueryException $ex) { + // This database is legitimately missing. + } + } + $sql = array(); foreach ($tables as $table) { $sql[] = qsprintf( @@ -148,6 +167,13 @@ final class PhabricatorConfigSchemaQuery extends Phobject { $server_schema->addDatabase($database_schema); } + foreach ($invisible_databases as $database_name) { + $server_schema->addDatabase( + id(new PhabricatorConfigDatabaseSchema()) + ->setName($database_name) + ->setAccessDenied(true)); + } + return $server_schema; } @@ -194,6 +220,7 @@ final class PhabricatorConfigSchemaQuery extends Phobject { if (!$actual_database) { $actual_database = $expect_database->newEmptyClone(); } + if (!$expect_database) { $expect_database = $actual_database->newEmptyClone(); } diff --git a/src/applications/config/schema/PhabricatorConfigStorageSchema.php b/src/applications/config/schema/PhabricatorConfigStorageSchema.php index 74856053e4..706be80568 100644 --- a/src/applications/config/schema/PhabricatorConfigStorageSchema.php +++ b/src/applications/config/schema/PhabricatorConfigStorageSchema.php @@ -17,6 +17,7 @@ abstract class PhabricatorConfigStorageSchema extends Phobject { const ISSUE_SUBFAIL = 'subfail'; const ISSUE_AUTOINCREMENT = 'autoincrement'; const ISSUE_UNKNOWN = 'unknown'; + const ISSUE_ACCESSDENIED = 'accessdenied'; const STATUS_OKAY = 'okay'; const STATUS_WARN = 'warn'; @@ -130,6 +131,8 @@ abstract class PhabricatorConfigStorageSchema extends Phobject { return pht('Column has Wrong Autoincrement'); case self::ISSUE_UNKNOWN: return pht('Column Has No Specification'); + case self::ISSUE_ACCESSDENIED: + return pht('Access Denied'); default: throw new Exception(pht('Unknown schema issue "%s"!', $issue)); } @@ -175,6 +178,7 @@ abstract class PhabricatorConfigStorageSchema extends Phobject { public static function getIssueStatus($issue) { switch ($issue) { case self::ISSUE_MISSING: + case self::ISSUE_ACCESSDENIED: case self::ISSUE_SURPLUS: case self::ISSUE_NULLABLE: case self::ISSUE_SUBFAIL: diff --git a/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php b/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php index 76e8e0a057..ae83be216c 100644 --- a/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php +++ b/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php @@ -123,6 +123,16 @@ final class PhabricatorStorageManagementAPI extends Phobject { 'SELECT patch FROM %T', self::TABLE_STATUS); return ipull($applied, 'patch'); + } catch (AphrontAccessDeniedQueryException $ex) { + throw new PhutilProxyException( + pht( + 'Failed while trying to read schema status: the database "%s" '. + 'exists, but the current user ("%s") does not have permission to '. + 'access it. GRANT the current user more permissions, or use a '. + 'different user.', + $this->getDatabaseName('meta_data'), + $this->getUser()), + $ex); } catch (AphrontQueryException $ex) { return null; } diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php index cbb88ce818..cc917215ee 100644 --- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php +++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php @@ -422,6 +422,11 @@ abstract class PhabricatorStorageManagementWorkflow continue; } + if ($actual_database->getAccessDenied()) { + // If we can't access the database, we can't access the tables either. + continue; + } + $issues = array(); if ($database->hasIssue($issue_charset)) { $issues[] = $issue_charset; @@ -634,6 +639,8 @@ abstract class PhabricatorStorageManagementWorkflow $any_surplus = false; $all_surplus = true; + $any_access = false; + $all_access = true; foreach ($errors as $error) { $pieces = array_select_keys( $error, @@ -643,12 +650,20 @@ abstract class PhabricatorStorageManagementWorkflow $name = PhabricatorConfigStorageSchema::getIssueName($error['issue']); - if ($error['issue'] === PhabricatorConfigStorageSchema::ISSUE_SURPLUS) { + $issue = $error['issue']; + + if ($issue === PhabricatorConfigStorageSchema::ISSUE_SURPLUS) { $any_surplus = true; } else { $all_surplus = false; } + if ($issue === PhabricatorConfigStorageSchema::ISSUE_ACCESSDENIED) { + $any_access = true; + } else { + $all_access = false; + } + $table->addRow( array( 'target' => $target, @@ -668,11 +683,24 @@ abstract class PhabricatorStorageManagementWorkflow 'does not expect). For information on resolving these '. 'issues, see the "Surplus Schemata" section in the "Managing Storage '. 'Adjustments" article in the documentation.'); + } else if ($all_access) { + $message[] = pht( + 'The user you are connecting to MySQL with does not have the correct '. + 'permissions, and can not access some databases or tables that it '. + 'needs to be able to access. GRANT the user additional permissions.'); } else { $message[] = pht( 'The schemata have errors (detailed above) which the adjustment '. 'workflow can not fix.'); + if ($any_access) { + $message[] = pht( + 'Some of these errors are caused by access control problems. '. + 'The user you are connecting with does not have permission to see '. + 'all of the database or tables that Phabricator uses. You need to '. + 'GRANT the user more permission, or use a different user.'); + } + if ($any_surplus) { $message[] = pht( 'Some of these errors are caused by surplus schemata (extra '. @@ -698,6 +726,11 @@ abstract class PhabricatorStorageManagementWorkflow "** %s **\n\n%s\n", pht('SURPLUS SCHEMATA'), phutil_console_wrap($message)); + } else if ($all_access) { + $console->writeOut( + "** %s **\n\n%s\n", + pht('ACCESS DENIED'), + phutil_console_wrap($message)); } else { $console->writeOut( "** %s **\n\n%s\n", From 6a701c19884384f533d637ed283f48234cdd32e6 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Thu, 21 Jan 2016 14:07:09 -0800 Subject: [PATCH 54/66] Spiffy up new sidebar, simplify UI Summary: Mostly a visual spacing pass, also adds in circle icons for edit, collapse. For now removing the fixed position on the icons for simplicity while the basics are being polished. Test Plan: Projects, Profiles, wide and narrow. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D15081 --- resources/celerity/map.php | 10 +- .../CelerityDefaultPostprocessor.php | 16 +-- .../engine/PhabricatorProfilePanelEngine.php | 8 +- .../uiexample/examples/PHUIIconExample.php | 4 +- src/view/phui/PHUIIconCircleView.php | 2 +- src/view/phui/PHUIListItemView.php | 3 +- webroot/rsrc/css/phui/phui-profile-menu.css | 97 ++++++++----------- webroot/rsrc/css/phui/phui-workboard-view.css | 2 +- 8 files changed, 58 insertions(+), 84 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 183f0fa7f3..54af7fcd8f 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => '005bc22f', + 'core.pkg.css' => 'cea85605', 'core.pkg.js' => '573e6664', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -143,7 +143,7 @@ return array( 'rsrc/css/phui/phui-object-item-list-view.css' => '26c30d3f', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', - 'rsrc/css/phui/phui-profile-menu.css' => '84966ae9', + 'rsrc/css/phui/phui-profile-menu.css' => '2168816d', 'rsrc/css/phui/phui-property-list-view.css' => '27b2849e', 'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591', 'rsrc/css/phui/phui-spacing.css' => '042804d6', @@ -152,7 +152,7 @@ return array( 'rsrc/css/phui/phui-text.css' => 'cf019f54', 'rsrc/css/phui/phui-timeline-view.css' => '2efceff8', 'rsrc/css/phui/phui-two-column-view.css' => '39ecafb1', - 'rsrc/css/phui/phui-workboard-view.css' => '8330bca5', + 'rsrc/css/phui/phui-workboard-view.css' => 'f488d036', 'rsrc/css/phui/phui-workpanel-view.css' => 'adec7699', 'rsrc/css/sprite-login.css' => '60e8560e', 'rsrc/css/sprite-menu.css' => '9dd65b92', @@ -819,7 +819,7 @@ return array( 'phui-object-item-list-view-css' => '26c30d3f', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', - 'phui-profile-menu-css' => '84966ae9', + 'phui-profile-menu-css' => '2168816d', 'phui-property-list-view-css' => '27b2849e', 'phui-remarkup-preview-css' => '1a8f2591', 'phui-spacing-css' => '042804d6', @@ -829,7 +829,7 @@ return array( 'phui-theme-css' => '981a58f8', 'phui-timeline-view-css' => '2efceff8', 'phui-two-column-view-css' => '39ecafb1', - 'phui-workboard-view-css' => '8330bca5', + 'phui-workboard-view-css' => 'f488d036', 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', diff --git a/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php b/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php index e6212c4eb0..94246e23c7 100644 --- a/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php +++ b/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php @@ -191,18 +191,10 @@ final class CelerityDefaultPostprocessor // Background color for "dark" themes. 'page.background.dark' => '#ebecee', - // NOTE: We can't just do these with an alpha channel because the - // fixed items in the footer may render on top of other items, so the - // backgrounds must be opaque. - // This is the base background color. - 'menu.profile.background' => '#525868', - - // This is premultiplied 7.5% alpha. - 'menu.profile.background.hover' => '#4c5160', - - // This is premultiplied 15% alpha. - 'menu.profile.background.selected' => '#464b59', + 'menu.profile.background' => '#525867', + 'menu.profile.background.hover' => '#464b58', + 'menu.profile.background.selected' => '#393d48', 'menu.profile.text' => '#c6c7cb', 'menu.profile.text.selected' => '#ffffff', @@ -211,7 +203,7 @@ final class CelerityDefaultPostprocessor 'menu.main.height' => '44px', 'menu.profile.width' => '240px', - 'menu.profile.width.collapsed' => '80px', + 'menu.profile.width.collapsed' => '88px', 'menu.profile.item.height' => '46px', ); diff --git a/src/applications/search/engine/PhabricatorProfilePanelEngine.php b/src/applications/search/engine/PhabricatorProfilePanelEngine.php index 8e11d43e32..5f97ab1f8f 100644 --- a/src/applications/search/engine/PhabricatorProfilePanelEngine.php +++ b/src/applications/search/engine/PhabricatorProfilePanelEngine.php @@ -327,12 +327,12 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $object, PhabricatorPolicyCapability::CAN_EDIT); - $expanded_edit_icon = id(new PHUIIconView()) + $expanded_edit_icon = id(new PHUIIconCircleView()) ->addClass('phui-list-item-icon') ->addClass('phui-profile-menu-visible-when-expanded') ->setIconFont('fa-pencil'); - $collapsed_edit_icon = id(new PHUIIconView()) + $collapsed_edit_icon = id(new PHUIIconCircleView()) ->addClass('phui-list-item-icon') ->addClass('phui-profile-menu-visible-when-collapsed') ->setIconFont('fa-pencil') @@ -386,12 +386,12 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { 'settingsURI' => $settings_uri, )); - $collapse_icon = id(new PHUIIconView()) + $collapse_icon = id(new PHUIIconCircleView()) ->addClass('phui-list-item-icon') ->addClass('phui-profile-menu-visible-when-expanded') ->setIconFont('fa-angle-left'); - $expand_icon = id(new PHUIIconView()) + $expand_icon = id(new PHUIIconCircleView()) ->addClass('phui-list-item-icon') ->addClass('phui-profile-menu-visible-when-collapsed') ->addSigil('has-tooltip') diff --git a/src/applications/uiexample/examples/PHUIIconExample.php b/src/applications/uiexample/examples/PHUIIconExample.php index 3aa746b7b6..28d957b460 100644 --- a/src/applications/uiexample/examples/PHUIIconExample.php +++ b/src/applications/uiexample/examples/PHUIIconExample.php @@ -115,7 +115,7 @@ final class PHUIIconExample extends PhabricatorUIExample { foreach ($circles as $circle) { $circleview[] = id(new PHUIIconCircleView()) - ->setIcon($circle) + ->setIconFont($circle) ->setHref('#') ->addClass('mmr'); } @@ -124,7 +124,7 @@ final class PHUIIconExample extends PhabricatorUIExample { foreach ($circles as $circle) { $circleview[] = id(new PHUIIconCircleView()) - ->setIcon($circle) + ->setIconFont($circle) ->setSize(PHUIIconCircleView::MEDIUM) ->setHref('#') ->addClass('mmr'); diff --git a/src/view/phui/PHUIIconCircleView.php b/src/view/phui/PHUIIconCircleView.php index 63165c38be..1269c4e28c 100644 --- a/src/view/phui/PHUIIconCircleView.php +++ b/src/view/phui/PHUIIconCircleView.php @@ -15,7 +15,7 @@ final class PHUIIconCircleView extends AphrontTagView { return $this; } - public function setIcon($icon) { + public function setIconFont($icon) { $this->icon = $icon; return $this; } diff --git a/src/view/phui/PHUIListItemView.php b/src/view/phui/PHUIListItemView.php index abe1c11409..f0bb46fb87 100644 --- a/src/view/phui/PHUIListItemView.php +++ b/src/view/phui/PHUIListItemView.php @@ -160,7 +160,7 @@ final class PHUIListItemView extends AphrontTagView { return $this; } - public function addIcon(PHUIIconView $icon) { + public function addIcon($icon) { $this->icons[] = $icon; return $this; } @@ -275,6 +275,7 @@ final class PHUIListItemView extends AphrontTagView { if ($this->profileImage) { $icon = id(new PHUIIconView()) ->setHeadSize(PHUIIconView::HEAD_SMALL) + ->addClass('phui-list-item-icon') ->setImage($this->profileImage); } diff --git a/webroot/rsrc/css/phui/phui-profile-menu.css b/webroot/rsrc/css/phui/phui-profile-menu.css index c749c7f3d4..4d339fe387 100644 --- a/webroot/rsrc/css/phui/phui-profile-menu.css +++ b/webroot/rsrc/css/phui/phui-profile-menu.css @@ -45,29 +45,27 @@ .phui-profile-menu .phabricator-side-menu .phui-list-item-href { display: block; text-decoration: none; - padding: 12px 8px 12px 48px; - font-size: 15px; + padding: 0 8px 0 48px; + height: 48px; + font-size: {$biggerfontsize}; -webkit-font-smoothing: antialiased; color: {$menu.profile.text}; line-height: 22px; overflow: hidden; text-overflow: ellipsis; - - /* NOTE: We must have an opaque background on these items so the footer - items appear opaque when the render over normal items. */ - background: {$menu.profile.background}; + line-height: 48px; } .phui-profile-menu .phabricator-side-menu .phui-list-item-icon, .phui-profile-menu .phabricator-side-menu - .phui-list-item-href .phui-icon-view { + .phui-list-item-href .phui-list-item-icon { position: absolute; top: 12px; left: 13px; - font-size: 20px; - width: 22px; - height: 22px; - line-height: 22px; + font-size: 24px; + width: 24px; + height: 24px; + line-height: 24px; text-align: center; color: {$menu.profile.text}; background-size: 100%; @@ -76,9 +74,10 @@ .phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu .phui-list-item-href { text-align: center; - padding: 42px 8px 12px; - font-size: 11px; - line-height: 13px; + padding: 42px 4px 14px; + line-height: 14px; + height: auto; + font-size: {$smallerfontsize}; } .phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu @@ -91,9 +90,9 @@ .phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu .phui-list-item-icon, .phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu - .phui-list-item-href .phui-icon-view { - top: 10px; - left: 29px; + .phui-list-item-href .phui-list-item-icon { + top: 14px; + left: 31px; } .phui-profile-menu .phabricator-side-menu @@ -130,10 +129,9 @@ color: {$menu.profile.text.selected}; } - .phui-profile-menu .phabricator-side-menu .phui-divider { margin: 4px 0; - border-bottom: 1px solid rgba(0, 0, 0, 0.200); + border-bottom: 1px solid rgba(0, 0, 0, 0.2); } .phui-profile-menu .phabricator-side-menu .phui-motivator { @@ -154,54 +152,37 @@ height: {$menu.profile.item.height}; } -.phui-profile-menu .phabricator-side-menu .phui-profile-menu-footer { - position: fixed; - box-sizing: border-box; - width: {$menu.profile.width}; - bottom: 0px; -} - -.phui-profile-menu .phabricator-side-menu .phui-profile-menu-footer-1 { - left: 0; -} - -.phui-profile-menu .phabricator-side-menu .phui-profile-menu-footer-2 { - left: 120px; -} - -.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu - .phui-profile-menu-footer { - width: 40px; - height: {$menu.profile.item.height}; - bottom: 0px; -} - -.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu - .phui-profile-menu-footer-1 { - left: 0; -} - -.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu - .phui-profile-menu-footer-2 { - left: 40px; -} - .phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu .phui-profile-menu-footer .phui-list-item-name { display: none; } -.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu - .phui-profile-menu-footer - .phui-list-item-icon { - top: 10px; - left: 10px; -} - .phui-profile-menu .phui-profile-menu-expanded .phui-profile-menu-visible-when-collapsed, .phui-profile-menu .phui-profile-menu-collapsed .phui-profile-menu-visible-when-expanded { display: none; } + +.phui-profile-menu .phui-profile-menu-footer .phui-icon-circle { + border-color: {$menu.profile.text}; +} + +.phui-profile-menu .phui-profile-menu-footer .phui-icon-circle .phui-icon-view { + color: {$menu.profile.text}; +} + +.phui-profile-menu .phui-profile-menu-footer:hover .phui-icon-circle { + border-color: #fff; +} + +.phui-profile-menu .phui-profile-menu-footer:hover .phui-icon-circle + .phui-icon-view { + color: #fff; +} + +.phui-profile-menu .phui-profile-menu-footer + .phui-icon-circle.phui-list-item-icon { + font-size: 11px; +} diff --git a/webroot/rsrc/css/phui/phui-workboard-view.css b/webroot/rsrc/css/phui/phui-workboard-view.css index becd8ba0a2..5d4ed5dd1c 100644 --- a/webroot/rsrc/css/phui/phui-workboard-view.css +++ b/webroot/rsrc/css/phui/phui-workboard-view.css @@ -43,7 +43,7 @@ .device-desktop .phui-profile-menu-collapsed .project-board-wrapper .phui-workboard-view-shadow { - left: 93px; + left: 101px; } .device-desktop .phui-workboard-view .aphront-multi-column-fixed From 5f170847caa81e66ef3f30392c1a8d29c03a4e32 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 21 Jan 2016 13:15:38 -0800 Subject: [PATCH 55/66] Throw a more tailored error when a `storage upgrade` patch can't access a database Summary: Fixes T8762. Test Plan: Ran `bin/storage upgrade --namespace ... --user limited`, saw a more specific error. Reviewers: chad Reviewed By: chad Maniphest Tasks: T8762 Differential Revision: https://secure.phabricator.com/D15080 --- .../PhabricatorStorageManagementAPI.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php b/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php index ae83be216c..87cb079c7e 100644 --- a/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php +++ b/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php @@ -256,10 +256,19 @@ final class PhabricatorStorageManagementAPI extends Phobject { $query = str_replace('{$'.$key.'}', $value, $query); } - queryfx( - $conn, - '%Q', - $query); + try { + queryfx($conn, '%Q', $query); + } catch (AphrontAccessDeniedQueryException $ex) { + throw new PhutilProxyException( + pht( + 'Unable to access a required database or table. This almost '. + 'always means that the user you are connecting with ("%s") does '. + 'not have sufficient permissions granted in MySQL. You can '. + 'use `bin/storage databases` to get a list of all databases '. + 'permission is required on.', + $this->getUser()), + $ex); + } } } From 6ea9aa39a08adb4952f77b106c59cd18a626882b Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 21 Jan 2016 16:21:48 -0800 Subject: [PATCH 56/66] Fix quicksand interaction with HTTP GET prefilling in ApplicationSearch Summary: Fixes T10196. This is a weird interaction and this might not be the best long-term fix, but just get it working OK for now. General problem is that Quicksand doesn't currently use GET for requests. This is a very unusual case where the method is relevant. In the future, I might change Quicksand to use GET. Test Plan: Clicked "Open Tasks" with Quicksand active, got a results list. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10196 Differential Revision: https://secure.phabricator.com/D15082 --- .../controller/PhabricatorApplicationSearchController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/search/controller/PhabricatorApplicationSearchController.php b/src/applications/search/controller/PhabricatorApplicationSearchController.php index 186e6474cd..3b30d5d30c 100644 --- a/src/applications/search/controller/PhabricatorApplicationSearchController.php +++ b/src/applications/search/controller/PhabricatorApplicationSearchController.php @@ -100,7 +100,7 @@ final class PhabricatorApplicationSearchController } else if (!strlen($this->queryKey)) { $found_query_data = false; - if ($request->isHTTPGet()) { + if ($request->isHTTPGet() || $request->isQuicksand()) { // If this is a GET request and it has some query data, don't // do anything unless it's only before= or after=. We'll build and // execute a query from it below. This allows external tools to build From 1eec7471235231cec246d9230cef5f9b7d182f25 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Thu, 21 Jan 2016 19:02:08 -0800 Subject: [PATCH 57/66] More profile nav updates Summary: Sets the edit, collapse icons back in the footer, also adds basic transitions. Test Plan: lots of clicking, safari and chrome {F1066381} Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D15083 --- resources/celerity/map.php | 6 +- webroot/rsrc/css/phui/phui-profile-menu.css | 69 ++++++++++++++++++--- 2 files changed, 63 insertions(+), 12 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 54af7fcd8f..68c281faa5 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => 'cea85605', + 'core.pkg.css' => '1d1e9a3a', 'core.pkg.js' => '573e6664', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -143,7 +143,7 @@ return array( 'rsrc/css/phui/phui-object-item-list-view.css' => '26c30d3f', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', - 'rsrc/css/phui/phui-profile-menu.css' => '2168816d', + 'rsrc/css/phui/phui-profile-menu.css' => '43826c43', 'rsrc/css/phui/phui-property-list-view.css' => '27b2849e', 'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591', 'rsrc/css/phui/phui-spacing.css' => '042804d6', @@ -819,7 +819,7 @@ return array( 'phui-object-item-list-view-css' => '26c30d3f', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', - 'phui-profile-menu-css' => '2168816d', + 'phui-profile-menu-css' => '43826c43', 'phui-property-list-view-css' => '27b2849e', 'phui-remarkup-preview-css' => '1a8f2591', 'phui-spacing-css' => '042804d6', diff --git a/webroot/rsrc/css/phui/phui-profile-menu.css b/webroot/rsrc/css/phui/phui-profile-menu.css index 4d339fe387..8c765b56f2 100644 --- a/webroot/rsrc/css/phui/phui-profile-menu.css +++ b/webroot/rsrc/css/phui/phui-profile-menu.css @@ -18,6 +18,7 @@ vertical-align: top; width: {$menu.profile.width}; max-width: {$menu.profile.width}; + transition: .2s; margin-top: 0; overflow: hidden; } @@ -92,7 +93,7 @@ .phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu .phui-list-item-href .phui-list-item-icon { top: 14px; - left: 31px; + left: 32px; } .phui-profile-menu .phabricator-side-menu @@ -109,6 +110,7 @@ .phui-list-item-href:hover { background-color: {$menu.profile.background.hover}; color: {$menu.profile.text.selected}; + transition: 0.2s; } .phui-profile-menu .phabricator-side-menu @@ -118,15 +120,14 @@ .phui-list-item-href:hover .phui-list-item-icon { color: {$menu.profile.text.selected}; + transition: 0.2s; } .phui-profile-menu .phabricator-side-menu .phui-list-item-selected - .phui-list-item-href, -.device-desktop .phui-profile-menu .phabricator-side-menu - .phui-list-item-selected - .phui-list-item-href:hover { + .phui-list-item-href { background-color: {$menu.profile.background.selected}; color: {$menu.profile.text.selected}; + transition: 0.2s; } .phui-profile-menu .phabricator-side-menu .phui-divider { @@ -165,6 +166,22 @@ display: none; } + +.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu + .phui-profile-menu-footer .phui-list-item-href { + padding: 20px 0 20px; +} + +.phui-profile-menu .phabricator-side-menu .phui-profile-menu-footer + .phui-list-item-href:hover { + background: transparent; +} + +.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu + .phui-profile-menu-footer .phui-list-item-href .phui-list-item-icon { + top: 8px; +} + .phui-profile-menu .phui-profile-menu-footer .phui-icon-circle { border-color: {$menu.profile.text}; } @@ -173,12 +190,17 @@ color: {$menu.profile.text}; } -.phui-profile-menu .phui-profile-menu-footer:hover .phui-icon-circle { - border-color: #fff; +.phui-profile-menu .phui-profile-menu-footer .phui-list-item-href:hover + .phui-icon-circle, +.phui-profile-menu .phui-list-item-selected.phui-profile-menu-footer + .phui-icon-circle { + border-color: #fff; } -.phui-profile-menu .phui-profile-menu-footer:hover .phui-icon-circle - .phui-icon-view { +.phui-profile-menu .phui-profile-menu-footer .phui-list-item-href:hover + .phui-icon-circle .phui-icon-view, +.phui-profile-menu .phui-list-item-selected.phui-profile-menu-footer + .phui-icon-circle .phui-icon-view { color: #fff; } @@ -186,3 +208,32 @@ .phui-icon-circle.phui-list-item-icon { font-size: 11px; } + +div.phui-profile-menu .phabricator-side-menu .phui-profile-menu-footer-1 { + bottom: 40px; + position: fixed; + background-color: {$menu.profile.background}; +} + +div.phui-profile-menu .phabricator-side-menu .phui-profile-menu-footer-2 { + bottom: 0; + position: fixed; + background-color: {$menu.profile.background}; +} + +.phui-profile-menu .phui-profile-menu-footer-1, +.phui-profile-menu .phui-profile-menu-footer-2 { + width: {$menu.profile.width}; + transition: .2s; +} + +.phui-profile-menu .phui-profile-menu-collapsed .phui-profile-menu-footer-1, +.phui-profile-menu .phui-profile-menu-collapsed .phui-profile-menu-footer-2 { + width: {$menu.profile.width.collapsed}; + transition: .2s; +} + +.phui-profile-menu .phabricator-side-menu + .phui-list-item-selected.phui-profile-menu-footer .phui-list-item-href { + background: transparent; +} From 12a87267831054ecb8bc370a1f89e74b3a77ae70 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 22 Jan 2016 04:01:55 -0800 Subject: [PATCH 58/66] Fix an issue where the first click on the profile menu collapse link could be swallowed Summary: `alterClass()` is strict about true/false but we set 0/1 elsewhere. Test Plan: Collapsed/expanded menu, reloaded expanded menu, clicked collapse, got immediate collapse. Reviewers: chad Reviewed By: chad Differential Revision: https://secure.phabricator.com/D15087 --- .../search/engine/PhabricatorProfilePanelEngine.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/search/engine/PhabricatorProfilePanelEngine.php b/src/applications/search/engine/PhabricatorProfilePanelEngine.php index 5f97ab1f8f..9ab8d6c591 100644 --- a/src/applications/search/engine/PhabricatorProfilePanelEngine.php +++ b/src/applications/search/engine/PhabricatorProfilePanelEngine.php @@ -382,7 +382,7 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { array( 'menuID' => $nav->getMainID(), 'collapseID' => $collapse_id, - 'isCollapsed' => $is_collapsed, + 'isCollapsed' => (bool)$is_collapsed, 'settingsURI' => $settings_uri, )); From c25de5e02fb420cda91c28304439332c189a5409 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 22 Jan 2016 04:33:23 -0800 Subject: [PATCH 59/66] Allow project colors to be relabeled Summary: Fixes T5819. Adds configuration for setting color labels on projects and changing the default. Options are locked to what we make available. Test Plan: {F1066823} Reviewers: chad Reviewed By: chad Maniphest Tasks: T5819 Differential Revision: https://secure.phabricator.com/D15088 --- src/__phutil_library_map__.php | 6 +- ...abricatorProjectColorsConfigOptionType.php | 10 ++ .../PhabricatorProjectConfigOptions.php | 26 ++- ...abricatorProjectIconsConfigOptionType.php} | 2 +- .../icon/PhabricatorProjectIconSet.php | 163 ++++++++++++++++-- .../query/PhabricatorProjectSearchEngine.php | 4 +- .../project/storage/PhabricatorProject.php | 7 +- 7 files changed, 197 insertions(+), 21 deletions(-) create mode 100644 src/applications/project/config/PhabricatorProjectColorsConfigOptionType.php rename src/applications/project/config/{PhabricatorProjectTypeConfigOptionType.php => PhabricatorProjectIconsConfigOptionType.php} (79%) diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 2b995de20d..720a5d0c3c 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2858,6 +2858,7 @@ phutil_register_library_map(array( 'PhabricatorProjectBoardImportController' => 'applications/project/controller/PhabricatorProjectBoardImportController.php', 'PhabricatorProjectBoardReorderController' => 'applications/project/controller/PhabricatorProjectBoardReorderController.php', 'PhabricatorProjectBoardViewController' => 'applications/project/controller/PhabricatorProjectBoardViewController.php', + 'PhabricatorProjectColorsConfigOptionType' => 'applications/project/config/PhabricatorProjectColorsConfigOptionType.php', 'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php', 'PhabricatorProjectColumnDetailController' => 'applications/project/controller/PhabricatorProjectColumnDetailController.php', 'PhabricatorProjectColumnEditController' => 'applications/project/controller/PhabricatorProjectColumnEditController.php', @@ -2890,6 +2891,7 @@ phutil_register_library_map(array( 'PhabricatorProjectHeraldFieldGroup' => 'applications/project/herald/PhabricatorProjectHeraldFieldGroup.php', 'PhabricatorProjectHistoryController' => 'applications/project/controller/PhabricatorProjectHistoryController.php', 'PhabricatorProjectIconSet' => 'applications/project/icon/PhabricatorProjectIconSet.php', + 'PhabricatorProjectIconsConfigOptionType' => 'applications/project/config/PhabricatorProjectIconsConfigOptionType.php', 'PhabricatorProjectInterface' => 'applications/project/interface/PhabricatorProjectInterface.php', 'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php', 'PhabricatorProjectListView' => 'applications/project/view/PhabricatorProjectListView.php', @@ -2937,7 +2939,6 @@ phutil_register_library_map(array( 'PhabricatorProjectTransaction' => 'applications/project/storage/PhabricatorProjectTransaction.php', 'PhabricatorProjectTransactionEditor' => 'applications/project/editor/PhabricatorProjectTransactionEditor.php', 'PhabricatorProjectTransactionQuery' => 'applications/project/query/PhabricatorProjectTransactionQuery.php', - 'PhabricatorProjectTypeConfigOptionType' => 'applications/project/config/PhabricatorProjectTypeConfigOptionType.php', 'PhabricatorProjectUIEventListener' => 'applications/project/events/PhabricatorProjectUIEventListener.php', 'PhabricatorProjectUpdateController' => 'applications/project/controller/PhabricatorProjectUpdateController.php', 'PhabricatorProjectUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectUserFunctionDatasource.php', @@ -7255,6 +7256,7 @@ phutil_register_library_map(array( 'PhabricatorProjectBoardImportController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardReorderController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardViewController' => 'PhabricatorProjectBoardController', + 'PhabricatorProjectColorsConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'PhabricatorProjectColumn' => array( 'PhabricatorProjectDAO', 'PhabricatorApplicationTransactionInterface', @@ -7298,6 +7300,7 @@ phutil_register_library_map(array( 'PhabricatorProjectHeraldFieldGroup' => 'HeraldFieldGroup', 'PhabricatorProjectHistoryController' => 'PhabricatorProjectController', 'PhabricatorProjectIconSet' => 'PhabricatorIconSet', + 'PhabricatorProjectIconsConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'PhabricatorProjectListController' => 'PhabricatorProjectController', 'PhabricatorProjectListView' => 'AphrontView', 'PhabricatorProjectLockController' => 'PhabricatorProjectController', @@ -7347,7 +7350,6 @@ phutil_register_library_map(array( 'PhabricatorProjectTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorProjectTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorProjectTransactionQuery' => 'PhabricatorApplicationTransactionQuery', - 'PhabricatorProjectTypeConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'PhabricatorProjectUIEventListener' => 'PhabricatorEventListener', 'PhabricatorProjectUpdateController' => 'PhabricatorProjectController', 'PhabricatorProjectUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', diff --git a/src/applications/project/config/PhabricatorProjectColorsConfigOptionType.php b/src/applications/project/config/PhabricatorProjectColorsConfigOptionType.php new file mode 100644 index 0000000000..4cd8c09bbc --- /dev/null +++ b/src/applications/project/config/PhabricatorProjectColorsConfigOptionType.php @@ -0,0 +1,10 @@ +deformat(pht(<<deformat(pht(<< true, @@ -76,6 +97,9 @@ EOTEXT $this->newOption('projects.icons', $icons_type, $default_icons) ->setSummary(pht('Adjust project icons.')) ->setDescription($icons_description), + $this->newOption('projects.colors', $colors_type, $default_colors) + ->setSummary(pht('Adjust project colors.')) + ->setDescription($colors_description), ); } diff --git a/src/applications/project/config/PhabricatorProjectTypeConfigOptionType.php b/src/applications/project/config/PhabricatorProjectIconsConfigOptionType.php similarity index 79% rename from src/applications/project/config/PhabricatorProjectTypeConfigOptionType.php rename to src/applications/project/config/PhabricatorProjectIconsConfigOptionType.php index 8c65dfe35a..054a696a44 100644 --- a/src/applications/project/config/PhabricatorProjectTypeConfigOptionType.php +++ b/src/applications/project/config/PhabricatorProjectIconsConfigOptionType.php @@ -1,6 +1,6 @@ PHUITagView::COLOR_RED, + 'name' => pht('Red'), + ), + array( + 'key' => PHUITagView::COLOR_ORANGE, + 'name' => pht('Orange'), + ), + array( + 'key' => PHUITagView::COLOR_YELLOW, + 'name' => pht('Yellow'), + ), + array( + 'key' => PHUITagView::COLOR_GREEN, + 'name' => pht('Green'), + ), + array( + 'key' => PHUITagView::COLOR_BLUE, + 'name' => pht('Blue'), + 'default' => true, + ), + array( + 'key' => PHUITagView::COLOR_INDIGO, + 'name' => pht('Indigo'), + ), + array( + 'key' => PHUITagView::COLOR_VIOLET, + 'name' => pht('Violet'), + ), + array( + 'key' => PHUITagView::COLOR_PINK, + 'name' => pht('Pink'), + ), + array( + 'key' => PHUITagView::COLOR_GREY, + 'name' => pht('Grey'), + ), + array( + 'key' => PHUITagView::COLOR_CHECKERED, + 'name' => pht('Checkered'), + ), + ); + } + + public static function validateColorConfiguration($config) { + if (!is_array($config)) { + throw new Exception( + pht('Configuration must be a list of project color specifications.')); + } + + $available_keys = self::getAvailableColorKeys(); + $available_keys = array_fuse($available_keys); + + foreach ($config as $idx => $value) { + if (!is_array($value)) { + throw new Exception( + pht( + 'Value for index "%s" should be a dictionary.', + $idx)); + } + + PhutilTypeSpec::checkMap( + $value, + array( + 'key' => 'string', + 'name' => 'string', + 'default' => 'optional bool', + )); + + $key = $value['key']; + if (!isset($available_keys[$key])) { + throw new Exception( + pht( + 'Color key "%s" is not a valid color key. The supported color '. + 'keys are: %s.', + $key, + implode(', ', $available_keys))); + } + } + + $default = null; + $keys = array(); + foreach ($config as $idx => $value) { + $key = $value['key']; + if (isset($keys[$key])) { + throw new Exception( + pht( + 'Project colors must have unique keys, but two icons share the '. + 'same key ("%s").', + $key)); + } else { + $keys[$key] = true; + } + + if (idx($value, 'default')) { + if ($default === null) { + $default = $value; + } else { + $original_key = $default['key']; + throw new Exception( + pht( + 'Two different colors ("%s", "%s") are marked as the default '. + 'color. Only one color may be marked as the default.', + $key, + $original_key)); + } + } + } + + if ($default === null) { + throw new Exception( + pht( + 'Project colors must include one color marked as the "%s" color, '. + 'but no such color exists.', + 'default')); + } + + } + } diff --git a/src/applications/project/query/PhabricatorProjectSearchEngine.php b/src/applications/project/query/PhabricatorProjectSearchEngine.php index eca90853cc..7d533c8a11 100644 --- a/src/applications/project/query/PhabricatorProjectSearchEngine.php +++ b/src/applications/project/query/PhabricatorProjectSearchEngine.php @@ -42,7 +42,7 @@ final class PhabricatorProjectSearchEngine } -protected function buildQueryFromParameters(array $map) { + protected function buildQueryFromParameters(array $map) { $query = $this->newQuery(); if (strlen($map['name'])) { @@ -155,8 +155,6 @@ protected function buildQueryFromParameters(array $map) { ->setType(PHUITagView::TYPE_SHADE) ->setShade($color) ->setName($name), - ' ', - $name, ); } diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php index 5f4d511158..97ed2765ef 100644 --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -44,8 +44,6 @@ final class PhabricatorProject extends PhabricatorProjectDAO private $slugs = self::ATTACHABLE; private $parentProject = self::ATTACHABLE; - const DEFAULT_COLOR = 'blue'; - const TABLE_DATASOURCE_TOKEN = 'project_datasourcetoken'; const PANEL_PROFILE = 'project.profile'; @@ -68,11 +66,12 @@ final class PhabricatorProject extends PhabricatorProjectDAO ProjectDefaultJoinCapability::CAPABILITY); $default_icon = PhabricatorProjectIconSet::getDefaultIconKey(); + $default_color = PhabricatorProjectIconSet::getDefaultColorKey(); return id(new PhabricatorProject()) ->setAuthorPHID($actor->getPHID()) ->setIcon($default_icon) - ->setColor(self::DEFAULT_COLOR) + ->setColor($default_color) ->setViewPolicy($view_policy) ->setEditPolicy($edit_policy) ->setJoinPolicy($join_policy) @@ -511,7 +510,7 @@ final class PhabricatorProject extends PhabricatorProjectDAO public function getDisplayColor() { if ($this->isMilestone()) { - return self::DEFAULT_COLOR; + return PhabricatorProjectIconSet::getDefaultColorKey(); } return $this->getColor(); From 51ed95c00b8de3a7e552858b215aaa25e9871bc5 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 22 Jan 2016 05:33:21 -0800 Subject: [PATCH 60/66] Give profile menus more straightforward hide/disable/delete/default interactions Summary: Ref T10054. - Just let users delete non-builtin items. - Let users choose a default item explicitly. - Do a better job of cleaning up items which no longer exist or belong to uninstalled applications. (NOTE) This has one user-facing change: workboards are no longer the default on projects with workboards. I think this is probably OK since we're giving users a ton of new toys at the same time, but I'll write some docs at least. Test Plan: - Deleted custom items. - Disabled/enabled builtin items. - Made various things defaults. - Uninstalled Maniphest, saw Workboards tab disappear entirely. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15089 --- .../base/PhabricatorApplication.php | 1 + .../PhabricatorProjectBoardViewController.php | 11 +- .../PhabricatorProjectViewController.php | 17 +- .../PhabricatorProjectDetailsProfilePanel.php | 5 + ...habricatorProjectWorkboardProfilePanel.php | 5 + .../engine/PhabricatorProfilePanelEngine.php | 239 ++++++++++++++++-- .../profilepanel/PhabricatorProfilePanel.php | 5 + .../PhabricatorProfilePanelConfiguration.php | 16 +- 8 files changed, 251 insertions(+), 48 deletions(-) diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php index 4fc3e10314..0ed4917800 100644 --- a/src/applications/base/PhabricatorApplication.php +++ b/src/applications/base/PhabricatorApplication.php @@ -641,6 +641,7 @@ abstract class PhabricatorApplication return array( '(?Pview)/(?P[^/]+)/' => $controller, '(?Phide)/(?P[^/]+)/' => $controller, + '(?Pdefault)/(?P[^/]+)/' => $controller, '(?Pconfigure)/' => $controller, '(?Preorder)/' => $controller, '(?Pedit)/'.$edit_route => $controller, diff --git a/src/applications/project/controller/PhabricatorProjectBoardViewController.php b/src/applications/project/controller/PhabricatorProjectBoardViewController.php index 571d5b866d..1b2d9d65e2 100644 --- a/src/applications/project/controller/PhabricatorProjectBoardViewController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardViewController.php @@ -712,16 +712,15 @@ final class PhabricatorProjectBoardViewController pht('Import Columns'), pht('Import board columns from another project.')); - $dialog = id(new AphrontDialogView()) - ->setUser($this->getRequest()->getUser()) + + $cancel_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); + + return $this->newDialog() ->setTitle(pht('New Workboard')) ->addSubmitButton('Continue') - ->addCancelButton($this->getApplicationURI('view/'.$project->getID().'/')) + ->addCancelButton($cancel_uri) ->appendParagraph($instructions) ->appendChild($new_selector); - - return id(new AphrontDialogResponse()) - ->setDialog($dialog); } private function noAccessDialog(PhabricatorProject $project) { diff --git a/src/applications/project/controller/PhabricatorProjectViewController.php b/src/applications/project/controller/PhabricatorProjectViewController.php index 087971878b..412565c056 100644 --- a/src/applications/project/controller/PhabricatorProjectViewController.php +++ b/src/applications/project/controller/PhabricatorProjectViewController.php @@ -17,21 +17,14 @@ final class PhabricatorProjectViewController } $project = $this->getProject(); - $columns = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withProjectPHIDs(array($project->getPHID())) - ->execute(); - if ($columns) { - $controller = 'board'; - } else { - $controller = 'profile'; - } + $engine = $this->getProfilePanelEngine(); + $default = $engine->getDefaultPanel(); - switch ($controller) { - case 'board': + switch ($default->getBuiltinKey()) { + case PhabricatorProject::PANEL_WORKBOARD: $controller_object = new PhabricatorProjectBoardViewController(); break; - case 'profile': + case PhabricatorProject::PANEL_PROFILE: default: $controller_object = new PhabricatorProjectProfileController(); break; diff --git a/src/applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php b/src/applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php index 97ba3a1aaa..07e6ce4c10 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php +++ b/src/applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php @@ -13,6 +13,11 @@ final class PhabricatorProjectDetailsProfilePanel return pht('Project Details'); } + public function canMakeDefault( + PhabricatorProfilePanelConfiguration $config) { + return true; + } + public function getDisplayName( PhabricatorProfilePanelConfiguration $config) { $name = $config->getPanelProperty('name'); diff --git a/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php b/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php index 02b54537e5..f8b2abfc2f 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php +++ b/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php @@ -13,6 +13,11 @@ final class PhabricatorProjectWorkboardProfilePanel return pht('Workboard'); } + public function canMakeDefault( + PhabricatorProfilePanelConfiguration $config) { + return true; + } + public function getDisplayName( PhabricatorProfilePanelConfiguration $config) { $name = $config->getPanelProperty('name'); diff --git a/src/applications/search/engine/PhabricatorProfilePanelEngine.php b/src/applications/search/engine/PhabricatorProfilePanelEngine.php index 9ab8d6c591..ea4cefce56 100644 --- a/src/applications/search/engine/PhabricatorProfilePanelEngine.php +++ b/src/applications/search/engine/PhabricatorProfilePanelEngine.php @@ -5,6 +5,7 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { private $viewer; private $profileObject; private $panels; + private $defaultPanel; private $controller; private $navigation; @@ -35,6 +36,17 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { return $this->controller; } + private function setDefaultPanel( + PhabricatorProfilePanelConfiguration $default_panel) { + $this->defaultPanel = $default_panel; + return $this; + } + + public function getDefaultPanel() { + $this->loadPanels(); + return $this->defaultPanel; + } + abstract protected function getPanelURI($path); protected function isPanelEngineConfigurable() { @@ -89,6 +101,7 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { case 'view': case 'info': case 'hide': + case 'default': case 'builtin': if (!$selected_panel) { return new Aphront404Response(); @@ -122,6 +135,11 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { case 'hide': $content = $this->buildPanelHideContent($selected_panel); break; + case 'default': + $content = $this->buildPanelDefaultContent( + $selected_panel, + $panel_list); + break; case 'edit': $content = $this->buildPanelEditContent(); break; @@ -225,7 +243,15 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { foreach ($stored_panels as $stored_panel) { $builtin_key = $stored_panel->getBuiltinKey(); if ($builtin_key !== null) { - $panels[$builtin_key] = $stored_panel; + // If this builtin actually exists, replace the builtin with the + // stored configuration. Otherwise, we're just going to drop the + // stored config: it corresponds to an out-of-date or uninstalled + // panel. + if (isset($panels[$builtin_key])) { + $panels[$builtin_key] = $stored_panel; + } else { + continue; + } } else { $panels[] = $stored_panel; } @@ -243,6 +269,33 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { // partially keyed. $panels = array_values($panels); + + // Make sure exactly one valid panel is marked as default. + $default = null; + $first = null; + foreach ($panels as $panel) { + if (!$panel->canMakeDefault()) { + continue; + } + + if ($panel->isDefault()) { + $default = $panel; + break; + } + + if ($first === null) { + $first = $panel; + } + } + + if (!$default) { + $default = $first; + } + + if ($default) { + $this->setDefaultPanel($default); + } + return $panels; } @@ -542,6 +595,31 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { 'key' => nonempty($id, $builtin_key), )); + if ($id) { + $default_uri = $this->getPanelURI("default/{$id}/"); + } else { + $default_uri = $this->getPanelURI("default/{$builtin_key}/"); + } + + if ($panel->isDefault()) { + $default_icon = 'fa-thumb-tack green'; + $default_text = pht('Current Default'); + } else if ($panel->canMakeDefault()) { + $default_icon = 'fa-thumb-tack'; + $default_text = pht('Make Default'); + } else { + $default_text = null; + } + + if ($default_text !== null) { + $item->addAction( + id(new PHUIListItemView()) + ->setHref($default_uri) + ->setWorkflow(true) + ->setName($default_text) + ->setIcon($default_icon)); + } + if ($id) { $item->setHref($this->getPanelURI("edit/{$id}/")); $hide_uri = $this->getPanelURI("hide/{$id}/"); @@ -550,16 +628,27 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $hide_uri = $this->getPanelURI("hide/{$builtin_key}/"); } + if ($panel->isDisabled()) { + $hide_icon = 'fa-plus'; + $hide_text = pht('Show'); + } else if ($panel->getBuiltinKey() !== null) { + $hide_icon = 'fa-times'; + $hide_text = pht('Disable'); + } else { + $hide_icon = 'fa-times'; + $hide_text = pht('Delete'); + } + $item->addAction( id(new PHUIListItemView()) ->setHref($hide_uri) ->setWorkflow(true) - ->setIcon(pht('fa-eye'))); + ->setName($hide_text) + ->setIcon($hide_icon)); } if ($panel->isDisabled()) { $item->setDisabled(true); - $item->addIcon('fa-times grey', pht('Disabled')); } $list->addItem($item); @@ -707,18 +796,130 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $configuration, PhabricatorPolicyCapability::CAN_EDIT); + if ($configuration->getBuiltinKey() === null) { + $new_value = null; + + $title = pht('Delete Menu Item'); + $body = pht('Delete this menu item?'); + $button = pht('Delete Menu Item'); + } else if ($configuration->isDisabled()) { + $new_value = PhabricatorProfilePanelConfiguration::VISIBILITY_VISIBLE; + + $title = pht('Enable Menu Item'); + $body = pht( + 'Enable this menu item? It will appear in the menu again.'); + $button = pht('Enable Menu Item'); + } else { + $new_value = PhabricatorProfilePanelConfiguration::VISIBILITY_DISABLED; + + $title = pht('Disable Menu Item'); + $body = pht( + 'Disable this menu item? It will no longer appear in the menu, but '. + 'you can re-enable it later.'); + $button = pht('Disable Menu Item'); + } + $v_visibility = $configuration->getVisibility(); if ($request->isFormPost()) { - $v_visibility = $request->getStr('visibility'); + if ($new_value === null) { + $configuration->delete(); + } else { + $type_visibility = + PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY; - $type_visibility = - PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY; + $xactions = array(); + $xactions[] = id(new PhabricatorProfilePanelConfigurationTransaction()) + ->setTransactionType($type_visibility) + ->setNewValue($new_value); + + $editor = id(new PhabricatorProfilePanelEditor()) + ->setContentSourceFromRequest($request) + ->setActor($viewer) + ->setContinueOnMissingFields(true) + ->setContinueOnNoEffect(true) + ->applyTransactions($configuration, $xactions); + } + + return id(new AphrontRedirectResponse()) + ->setURI($this->getConfigureURI()); + } + + return $controller->newDialog() + ->setTitle($title) + ->appendParagraph($body) + ->addCancelButton($this->getConfigureURI()) + ->addSubmitButton($button); + } + + private function buildPanelDefaultContent( + PhabricatorProfilePanelConfiguration $configuration, + array $panels) { + + $controller = $this->getController(); + $request = $controller->getRequest(); + $viewer = $this->getViewer(); + + PhabricatorPolicyFilter::requireCapability( + $viewer, + $configuration, + PhabricatorPolicyCapability::CAN_EDIT); + + $done_uri = $this->getConfigureURI(); + + if (!$configuration->canMakeDefault()) { + return $controller->newDialog() + ->setTitle(pht('Not Defaultable')) + ->appendParagraph( + pht( + 'This item can not be set as the default item. This is usually '. + 'because the item has no page of its own, or links to an '. + 'external page.')) + ->addCancelButton($done_uri); + } + + if ($configuration->isDefault()) { + return $controller->newDialog() + ->setTitle(pht('Already Default')) + ->appendParagraph( + pht( + 'This item is already set as the default item for this menu.')) + ->addCancelButton($done_uri); + } + + $type_visibility = + PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY; + + $v_visible = PhabricatorProfilePanelConfiguration::VISIBILITY_VISIBLE; + $v_default = PhabricatorProfilePanelConfiguration::VISIBILITY_DEFAULT; + + if ($request->isFormPost()) { + // First, mark any existing default panels as merely visible. + foreach ($panels as $panel) { + if (!$panel->isDefault()) { + continue; + } + + $xactions = array(); + + $xactions[] = id(new PhabricatorProfilePanelConfigurationTransaction()) + ->setTransactionType($type_visibility) + ->setNewValue($v_visible); + + $editor = id(new PhabricatorProfilePanelEditor()) + ->setContentSourceFromRequest($request) + ->setActor($viewer) + ->setContinueOnMissingFields(true) + ->setContinueOnNoEffect(true) + ->applyTransactions($panel, $xactions); + } + + // Now, make this panel the default. $xactions = array(); $xactions[] = id(new PhabricatorProfilePanelConfigurationTransaction()) ->setTransactionType($type_visibility) - ->setNewValue($v_visibility); + ->setNewValue($v_default); $editor = id(new PhabricatorProfilePanelEditor()) ->setContentSourceFromRequest($request) @@ -728,25 +929,17 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { ->applyTransactions($configuration, $xactions); return id(new AphrontRedirectResponse()) - ->setURI($this->getConfigureURI()); + ->setURI($done_uri); } - $map = PhabricatorProfilePanelConfiguration::getVisibilityNameMap(); - - $form = id(new AphrontFormView()) - ->setUser($viewer) - ->appendControl( - id(new AphrontFormSelectControl()) - ->setName('visibility') - ->setLabel(pht('Visibility')) - ->setValue($v_visibility) - ->setOptions($map)); - return $controller->newDialog() - ->setTitle(pht('Change Item Visibility')) - ->appendForm($form) - ->addCancelButton($this->getConfigureURI()) - ->addSubmitButton(pht('Save Changes')); + ->setTitle(pht('Make Default')) + ->appendParagraph( + pht( + 'Set this item as the default for this menu? Users arriving on '. + 'this page will be shown the content of this item by default.')) + ->addCancelButton($done_uri) + ->addSubmitButton(pht('Make Default')); } protected function newPanel() { diff --git a/src/applications/search/profilepanel/PhabricatorProfilePanel.php b/src/applications/search/profilepanel/PhabricatorProfilePanel.php index 43637a6678..49159dbf8d 100644 --- a/src/applications/search/profilepanel/PhabricatorProfilePanel.php +++ b/src/applications/search/profilepanel/PhabricatorProfilePanel.php @@ -30,6 +30,11 @@ abstract class PhabricatorProfilePanel extends Phobject { return false; } + public function canMakeDefault( + PhabricatorProfilePanelConfiguration $config) { + return false; + } + public function setViewer(PhabricatorUser $viewer) { $this->viewer = $viewer; return $this; diff --git a/src/applications/search/storage/PhabricatorProfilePanelConfiguration.php b/src/applications/search/storage/PhabricatorProfilePanelConfiguration.php index a4813592f6..127ce6b688 100644 --- a/src/applications/search/storage/PhabricatorProfilePanelConfiguration.php +++ b/src/applications/search/storage/PhabricatorProfilePanelConfiguration.php @@ -17,6 +17,7 @@ final class PhabricatorProfilePanelConfiguration private $profileObject = self::ATTACHABLE; private $panel = self::ATTACHABLE; + const VISIBILITY_DEFAULT = 'default'; const VISIBILITY_VISIBLE = 'visible'; const VISIBILITY_DISABLED = 'disabled'; @@ -56,13 +57,6 @@ final class PhabricatorProfilePanelConfiguration ) + parent::getConfiguration(); } - public static function getVisibilityNameMap() { - return array( - self::VISIBILITY_VISIBLE => pht('Visible'), - self::VISIBILITY_DISABLED => pht('Disabled'), - ); - } - public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorProfilePanelPHIDType::TYPECONST); @@ -107,6 +101,10 @@ final class PhabricatorProfilePanelConfiguration return $this->getPanel()->getDisplayName($this); } + public function canMakeDefault() { + return $this->getPanel()->canMakeDefault($this); + } + public function getSortKey() { $order = $this->getPanelOrder(); if ($order === null) { @@ -125,6 +123,10 @@ final class PhabricatorProfilePanelConfiguration return ($this->getVisibility() === self::VISIBILITY_DISABLED); } + public function isDefault() { + return ($this->getVisibility() === self::VISIBILITY_DEFAULT); + } + /* -( PhabricatorPolicyInterface )----------------------------------------- */ From df4b484a5f78adddda17f13e66eef6aebada202a Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 22 Jan 2016 06:49:33 -0800 Subject: [PATCH 61/66] Write documentation for profile menus Summary: Ref T10054. This is all pretty straightforward. Also include some project-specific examples in the project documentation. Test Plan: Read documentation. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15090 --- .../PhabricatorProjectProfilePanelEngine.php | 12 -- .../engine/PhabricatorProfilePanelEngine.php | 8 +- src/docs/user/userguide/profile_menu.diviner | 143 ++++++++++++++++++ src/docs/user/userguide/projects.diviner | 42 +++++ 4 files changed, 191 insertions(+), 14 deletions(-) create mode 100644 src/docs/user/userguide/profile_menu.diviner diff --git a/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php b/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php index f88faa15c4..d37178ef7a 100644 --- a/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php +++ b/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php @@ -20,18 +20,6 @@ final class PhabricatorProjectProfilePanelEngine ->setBuiltinKey(PhabricatorProject::PANEL_WORKBOARD) ->setPanelKey(PhabricatorProjectWorkboardProfilePanel::PANELKEY); - // TODO: This is temporary. - $uri = urisprintf( - '/maniphest/?statuses=open()&projects=%s#R', - $object->getPHID()); - - $panels[] = $this->newPanel() - ->setBuiltinKey('tasks') - ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) - ->setPanelProperty('icon', 'maniphest') - ->setPanelProperty('name', pht('Open Tasks')) - ->setPanelProperty('uri', $uri); - $panels[] = $this->newPanel() ->setBuiltinKey(PhabricatorProject::PANEL_MEMBERS) ->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY); diff --git a/src/applications/search/engine/PhabricatorProfilePanelEngine.php b/src/applications/search/engine/PhabricatorProfilePanelEngine.php index ea4cefce56..e0f86766a1 100644 --- a/src/applications/search/engine/PhabricatorProfilePanelEngine.php +++ b/src/applications/search/engine/PhabricatorProfilePanelEngine.php @@ -630,7 +630,7 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { if ($panel->isDisabled()) { $hide_icon = 'fa-plus'; - $hide_text = pht('Show'); + $hide_text = pht('Enable'); } else if ($panel->getBuiltinKey() !== null) { $hide_icon = 'fa-times'; $hide_text = pht('Disable'); @@ -683,10 +683,14 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { ->setLabel(true) ->setName(pht('Documentation'))); + $doc_link = PhabricatorEnv::getDoclink('Profile Menu User Guide'); + $doc_name = pht('Profile Menu User Guide'); + $action_view->addAction( id(new PhabricatorActionView()) ->setIcon('fa-book') - ->setName(pht('TODO: Write Documentation'))); + ->setHref($doc_link) + ->setName($doc_name)); $action_button = id(new PHUIButtonView()) ->setTag('a') diff --git a/src/docs/user/userguide/profile_menu.diviner b/src/docs/user/userguide/profile_menu.diviner new file mode 100644 index 0000000000..51912dd860 --- /dev/null +++ b/src/docs/user/userguide/profile_menu.diviner @@ -0,0 +1,143 @@ +@title Profile Menu User Guide +@group userguide + +Master profile menus for projects and other objects. + +Overview +======== + +Some objects, like projects, have customizable menus called "profile menus". +This guide discusses how to add, remove, reorder, configure and extend these +menus. + + +Supported Applications +====================== + +These applications currently support profile menus: + +| Application | Support | +|-----|-----| +| Projects | Full | +| People | //Read-Only// | + + +Collapsing and Expanding +======================== + +To collapse a full-width profile menu, click +{nav icon="angle-left", name="Collapse"}. To expand a narrow menu, click +{nav icon="angle-right", name="Expand"}. + +If you're logged in, this setting is sticky, and all menus will respect your +preference. + + +Editing Menus +============= + +You can only edit an object's menu if you can edit the object. For example, you +must have permission to edit a project in order to reconfigure the menu for the +project. + +To edit a menu, click {nav icon="pencil", name="Edit Menu"}. This brings you to +the menu configuration interface which allows you to add and remove items, +reorder the menu, edit existing items, and choose a default item. + +Menus are comprised of a list of items. Some of the items are builtin +(for example, projects have builtin "Profile", "Workboard" and "Members" +items). You can also add custom items. Builtin and custom items mostly +behave in similar ways, but there are a few exceptions (for example, you can +not completely delete builtin items). + + +Adding Items +============ + +To add new items to a menu, use {nav icon="cog", name="Configure Menu"} and +choose a type of item to add. See below for more details on available items. + +You can also find a link to this documentation in the same menu, if you want +to reference it later. + + +Reordering Items +================ + +To reorder items, drag and drop them to the desired position. Your changes +will be reflected in the item ordering in the menu. + + +Setting a Default +================= + +The default item controls what content is shown when a user browses to the +object's main page. For example, the default item for a project controls where +the user ends up when they click a link to the project from another +application. + +To choose a default item, click {nav icon="thumb-tack", name="Make Default"}. +Not all kinds of items can be set as the default item. For example, you can not +set a separator line as a default because the item can't be selected and has no +content. + +If no default is explicitly selected, or a default is deleted or disabled, the +first item which is eligible to be a default is used as the default item. + + +Removing Items +============== + +To remove items, click the {nav icon="times", name="Delete"} action. + +Builtin items can not be deleted and have a +{nav icon="times", name="Disable"} action instead, which will hide them but +not delete them. You an re-enable a disabled item with the +{nav icon="plus', name="Enable"} action. + +Removing or hiding an item does not disable the underlying functionality. +For example, if you hide the "Members" item for a project, that just removes +it from the menu. The project still has members, and users can still navigate +to the members page by following a link to it from elsewhere in the application +or entering the URI manually. + + +Editing Items +============= + +To edit an item, click the name of the item. This will show you available +configuration for the item and allow you to edit it. + +Which properties are editable depends on what sort of item you are editing. +Most items can be renamed, and some items have more settings available. For +example, when editing a link, you can choose the link target and select an +icon for the item. + +A few items have no configuration. For example, visual separator lines are +purely cosmetic and have no available settings. + + +Available Items +=============== + +When you add items, you can choose between different types of items to add. +Which item types are available depends on what sort of object you are editing +the menu for, but most objects support these items: + + - {icon link} **Link**: Allows you to create an item which links to + somewhere else in Phabricator, or to an external site. + - {icon minus} **Divider**: Adds a visual separator to the menu. This is + purely cosmetic. + - {icon coffee} **Motivator**: Motivate your employees with inspirational + quotes. A new quote every day! + +To learn more about how an item works, try adding it. You can always delete +it later if it doesn't do what you wanted. + + +Writing New Item Types +====================== + +IMPORTANT: This feature is not stable, and the API is subject to change. + +To add new types of items, subclass @{class:PhabricatorProfilePanel}. diff --git a/src/docs/user/userguide/projects.diviner b/src/docs/user/userguide/projects.diviner index 77bc3523c7..17e8473131 100644 --- a/src/docs/user/userguide/projects.diviner +++ b/src/docs/user/userguide/projects.diviner @@ -51,3 +51,45 @@ complicated by members and watchers. If you'd like to receive edit notifications for a project, you can write a Herald rule to keep you in the loop. + + +Customizing Menus +================= + +Projects support profile menus, which are customizable. For full details on +managing and customizing profile menus, see @{article:Profile Menu User Guide}. + +Here are some examples of common ways to customize project profile menus that +may be useful: + +**Link to Tasks or Repositories**: You can add a menu item for "Open Tasks" or +"Active Repositories" for a project by running the search in the appropriate +application, then adding a link to the search results to the menu. + +This can let you quickly jump from a project screen to related tasks, +revisions, repositories, or other objects. + +For more details on how to use search and manage queries, see +@{article:Search User Guide}. + +**New Task Button**: To let users easily make a new task that is tagged with +the current project, add a link to the "New Task" form with the project +prefilled, or to a custom form with appropriate defaults. + +For information on customizing and prefilling forms, see +@{article:User Guide: Customizing Forms}. + +**Link to Wiki Pages**: You can add links to relevant wiki pages or other +documentation to the menu to make it easy to find and access. You could also +link to a Conpherence if you have a chatroom for a project. + +**Link to External Resources**: You can link to external resources outside +of Phabricator if you have other pages which are relevant to a project. + +**Set Workboard as Default**: For projects that are mostly used to organize +tasks, change the default item to the workboard instead of the profile to get +to the workboard view more easily. + +**Hide Unused Items**: If you have a project which you don't expect to have +members or won't have a workboard, you can hide these items to streamline the +menu. From b64d67f47afc9543c004c1e8978425181f451666 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 22 Jan 2016 07:15:03 -0800 Subject: [PATCH 62/66] Frame workboard empty/create states inside profile menu Summary: Ref T10054. Uncreated workboards feel a little awkward right now because you lose the menu. Instead, keep the menu. I also plan to: - add a "[X] Make the workboard the default view for this project." checkbox; and - resolve T6961. ...which will touch this workflow, so modernize/straighten it out. Test Plan: Viewed workboard, no access state, empty state. Created empty board, imported board. {F1066973} Reviewers: chad Reviewed By: chad Maniphest Tasks: T6961, T10054 Differential Revision: https://secure.phabricator.com/D15091 --- .../PhabricatorProjectBoardViewController.php | 249 ++++++++++-------- 1 file changed, 143 insertions(+), 106 deletions(-) diff --git a/src/applications/project/controller/PhabricatorProjectBoardViewController.php b/src/applications/project/controller/PhabricatorProjectBoardViewController.php index 1b2d9d65e2..f2556222e7 100644 --- a/src/applications/project/controller/PhabricatorProjectBoardViewController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardViewController.php @@ -19,50 +19,16 @@ final class PhabricatorProjectBoardViewController public function handleRequest(AphrontRequest $request) { $viewer = $request->getUser(); - $id = $request->getURIData('id'); - $show_hidden = $request->getBool('hidden'); - $this->showHidden = $show_hidden; - - $project = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->needImages(true); - $id = $request->getURIData('id'); - $slug = $request->getURIData('slug'); - if ($slug) { - $project->withSlugs(array($slug)); - } else { - $project->withIDs(array($id)); - } - $project = $project->executeOne(); - if (!$project) { - return new Aphront404Response(); + $response = $this->loadProject(); + if ($response) { + return $response; } - $this->setProject($project); - $this->id = $project->getID(); + $project = $this->getProject(); - $sort_key = $request->getStr('order'); - switch ($sort_key) { - case PhabricatorProjectColumn::ORDER_NATURAL: - case PhabricatorProjectColumn::ORDER_PRIORITY: - break; - default: - $sort_key = PhabricatorProjectColumn::DEFAULT_ORDER; - break; - } - $this->sortKey = $sort_key; - - $column_query = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withProjectPHIDs(array($project->getPHID())); - if (!$show_hidden) { - $column_query->withStatuses( - array(PhabricatorProjectColumn::STATUS_ACTIVE)); - } - - $columns = $column_query->execute(); - $columns = mpull($columns, null, 'getSequence'); + $this->readRequestState(); + $columns = $this->loadColumns($project); // TODO: Expand the checks here if we add the ability // to hide the Backlog column @@ -72,32 +38,31 @@ final class PhabricatorProjectBoardViewController $project, PhabricatorPolicyCapability::CAN_EDIT); if (!$can_edit) { - return $this->noAccessDialog($project); + $content = $this->buildNoAccessContent($project); + } else { + $content = $this->buildInitializeContent($project); } - switch ($request->getStr('initialize-type')) { - case 'backlog-only': - $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); - $column = PhabricatorProjectColumn::initializeNewColumn($viewer) - ->setSequence(0) - ->setProperty('isDefault', true) - ->setProjectPHID($project->getPHID()) - ->save(); - $column->attachProject($project); - $columns[0] = $column; - unset($unguarded); - break; - case 'import': - return id(new AphrontRedirectResponse()) - ->setURI( - $this->getApplicationURI('board/'.$project->getID().'/import/')); - break; - default: - return $this->initializeWorkboardDialog($project); - break; - } - } - ksort($columns); + if ($content instanceof AphrontResponse) { + return $content; + } + + $nav = $this->getProfileMenu(); + $nav->selectFilter(PhabricatorProject::PANEL_WORKBOARD); + + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb(pht('Workboard')); + + return $this->newPage() + ->setTitle( + array( + pht('Workboard'), + $project->getName(), + )) + ->setNavigation($nav) + ->setCrumbs($crumbs) + ->appendChild($content); + } $board_uri = $this->getApplicationURI('board/'.$project->getID().'/'); @@ -350,7 +315,7 @@ final class PhabricatorProjectBoardViewController $sort_menu = $this->buildSortMenu( $viewer, - $sort_key); + $this->sortKey); $filter_menu = $this->buildFilterMenu( $viewer, @@ -358,7 +323,7 @@ final class PhabricatorProjectBoardViewController $engine, $query_key); - $manage_menu = $this->buildManageMenu($project, $show_hidden); + $manage_menu = $this->buildManageMenu($project, $this->showHidden); $header_link = phutil_tag( 'a', @@ -402,6 +367,44 @@ final class PhabricatorProjectBoardViewController )); } + private function readRequestState() { + $request = $this->getRequest(); + $project = $this->getProject(); + + $this->showHidden = $request->getBool('hidden'); + $this->id = $project->getID(); + + $sort_key = $request->getStr('order'); + switch ($sort_key) { + case PhabricatorProjectColumn::ORDER_NATURAL: + case PhabricatorProjectColumn::ORDER_PRIORITY: + break; + default: + $sort_key = PhabricatorProjectColumn::DEFAULT_ORDER; + break; + } + $this->sortKey = $sort_key; + } + + private function loadColumns(PhabricatorProject $project) { + $viewer = $this->getViewer(); + + $column_query = id(new PhabricatorProjectColumnQuery()) + ->setViewer($viewer) + ->withProjectPHIDs(array($project->getPHID())); + + if (!$this->showHidden) { + $column_query->withStatuses( + array(PhabricatorProjectColumn::STATUS_ACTIVE)); + } + + $columns = $column_query->execute(); + $columns = mpull($columns, null, 'getSequence'); + ksort($columns); + + return $columns; + } + private function buildSortMenu( PhabricatorUser $viewer, $sort_key) { @@ -697,46 +700,6 @@ final class PhabricatorProjectBoardViewController return $column_button; } - private function initializeWorkboardDialog(PhabricatorProject $project) { - - $instructions = pht('This workboard has not been setup yet.'); - $new_selector = id(new AphrontFormRadioButtonControl()) - ->setName('initialize-type') - ->setValue('backlog-only') - ->addButton( - 'backlog-only', - pht('New Empty Board'), - pht('Create a new board with just a backlog column.')) - ->addButton( - 'import', - pht('Import Columns'), - pht('Import board columns from another project.')); - - - $cancel_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); - - return $this->newDialog() - ->setTitle(pht('New Workboard')) - ->addSubmitButton('Continue') - ->addCancelButton($cancel_uri) - ->appendParagraph($instructions) - ->appendChild($new_selector); - } - - private function noAccessDialog(PhabricatorProject $project) { - - $instructions = pht('This workboard has not been setup yet.'); - - $dialog = id(new AphrontDialogView()) - ->setUser($this->getRequest()->getUser()) - ->setTitle(pht('No Workboard')) - ->addCancelButton($this->getApplicationURI('view/'.$project->getID().'/')) - ->appendParagraph($instructions); - - return id(new AphrontDialogResponse()) - ->setDialog($dialog); - } - /** * Add current state parameters (like order and the visibility of hidden @@ -785,4 +748,78 @@ final class PhabricatorProjectBoardViewController return $create_uri; } + + private function buildInitializeContent(PhabricatorProject $project) { + $request = $this->getRequest(); + $viewer = $this->getViewer(); + + $type = $request->getStr('initialize-type'); + + $id = $project->getID(); + + $profile_uri = $this->getApplicationURI("profile/{$id}/"); + $board_uri = $this->getApplicationURI("board/{$id}/"); + $import_uri = $this->getApplicationURI("board/{$id}/import/"); + + switch ($type) { + case 'backlog-only': + $column = PhabricatorProjectColumn::initializeNewColumn($viewer) + ->setSequence(0) + ->setProperty('isDefault', true) + ->setProjectPHID($project->getPHID()) + ->save(); + + return id(new AphrontRedirectResponse()) + ->setURI($board_uri); + case 'import': + return id(new AphrontRedirectResponse()) + ->setURI($import_uri); + } + + $new_selector = id(new AphrontFormRadioButtonControl()) + ->setName('initialize-type') + ->setValue('backlog-only') + ->addButton( + 'backlog-only', + pht('New Empty Board'), + pht('Create a new board with just a backlog column.')) + ->addButton( + 'import', + pht('Import Columns'), + pht('Import board columns from another project.')); + + $form = id(new AphrontFormView()) + ->setUser($viewer) + ->appendRemarkupInstructions( + pht('The workboard for this project has not been created yet.')) + ->appendControl($new_selector) + ->appendControl( + id(new AphrontFormSubmitControl()) + ->addCancelButton($profile_uri) + ->setValue(pht('Create Workboard'))); + + $box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Create Workboard')) + ->setForm($form); + + return $box; + } + + private function buildNoAccessContent(PhabricatorProject $project) { + $viewer = $this->getViewer(); + + $id = $project->getID(); + + $profile_uri = $this->getApplicationURI("profile/{$id}/"); + + return $this->newDialog() + ->setTitle(pht('Unable to Create Workboard')) + ->appendParagraph( + pht( + 'The workboard for this project has not been created yet, '. + 'but you do not have permission to create it. Only users '. + 'who can edit this project can create a workboard for it.')) + ->addCancelButton($profile_uri); + } + } From 9f56a014e2a8604b232ebbac794d4a0adc811187 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 22 Jan 2016 07:40:11 -0800 Subject: [PATCH 63/66] Migrate existing projects to retain "Workboard" as default item Summary: Ref T10054. Ref T6961. - Existing projects with workboards had "Workboard" as the default menu item. Retain this behavior. - Populate the recently-added `hasWorkboard` flag so we can do a couple of things a little faster (see T6961). Test Plan: - Ran migration. - Verified a bunch of projects looked sensible/correct after the migration. - Created a workboard, verified `hasWorkboard` got set properly. Reviewers: chad Reviewed By: chad Maniphest Tasks: T6961, T10054 Differential Revision: https://secure.phabricator.com/D15093 --- .../20160122.project.1.boarddefault.php | 60 +++++++++++++++++++ ...habricatorProjectBoardImportController.php | 3 + .../PhabricatorProjectBoardViewController.php | 2 + ...habricatorProjectWorkboardProfilePanel.php | 13 +--- 4 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 resources/sql/autopatches/20160122.project.1.boarddefault.php diff --git a/resources/sql/autopatches/20160122.project.1.boarddefault.php b/resources/sql/autopatches/20160122.project.1.boarddefault.php new file mode 100644 index 0000000000..8765184629 --- /dev/null +++ b/resources/sql/autopatches/20160122.project.1.boarddefault.php @@ -0,0 +1,60 @@ +establishConnection('w'); + +$panel_table = id(new PhabricatorProfilePanelConfiguration()); +$panel_conn = $panel_table->establishConnection('w'); + +foreach (new LiskMigrationIterator($project_table) as $project) { + $columns = queryfx_all( + $conn_w, + 'SELECT * FROM %T WHERE projectPHID = %s', + id(new PhabricatorProjectColumn())->getTableName(), + $project->getPHID()); + + // This project has no columns, so we don't need to change anything. + if (!$columns) { + continue; + } + + // This project has columns, so set its workboard flag. + queryfx( + $conn_w, + 'UPDATE %T SET hasWorkboard = 1 WHERE id = %d', + $project->getTableName(), + $project->getID()); + + // Try to set the default menu item to "Workboard". + $config = queryfx_all( + $panel_conn, + 'SELECT * FROM %T WHERE profilePHID = %s', + $panel_table->getTableName(), + $project->getPHID()); + + // There are already some settings, so don't touch them. + if ($config) { + continue; + } + + queryfx( + $panel_conn, + 'INSERT INTO %T + (phid, profilePHID, panelKey, builtinKey, visibility, panelProperties, + panelOrder, dateCreated, dateModified) + VALUES (%s, %s, %s, %s, %s, %s, %d, %d, %d)', + $panel_table->getTableName(), + $panel_table->generatePHID(), + $project->getPHID(), + PhabricatorProjectWorkboardProfilePanel::PANELKEY, + PhabricatorProject::PANEL_WORKBOARD, + PhabricatorProfilePanelConfiguration::VISIBILITY_DEFAULT, + '{}', + 2, + PhabricatorTime::getNow(), + PhabricatorTime::getNow()); +} diff --git a/src/applications/project/controller/PhabricatorProjectBoardImportController.php b/src/applications/project/controller/PhabricatorProjectBoardImportController.php index 46877b9e14..8df4e8b810 100644 --- a/src/applications/project/controller/PhabricatorProjectBoardImportController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardImportController.php @@ -57,6 +57,9 @@ final class PhabricatorProjectBoardImportController ->setProperties($import_column->getProperties()) ->save(); } + + $project->setHasWorkboard(1)->save(); + $table->saveTransaction(); return id(new AphrontRedirectResponse())->setURI($board_uri); diff --git a/src/applications/project/controller/PhabricatorProjectBoardViewController.php b/src/applications/project/controller/PhabricatorProjectBoardViewController.php index f2556222e7..e993c1b85b 100644 --- a/src/applications/project/controller/PhabricatorProjectBoardViewController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardViewController.php @@ -769,6 +769,8 @@ final class PhabricatorProjectBoardViewController ->setProjectPHID($project->getPHID()) ->save(); + $project->setHasWorkboard(1)->save(); + return id(new AphrontRedirectResponse()) ->setURI($board_uri); case 'import': diff --git a/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php b/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php index f8b2abfc2f..9bf28cdb31 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php +++ b/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php @@ -52,15 +52,7 @@ final class PhabricatorProjectWorkboardProfilePanel $project = $config->getProfileObject(); - $columns = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withProjectPHIDs(array($project->getPHID())) - ->execute(); - if ($columns) { - $icon = 'fa-columns'; - } else { - $icon = 'fa-columns grey'; - } + $has_workboard = $project->getHasWorkboard(); $id = $project->getID(); $href = "/project/board/{$id}/"; @@ -69,7 +61,8 @@ final class PhabricatorProjectWorkboardProfilePanel $item = $this->newItem() ->setHref($href) ->setName($name) - ->setIcon($icon); + ->setDisabled(!$has_workboard) + ->setIcon('fa-columns'); return array( $item, From b1f3e02d82133319afe999df4855634b20f0b09e Mon Sep 17 00:00:00 2001 From: Sbastien Santoro Date: Fri, 22 Jan 2016 20:19:46 +0000 Subject: [PATCH 64/66] Fixed typo in PhabricatorMotivatorProfilePanel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: racooons → racoons Test Plan: Read again the sentence. Reviewers: #blessed_reviewers, chad Reviewed By: #blessed_reviewers, chad Subscribers: epriestley Differential Revision: https://secure.phabricator.com/D15094 --- .../search/profilepanel/PhabricatorMotivatorProfilePanel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php b/src/applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php index bee5843f75..73668fdd41 100644 --- a/src/applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php +++ b/src/applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php @@ -124,7 +124,7 @@ final class PhabricatorMotivatorProfilePanel pht( 'Not all cats can retract their claws, but most of them can.'), pht( - 'In the wild, cats and racooons sometimes hunt together in packs.'), + 'In the wild, cats and racoons sometimes hunt together in packs.'), pht( 'The Spanish word for cat is "cato". The biggest cat is called '. '"el cato".'), From 66ef506808ddc1ecf7b78b7a8ea4d682563f2b09 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 22 Jan 2016 17:26:46 -0800 Subject: [PATCH 65/66] Redirect to profile after watching a project, not default page Summary: Ref T10054. Test Plan: watched project o_O Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15095 --- .../project/controller/PhabricatorProjectWatchController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/project/controller/PhabricatorProjectWatchController.php b/src/applications/project/controller/PhabricatorProjectWatchController.php index 263c508441..9624a0b730 100644 --- a/src/applications/project/controller/PhabricatorProjectWatchController.php +++ b/src/applications/project/controller/PhabricatorProjectWatchController.php @@ -20,7 +20,7 @@ final class PhabricatorProjectWatchController $via = $request->getStr('via'); if ($via == 'profile') { - $done_uri = $project->getURI(); + $done_uri = "/project/profile/{$id}/"; } else { $done_uri = "/project/members/{$id}/"; } From 0b67e89904c3a5e9e51fabc4e1ccc0a88a8c6304 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 22 Jan 2016 07:36:56 -0800 Subject: [PATCH 66/66] Add a "make the workboard the default view" checkbox when creating a workboard Summary: Ref T10054. Since we no longer have the "workboard default if it exists" rule, provide a quick way to make it the default. Test Plan: Created a new workboard with the box checked, saw menu change appropriately. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15092 --- .../PhabricatorProjectBoardViewController.php | 24 +++- .../PhabricatorProjectController.php | 1 + .../engine/PhabricatorProfilePanelEngine.php | 106 ++++++++++++------ 3 files changed, 91 insertions(+), 40 deletions(-) diff --git a/src/applications/project/controller/PhabricatorProjectBoardViewController.php b/src/applications/project/controller/PhabricatorProjectBoardViewController.php index e993c1b85b..9b7b76e62c 100644 --- a/src/applications/project/controller/PhabricatorProjectBoardViewController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardViewController.php @@ -761,8 +761,15 @@ final class PhabricatorProjectBoardViewController $board_uri = $this->getApplicationURI("board/{$id}/"); $import_uri = $this->getApplicationURI("board/{$id}/import/"); - switch ($type) { - case 'backlog-only': + $set_default = $request->getBool('default'); + if ($set_default) { + $this + ->getProfilePanelEngine() + ->adjustDefault(PhabricatorProject::PANEL_WORKBOARD); + } + + if ($request->isFormPost()) { + if ($type == 'backlog-only') { $column = PhabricatorProjectColumn::initializeNewColumn($viewer) ->setSequence(0) ->setProperty('isDefault', true) @@ -773,12 +780,14 @@ final class PhabricatorProjectBoardViewController return id(new AphrontRedirectResponse()) ->setURI($board_uri); - case 'import': + } else { return id(new AphrontRedirectResponse()) ->setURI($import_uri); + } } $new_selector = id(new AphrontFormRadioButtonControl()) + ->setLabel(pht('Columns')) ->setName('initialize-type') ->setValue('backlog-only') ->addButton( @@ -790,11 +799,20 @@ final class PhabricatorProjectBoardViewController pht('Import Columns'), pht('Import board columns from another project.')); + $default_checkbox = id(new AphrontFormCheckboxControl()) + ->setLabel(pht('Make Default')) + ->addCheckbox( + 'default', + 1, + pht('Make the workboard the default view for this project.'), + true); + $form = id(new AphrontFormView()) ->setUser($viewer) ->appendRemarkupInstructions( pht('The workboard for this project has not been created yet.')) ->appendControl($new_selector) + ->appendControl($default_checkbox) ->appendControl( id(new AphrontFormSubmitControl()) ->addCancelButton($profile_uri) diff --git a/src/applications/project/controller/PhabricatorProjectController.php b/src/applications/project/controller/PhabricatorProjectController.php index ebb3b31a2a..8687e0a3a7 100644 --- a/src/applications/project/controller/PhabricatorProjectController.php +++ b/src/applications/project/controller/PhabricatorProjectController.php @@ -133,6 +133,7 @@ abstract class PhabricatorProjectController extends PhabricatorController { if ($project) { $engine = id(new PhabricatorProjectProfilePanelEngine()) ->setViewer($viewer) + ->setController($this) ->setProfileObject($project); $this->profilePanelEngine = $engine; } diff --git a/src/applications/search/engine/PhabricatorProfilePanelEngine.php b/src/applications/search/engine/PhabricatorProfilePanelEngine.php index e0f86766a1..3622e43976 100644 --- a/src/applications/search/engine/PhabricatorProfilePanelEngine.php +++ b/src/applications/search/engine/PhabricatorProfilePanelEngine.php @@ -891,46 +891,13 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { ->addCancelButton($done_uri); } - $type_visibility = - PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY; - - $v_visible = PhabricatorProfilePanelConfiguration::VISIBILITY_VISIBLE; - $v_default = PhabricatorProfilePanelConfiguration::VISIBILITY_DEFAULT; - if ($request->isFormPost()) { - // First, mark any existing default panels as merely visible. - foreach ($panels as $panel) { - if (!$panel->isDefault()) { - continue; - } - - $xactions = array(); - - $xactions[] = id(new PhabricatorProfilePanelConfigurationTransaction()) - ->setTransactionType($type_visibility) - ->setNewValue($v_visible); - - $editor = id(new PhabricatorProfilePanelEditor()) - ->setContentSourceFromRequest($request) - ->setActor($viewer) - ->setContinueOnMissingFields(true) - ->setContinueOnNoEffect(true) - ->applyTransactions($panel, $xactions); + $key = $configuration->getID(); + if (!$key) { + $key = $configuration->getBuiltinKey(); } - // Now, make this panel the default. - $xactions = array(); - - $xactions[] = id(new PhabricatorProfilePanelConfigurationTransaction()) - ->setTransactionType($type_visibility) - ->setNewValue($v_default); - - $editor = id(new PhabricatorProfilePanelEditor()) - ->setContentSourceFromRequest($request) - ->setActor($viewer) - ->setContinueOnMissingFields(true) - ->setContinueOnNoEffect(true) - ->applyTransactions($configuration, $xactions); + $this->adjustDefault($key); return id(new AphrontRedirectResponse()) ->setURI($done_uri); @@ -950,4 +917,69 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { return PhabricatorProfilePanelConfiguration::initializeNewBuiltin(); } + public function adjustDefault($key) { + $controller = $this->getController(); + $request = $controller->getRequest(); + $viewer = $request->getViewer(); + + $panels = $this->loadPanels(); + + // To adjust the default panel, we first change any existing panels that + // are marked as defaults to "visible", then make the new default panel + // the default. + + $default = array(); + $visible = array(); + + foreach ($panels as $panel) { + $builtin_key = $panel->getBuiltinKey(); + $id = $panel->getID(); + + $is_target = + (($builtin_key !== null) && ($builtin_key === $key)) || + (($id !== null) && ($id === (int)$key)); + + if ($is_target) { + if (!$panel->isDefault()) { + $default[] = $panel; + } + } else { + if ($panel->isDefault()) { + $visible[] = $panel; + } + } + } + + $type_visibility = + PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY; + + $v_visible = PhabricatorProfilePanelConfiguration::VISIBILITY_VISIBLE; + $v_default = PhabricatorProfilePanelConfiguration::VISIBILITY_DEFAULT; + + $apply = array( + array($v_visible, $visible), + array($v_default, $default), + ); + + foreach ($apply as $group) { + list($value, $panels) = $group; + foreach ($panels as $panel) { + $xactions = array(); + + $xactions[] = id(new PhabricatorProfilePanelConfigurationTransaction()) + ->setTransactionType($type_visibility) + ->setNewValue($value); + + $editor = id(new PhabricatorProfilePanelEditor()) + ->setContentSourceFromRequest($request) + ->setActor($viewer) + ->setContinueOnMissingFields(true) + ->setContinueOnNoEffect(true) + ->applyTransactions($panel, $xactions); + } + } + + return $this; + } + }

    e=6Rsq@PT;d^w=1>{ieG25KiSAm#il-<=g)JA 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 diff --git a/resources/sprite/projects_2x/star.png b/resources/sprite/projects_2x/star.png deleted file mode 100644 index 35f8e802b93a0cd4e4136b4f6fe13af2d376d213..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 zcmeGl2{@Hm`xDu>79?qGZL%b#l$|UQ*+M%Nsu7h&%P>?*%Ot6Yh)Q-9rG%11B}CJT zBqSM{p;8I|dHwD@U$?to_eziVd0yXH-u*r2eB1f1eG4s3g!squV;Cl6W@==Ej;jHA zxiO4`ry(vMRrtJ2oi<~bz$ictEaK!C4CA+2YiPJ|p}VKI=Vo_LFBvmKLm974o~~fB1 z)SZ|h&O?X%4~khU3GU~A%2O|U`p~X3LHqA@*6uj7{&7yn>yqxvPjnhn+M_bcc=C7! zkDIDn&-52eG#EeP<*uTF!rFQjy#Rg%FHDp-W3}w&E_n{@lb@E>RJlB!>lnw@hXTA< z-h#-yY2)_xh`cp8v6RDqH%Fd#$ZT_7|IwJ<_Cp5eFg;@q|ETbZwpa`owz7DYOC7dQ z8CyB&kJk?||ENzVc5q-zj>?L0#Drinqt*l&VeWIWl(I$p=V6Z1u+gsO1)A7XWo(+6 zgR3ca;R=>lDk_kU@d{$otb+olU|c(}m3QRjw_>|bV55!O9JKzOnkL$)h$3|&T`NmL zb6&s_UgeEE4h|~gCzqN@OdYM^Jj^*lPbGib3CZaJGelmt-^Z|+5HaL!d)L-d;k43H zjYFBjE0o{f;O>!gajENWC`A6F@7sO^>?BT3u&l>9MpUy8ZSmJ!o!MEEje?^`{*RP-bw7zzHczOMmLcsK8 z0VZ6ZUgqC_ZxJ`H>Z zGUfJ!ik{W4YLq%Tb!ui}7uM-;>9T?V@?RoRB$-JEY?z?Ks ze0tvLcA3OX!2Dg!j%>uRq?E? z1_}lF2BHT1tNq7qS~(?Ur@`bsB^RU>SE~M{Cp{z2+I>%`m#|8{{Z(OYFOe_KywNu& z=LGO^>EGcUOWi4%dJWN(^sjXaC#y3 zgBr1o50c$Qo(Jm~7EQ~0GloaK;MZv?g|`eY&Q{_JT~&NhE=4f8aO{OeDV*8+KCCLc z=)*NKU|t@d2A7Y4jPrPXQ%4I&%crIZGUF6xjCjsBi;r`+b^au|&;;{K6R(Z;^?8$=ssG;ps8pRR9z zCc>sVA=Ylh%;3casj-gi(-$GS_ncdR}C#{1fc>SNlvH8a)9+Og3wM$Gom-He@z`otS*e*D6xvg)SvAw!&T_WFK$CK@o zq82vWO4+(4&P~{xJ!c=c_wp*t8#Y)#a%R-}vdIwRj%;Y^TluVf~`{la@|0aSJXT z9@S|3%(gn7KVE!+_M8uCDoN|(q++v;d~R%rZw-&WzT7|B!ZZHGw%o=q<9t=S?7BR@ z#D6dmbmYzuRN$@@EFGhDd*((@Eos%F%73j5m)+7cjB`Hb99FwKB&%HO%p>DJjYSTw zEnHfsQ0GzTQFvw|_e9x=<_q2~XpOL0kacd#xw#f|Es9F+mz*wnd}3y#w%U{FjggI! zPaGg}xIkjfyYzSPe=@jQ^zj#@OacWfRgvZ&b+3_Rdvn)d` zlcOKI-Ma8^=H1N1E0Px)o^n^FWqM@#I=i_@xLvuOcB?fsH`Mo<@1I@TJVJY)2`5W0 zmiF6xY18OAi{`wDC_UM#>wEkC@g`L_$1>5fr|NZ?ql%{#tc|jbd}!h(;g+>|S9{Qb zedarhRl;;sBBcte@8s6c_x`YPS?%_U4^fdBk@+nNmFHVETGzJjtvYpo#;GaMPU@Q< z+`41<(z>BsSK!pKY3plJ{HzSE0^BY)%B!wY4RJ_)a^XsxPf~~TI|-eSI-5?_>C|b> zdNKWl(~A4E@~+&uQfzh0GkQf}jo}~iJ*#`R_mpGt{u4OdIQIqU2P_%Z`Dy#_vNsOt z&Z%7UG5uMK{=t|meKGyuovAw;Zl=n*-}(D+s%%GNcxg!KTH(Njes3N>;BkKKeBhR! z;H1F4few3g4|xSSjxARUo9Ri$eck4IL? zEe>I6ez_C3FIXS2{N}x#H!pLnZx*oUZwT~lu6ok4%*s*KsphitmpxHZI%50wr;VEx=d4N`kO@7*|2b@WnVazWPWGS>>%rq?f&qn8LDPYQb-CcHuD+4D<6HH$8_ zeE2x8QZ=k(a%J|eOv9`*H?*$itckx{S~6GH?yTK=yDxSctrgXmou7Q#P~IxFBj@9c zzaLdD$?53QxqH3Rp2L2@BiBc3I?XyWI&{QTY6=~D2J;K z5$ETu@ObO}R;xSop;b}#$?S-NRc(vcANnNGI+0T3?wWj7+<*azG*P{Q-uzK$!-6h>sPv2Gju`bUiroFt% zq=P$fS6O$+hhP!I;lU?@i}wiaX^x()qpA5ycT-o>*LcIS)nyZ-CAv>{7pF;xtNML< z)cmBhJiI(MtSv0`hR5%5U2pT6CC^tD<`<5?es`<7+Vb~{I$Lh~RQX81J5wWKRsXxp zACr6BKVSS{`yjqER5CQQhl?}3{p%`q~qs*p_J+ z_I4$P%?Zaa3C|-dZX07*l%koDzTH+1?BX!XE{>iaL`o+Nqm#auoDvh+KC&H1WEVLr zC@}#~5Gh7{AZUpQ2MEDyf`*Z#B=@!TGC=od|a|LcSX1ji75(}p*%mjeA6j_?bi z(s!iF1ik?htbp=2Ok91E@P}^*h#7#8APvt%wagF`<~wXB{iBv{RsG69ay*gKK$4g^ z#y~_sLYxV8IDUdgd?q1-&_N3R%Pz4=|8?NFzG)+7z|oN|l4Ag=1j*l+iT43SKEe?~ zoxlX;ULZA52z?}vf5xT=u=5J-%@mf`*o_d{JB*WX*D#S>tp244{YoFzyC zElPlqnj(r}BNr~bMZ^k##~n|A%Bn>5Z>w+-Lj_TH&ln0c7l8l)Svjs!m{tkDuK zIz^HoujZ5c`182KmYDspO5T#lFU2NC5)U(!;xs4LNN>2V5DTECPOm5Ub%thd==Fpa z!@r}UN6BjXn@{`AUcvK7INVtHkeZQNL!DSKrUQ35-b;AVWdopCzQMZ zooxt3C@H7K6FmP%R3Q$JFrI)^nVJ&xvhF|NLnVQ}8YuenzaDA@awDRzoiMOSjv5@z zslGBvI%=MvheO|mhuCiLN{zS?U#BJUczTA))I4EGC^6H|qXdf`wft|kB!)PKtf;dk zFRU<}Smux;#1WxV*QCOPauQit$h4(Y1h9It3nKmPeKveXN3_j=HNfhO5S#$( zc@TQA#tn30g)=jY-~p0L>WK*PwNAgNXH`aKk#PcyW=Z5&<;Wc>VUDHJPj@#hLrVxr zh3n~oghZs=k&*$lWCSKGjB7xaO;!>{cH;C>bOLy3$p{G@y-hXfuMD|PCfZ?s-J_SE zmW+^-DT_KFOQXmU(9xdRCky1!?F8syCL_R402x$(3^5Ae08_wBM(~Q6aRTHl!3$%g z+#ik{ra^Hl6`HeD`l)vJha;Y3wD_WS7&3%;1V?xW3ab$*C??fNYa6q31Z_(F=0fl^ zs;{6?IXs5>mxvZFGCvTt(NraVOH30}AJJ@dgsa&CgxY;=^c>(MOPJ)csQd!qdt4hT z(hkgKgmz6VrtFV7!eSF?6F=k#ZE<2B)lZWV%wSUP)1ev9zL7(lrk`ef4LL$v!r4bP zlo9sDnl?@B$cP4QrZ7jvj`Ij?J&;D&#hj^>x!I8s*xnFD*$n1;S)CCpWFqWd03h6e z{J+-Ee_8Da{x(t+*-m_0*l+HzdT8NaiX``&)g%P5(vh`9`sNYU`?bo-q18jeQhC${ zH|YHitjq{0W7A1B_D37596=u?k%XxvTl=ArRYQx^up*c{7Zv*bRWBJuasqVFni0G` z=TT)LzJUehkx1q{dgL1(aF$A`wbbbL+cwRRDsv8z)R_TLCiy~ zz6BA;P$MGO&uB*Q@-k4x0^h(u8QybKd)Y`)ETb903tfOJNAV4GmSGWL$_dcd9~l8T zjGW+r4**ssrZ4ULBO|@mF!85f9!&IyBTh^>0jzpV^7pd$$I$u*NfKew7;eN*?j<}; zqWdEw)SRGYBL7K~wG@b$bwr7RZ0K5t5SCWZLuoevT#hgYl)jyyq3x|=PYL_!Jb0idJ#AQ^5Gc-MqL|qWQ1WpEXccM(BlQ25un2UnBp?al6h;Iw;|L@ASjNN59ATMJj0hfbgpsJRl4mF*tc)%rvWGIlNYq%# z^V4Jmv$0IQ_|u#fS($Qn%KmwV7dxZILR~`%VPS9?5j~U;Mxw?-o}q-WFu06}9!dx! zQDY&`P(oN3Tt-CyEC~rl&f}kZG7^g)g6C(r4>3fM%;}4!DLQ8T5Rqljh{2u^czXW^ zA-u`}fX_|g=|1c+8pUPIuYozloK6=`pPi#;3ka##5Zq* znF+r>MYvkxM`hUY3&4kvu!jzgaL)m>%mDmA)LDeE$q)dJ9lfRh?=mLrd;N;qfEEBQ zpW*JG0RIpQ=m_o5573T~@P$6efnCdZT2!SCm`Mm|n1&EOgI0jb5MWg(2KERaFd7TO zNM)2C6i+}1J4)9hWar0YNZk(s;4|zThZsOC7)}P_?YHk zuT==?+1gAs6wEGJ)D);Af)s=@)CdPj|4U>iJU@eP{8$3aE?Lx!DnSHr4*+^LB4p|l z9mGEn05*f|-~;%=vSc9HELpNZE+rU&I!__AqD1rq^j$(WtU%bxPFq;LWKr`)6A>gL zl%__=rv5sl2bQEFHtG9L4Xc-|?-UX>faBv4f*o5B!aV@H0q!5RAp{%1mH|r!(mfzc z7U(4h6{tg*Tqld#;bG-e7Rjbt>_E>DyuqHR!tP{%eno^{Q1}sGpwA(M7>J@mGeW{+ z6hb?@j<8gUBYej$h2-@7C^O_ZGH{@h0kHwyWPg1K2-pQb!VED$&gQbqVJdozQ9rX! zm8qzp-2EfW5O~bO3}hkZaR?<5W-=oP@t$OopK11iP6)j7mSMn)yNG8ZLJowmTd@Hl zY?w1g2yO6?uMi=<0GGYK^fL7){Xi~RV~``S5kdfIfhUM)DZ)}(h;cO2Q28uEdM<6H z5Ixw&b{NPR5`ny>mJGOahI0(i!R0Bv$v`Zl#XBn=pqN!sDlzeOZo<4$%0u4%Yg)Ll)-CHxH%iBld22S zeHft-LIV7a3ScAQH7%i?rAG)3yJ0s{2#&&=wyg-^9su5#4^%RcYAhNd>;Zs%0q{%> zY#WU*2q9a6-3fs$Ip8!eLfE{p4dJ-^LOn)or5H*G gTfn?B_dl$o0OxvqH?d|CMrwIO;Xt+)siK;>U(Yi$znS0m%*->-GtY5!jfp-N`y6%z zLAVSJbj`tWD+DVuf-tbO#N>elo2!BCUIgKo3BiDbpP!8&?55jsxHW5>T-;ptI=Q%t z8sc!Gu6tY@xBs#YLH50fw7^?hw9QiQZRpl93h+K-Ym!<(<#6dS90g-h8gn zn$#7UR?d>c%6ZN}$!w`NXS~k58GjuvDkyx}ET`qeF5!ysvZien+dCl6fb@B(sV$zL z!*Um4*!P5k70Fp0k+Wp3{}9hxov`%`-bWa6+=6~KV)f=nv^-AgTtT$-7`!7x7g`|E zOvvUEhb>LW8d+qshLW(}hJb!gPLXhYn0bp&{ zz`io>l(I6Flj+=>WZ&Ln9-6;pOVeOWd7`Tpg1mI|su+}!Pn+Ytg4x@7@X~?~CZ~-Y z(ZBW{cTDBcx`{-$y|C_bg}zyN@l-}lO-plg^{N6LJNt*$2L|zZn{uoNe)-o+?Ne{h zUw2?uTPBBjZtnED zT#iqhRgUOL6y)jf>acJ1p1WuBqNGDQQhue^M5H&%Kh+XZ&M|ZH3wGs}%d@)8t?tV6 z(VjIbS1QYgjY+$hb*8=8ivWf#$85w;vI>Uz_KD>hF!3Fi5PcB9Z#Lg3XsLmM`7ujT zD+7^E^*z&6{nzW=30hH%C?5Lcm!+?8#wXQG{VC^7Tt?ioIY;y^aXjAYrVt)DD>~xw zo*Q%2PpDjMeVpjT^CD0KSF|MO&1@E>f?t-%73S+)|5=7D*rDY5{3OoA!a3L0CNX9n z?Qtl-?#{&LvoeQGg~?q<)PA0}fsL_^NwqaFL0(juV($GE!+@iJn&pwM+QsxhLtP*PBZBcGv-WIB; zZFM=^ygu%t<&33)>vWPYrkh_i^N*XU{A;*s>ET(1Mls2k&OVvrBrvE174P&=ECzqeV;i3S%lu*QMmf3hA_t{rNjjsqjIWAOWxn!BbyU^A! zo-h|H8|ifE-vxpmvY%abcHvoJX?e@|gewUR2^>~kRwb5!@f$4;r07{GSv1A7Jw2Cb zl@Ph+orSOkK7K`*LU;F_cQavYm5L4N@;cVQ z|9;V{MZ#B2k&F65j|qCuirqW-&Vm6Z0_$Sc_^Gj02QxV4K`Nv@aF#|M^8 zk8HK5v8az_kDawzeR)rcT*A&6;ftBN?)P@Zc7#UV-RK=<>=N6sKfCqg+yn9hmIKZo zV|(;DZJ5(IC75eD%Vw+HU%J~xO+>z^_8&9chI}ntjQv^rke5e-GAh(ASLyws$8%zP z;rb?tCg(!u!pjSp7m6)3TK#r)N4WXwj4O+-tT0|-TvYm~^it`wu%!{|3eOc=BU&S# zM>O8ryl&q*ne@2y+uICNo7Y{j?MTns<-1PRHpa$k-G(&1m;{?7 zMm@vlU;8KhL3;cxp=&MG%(W@$&glp2@mmD(x9+FpcLZk#AGmYij{$WSF8>VLxdCRMnn$l;MEGpO@X%X>6A1{c{*n7Au;P_Fa zLnU${8gdcBh4sbR&8yscc5is;QP~q2krt8H9#?y{L#1PThkxCLN6Hr#McFFteVkv6 z`^&7QLX+dd*(Ez0le|oErat(at>W?y@ zYE8TLiRcV%0qwv;$%k5Ulf|5h|2~y0*4r9d7F4#K+jouEn`e(%>|fg-&-db#^!4|( z_R~D+8elW0LLp?Sdqo{?Z=>!<-E+DP5qJet)vL0rmP%_R$n8*jvFwiW9nC^HN83kL zHjy@lzZlI`m6J|U+4ala#!u~C{;wimaWr`fhRPRjaNU2gEU())c2>L`pUm=eTE+n; zKcD%JHm`KttP=}5XSy#q$-X~NBo9AdzCxuUpc=PcdY(zAf%IyR(|-qLE!{71UnxeW zCF6)>{HZKsF5~)$!hAbv!vp;Sv%eJX()LGb4{J{?JOBQ| zP&;29-^Rss2zedCy^E{n#SN~;wKv*(KCG;j4=I(Z z%{-ir%eZ_`?RM6-*au~$D>NDT_mb6#1^cK@m_%Lm(Ev>kd9jPEQz5qUQ9fS26A zb(?E1rF*tIlr`?)ae04-*X?EH%Aw<}E3#IUt?#_;)|pz{GSm9Db@{WwQJYl>iw%U?FQ?r-`5@7k>eiSRZ*wk%j|o&d@!gdkOwzC zFf6ddkIU~})Xy5Ks;@Nn477cU#g%U@Ul=7gcxkXCMR1n9S6|h;=VcY46&FJ~LxS%) z{~j~&Hs_tt)!M?m!g+Te>{C+M*uA#DJ=eX?UF7}cMjq4V-$f5f4LSXLy~pBlY=5v& zaPSZlV`$eW2PN5BaK9<)U|_x)K|B^9i1%Rx`F98$+Ysc}B?$6%GlDD+MG!%k)0^(= zAxNaOp{};&J_h9aG?M{_p&`JElBS{L|I9uim4ZQ2P+wB`f2E*JMBo8wLNW!3uXu7ijoi-=SDN&g3=hA55Nk$| z&IRYgd<5AI|zB=|YM@RFRhApegQlY>MaCQPP*1QruQkBtAETxT5i zH5QW*Ka+FU2-A2^$O)OSn2;M*#%sVxeR7tJFpc+Q>IgwD&fNGnO#(AspHotwCUK!e zk@50ihK$#P6J4L&8kibc;PE=54WI}h3BU`$0{{s=+=Gwbz_tXW3?S)C8XU$?)OL1X zAlhU6;=gGDJ~841`1no97#Y+U()C5y7)_6>7|xfdh?>sM1tdU0k*Fk%&D;lAz?-4Z zZI8`O#6e9&ia;BxMD0vu685osXd9%)kkJ;aH9+_!fDC|gfI$FK1h#!4>Hup1Yyn7J zMx^op>*zF*hKw!+eFJ6t=S!fNG+qk7xsFXdVYbCD9BJ#en~3v=&hl5!gqdVle=ebV^E$Fa>SF zP7ZmO0iY&oB0@?rm=_Ch4Im%j4FD;Ej#B_I0N4NkU&xap7)4YxQHG!rN&z!!L#Vm5 zDA0rUEc9qdJ2h^g#t;~G_~w#SU!g{a;X1kC1ioqIAI?B^9PeExsILc*3V@bcKm{)V zHUN@$v}p3F>FnCTQ}g?ZR|goMkmd4z;hCM^q_M}F9OWYVrVa)PN@>XK`3(#kMH zCe8Ju2*x5Zien}%8;i)KxqcMEQzjyaxk>VMY96JG;utJ@B0Mm4F0YC31|7741%wWQ zK&S#15JGRz!8sNXItT)x3Rpl0y+H@(SU~6?2!twN0U`7T9h_qUp@Se0sxXn;$qCy< zbIt>pwE*A`LBMV3asb2I(81|a65tU4+$5I+0JpqPI?;NiE&(jw2Ve)lI_cJv zRsik*hFdiQ0N_Sini4Gn0(S=A0MMbSWfLb1?x!^dplVAsS~X}95L*0X5?Z^_@>BK2 z0a_uDpB9sPG&PFRS)B{C(uWoSaR$b)0Kl(};IEneuMpG~>I`*3 zwE#8%D*z_@ZtoM&;XXhdKmtGqz@*S*1!OE^;TM=P0PtH3crNq>!r%x$RN)4Iy&K*# z6B4|2g}<@Z3D6DD0?U}v*2glLqhX}}M#*@k) z0GWRSz+njj{zDc>@Pl$l@C!yr@beisltJ(VFak^jVF8&4FHT?^GzkbTZhI%tCsV&E zS_EVUaN{8WINbcN5!BfSV0bwE?)uYWQYU4E2*|VqFaXd1nCu6Q@PT3;z%2lH7uWk(=s5W)WX&wL|&QffDoxeHi@l6$hwE}!r>u{@*4EXiLFEEGcMm( zD{LJ?-oMy7guH*gTPd~<8N;>MI%Et7ji-2cQpethP~gSMzU{@*g9kk2VuoD@&GO7 z5E_{>HN;>6p|dz*0l@-7XC9z4b+8_S1%%E#KxgV;Jp>B~oq2%H)B#U0hlU)gm}e_I S)6Rps8Ll+ZP0`tW=>GuTQa=Fz diff --git a/resources/sprite/projects_2x/tablet.png b/resources/sprite/projects_2x/tablet.png deleted file mode 100644 index ba08795dbd58c0044f108bcc24f068c41c56ad33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 Bl&k;% diff --git a/resources/sprite/projects_2x/travel.png b/resources/sprite/projects_2x/travel.png deleted file mode 100644 index 828f4d186092a0e5de5eeaedb2fa017b5d3f7787..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/twitter.png b/resources/sprite/projects_2x/twitter.png deleted file mode 100644 index 620b437d86f99c0954525f066c80ad1eea43cf94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/warning.png b/resources/sprite/projects_2x/warning.png deleted file mode 100644 index f07e8a467b04d80964b31f9898a32ef169b83703..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 zcmeG_2|QHW|5s$+DpE<0QY1@7i?UOQ$QD{@F)gpCyr)%EmX?>KBH~erY%NL&g$gA^ zDMhJ})T7_CL<#?M`kT6D?#$e4#!zp*pU>Al_j|tk_nf<&d+*r4z`|HWaFif|AR?wF zM%G}v3L-x*f^hNGL}!B?0XGxJEeIks3?dg2dTIoM2wJW+G+eM?jjOxsmNl+!vZjWH zvTmDQUDp1-8bP)`54R!N+SCo#ZhhHoVCL_2%*@qVl3&)^;Gma8-~=T(0r7eMa#7DD zt+Iy9nZqNU7wOM^_^{U@Nh@XH1A=9I)pDl~?>*yx;C}n-9cR`*NpF2y(0TQ#PHjR{ zcybY6Ccp3r6LqU;Uc%=M#teD2H}_7?>uOa!Z$WuCM4Uf)mE4w&aa>57r?IgA(@5ZLYEPKVPvwEzt2R3X9wbxH*VZkWZy|dVs4|o*1waI#A}s6 zrcPegN|o1~R9HCuaEj=1mG`%JyT-0qQPo*f6z`^oAg|p$i#wIol1F*X=Jndpd3t;U&zfaI zk$PYIdXEoK;W%KSBEOx$czpIm!y*$&t=T3=gR zUfp~n?>%*?w=qxKtLz8O=Fy{zjtcBsQSmmw`0F*HuCFqW#@;bqk?No%QDrrB(_y2~ zLrqho$L=>cI`QuKlCD*6DwW&0btC+~cWx_M`puFroe+jFxW`Wa8rdS`a zm9;aGY1H04NYii0+#7+j^N^`~zWSycPdVm&*-HDd@KwXq*cqet%{?vjaFzR%(178Q zVGlQ78Kr$_dQ|Ph_%&kB19S{?CuhDJ!KZ%b_sOa`w+$}MR2B$YnSW_)f^dA!sEZ2| zxYPExtSq|Z!86o*PNu+g9uEUq=P~*w4(1LPWhSw*qvbV*JQtWDz`f5ZTVZTatl5z^Gh)TmDSi$n%Hy644H%{-zQf<}&J6jX`wgcmq#hY$dg-if$>(`TE4eqjeK-)WUlSx z8B;!l)SeVO>1yYol%lj#GVs3O@p;E59G6y7vppYoF79QVkX@5qzHPwyWj4E#=Gv*- zRGk-id?Ma1E_}fU8)+NT`Ps34aimyRTivssjvf1X9dDc8wlq9z6?tiSReFxB(8`g? zTb1S3i^Ti>;XUongi8g_cK)f97SbV;c2GO+e3Yi4`aE^}Wb3A5F1mbGA)DGxxmyU- zD#ipic^-Hv@p0mtiPGmZ%u}bVUa~&!MDPiRc$0Xmc;gQl)066B!p~*QNpo!X7S+$4 zr?5o9m=sVrIK0;8naztB!I?sm863mX1m@^0>7zrXeKa<}$AcbJv)c+cIju zjNYZzVcW6cOH7Ngumf+husm!31he_?=Qo5}&rdx!@!V|l+2*+g4+>5fJUKZn zOnb`HskLFXVNb&F?CZ_2%t^VddRtSRFyPfFR4vdfvYLW*?lZqn_Bpp2khH+KEi zq0J}a_e?ZiW|55NmMfbjW-XlcGPLkigYK@o%_r*ANDf8fMP=$$DZ}z7-dP)N6ZXiM zBt=TyvbV|q;C{0``KrM>s$tSOFY+>~=ef6RTKal>NlSQGa#(hKZ25(T=?!Ze{3`x_ zpz-&_2uJlT4{zrgzOt$*))o5u_~iAK37(dQmfobRwd2%Qss-97KD~G?+9R&j`J

  • ua8=ycIaUDc@YB(mJSI=%GA6L; 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 diff --git a/resources/sprite/projects_2x/bacon.png b/resources/sprite/projects_2x/bacon.png deleted file mode 100644 index 0d413181d597233a81a7f0fcd849447c87292cef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 F{~vqi>dF8B diff --git a/resources/sprite/projects_2x/beer.png b/resources/sprite/projects_2x/beer.png deleted file mode 100644 index e51c3bbc59361880f9e6c3163d5e2d39c825beff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 Q?+&7^Cfk^&nJ(D+KTE6JX#fBK diff --git a/resources/sprite/projects_2x/bomb.png b/resources/sprite/projects_2x/bomb.png deleted file mode 100644 index 4b259fcb881cad76b266e6d54d812ad0e0d7b5bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/briefcase.png b/resources/sprite/projects_2x/briefcase.png deleted file mode 100644 index e3e953ec16647bc2a72a2caefe613351d243d13a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 aeSPCB4!BI)STh^;&2XuSZnBR3f&T$`A-cW* diff --git a/resources/sprite/projects_2x/bug.png b/resources/sprite/projects_2x/bug.png deleted file mode 100644 index 4f177e434a1afb4787775bba76805214e6cdb592..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/calendar.png b/resources/sprite/projects_2x/calendar.png deleted file mode 100644 index 6093a1463893698b3a2d1faa7b70520878bb9213..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/coffee.png b/resources/sprite/projects_2x/coffee.png deleted file mode 100644 index f3ad8bcf3ca286cd5a7da4cc279613df39323021..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/death.png b/resources/sprite/projects_2x/death.png deleted file mode 100644 index a588d306f6c9556b8e7f05e1d61788f65e744e63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/dropbox.png b/resources/sprite/projects_2x/dropbox.png deleted file mode 100644 index 49dc0a2480128568696264c8c8e744adb5d573d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/education.png b/resources/sprite/projects_2x/education.png deleted file mode 100644 index e1675d89a3586317a4cd93edce2fdf46980b10c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/facebook.png b/resources/sprite/projects_2x/facebook.png deleted file mode 100644 index 2acd42067cf82c1afd81b921b2917de12a444f66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/facility.png b/resources/sprite/projects_2x/facility.png deleted file mode 100644 index f6594eda4fc4b942844fdc5bc6da37ef611aba7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 zcmeGk2|N{Be?<1JO-YIWs9eJMYa~Dgc3q2 zqD@ht)m z*n|ZUgiomUbQYM1xSKg`Mi8+LSi#14zt7;Hv8sw9(sKe7PdpuBeRII9 zSpstT(ERkpo`t%FD^EtkE#^6;*aeq=l1LDQ<34;zK@p>*`Jzohfu3;oI^+ zOc=?W7m+z}#GVeRH^yO$`FwWsWqJfnw-ELjj2Lb^XnY1SoXzJG89LS$i55VX7pz=S zjm%d^maFV|^#JjS{1oQJhb%gxID{`c2vHccI=}>3GZRTDTCi^x;y4i*>|&9lgOsWx z6U`l5%#ia}kjz49v5SbXI5N>Xz;8Sv;Ds#DS5n%7><&W)&u((ieLo>dx=s~jD(s?e zstnhJb+nRT~i?&%RlhedX;D1Q}b`t^!f$5;6WqjStxq&lh&uC^Yy@t{fgf#yl4 zNAER0JpR_0l8#kX6>4Aj^(&?z=hx};c?GG*E?LR{(LzPq(Ic~}6+xQP+-^P`C(Q4& zW>;mAXU98(Hq+=ah>wf;;f)Bg)I?ds?oP5no-l%#MEk0qH0mCuMx%f~0|G#=-F@4UR~a?OW^^4gi!Yy5-VB{j0_uS)81rauD+?}+P7sgJ9e#d60)N`x z4=alkos}svRlw6&!Fi;Snd4kX%Tlvgg%Qfy1D=UY6XD-&oux85IM(9Q*lPp+ z%^9|0lGYwaGc~2h0|N(XN_z#6a;7N{+)J9Il6t70`GvpjN(Pq9F4(mA50Fd^TsCbA~GW^#>OjbhUx(a05s8~^@fTQ$z+&bm3WwbHfPwSucd zCmGqF3b%P4d%|wOl)#0?i6>HQ&ROq?9i;txxX!&@GUgVi6Hgv}FnrC>HLYvUz4o{^ z;Q7&!mLc~YN($;tUx&QrZ}AkD@E@`(FMvEwHe#62FtV)Yuydhv&&WR5FPmpKahlfK z(7G_GFgJTg)fCk~hXmabJv!&;*rRf)ns#U7&cwZl6SHr&FR%+dyVQ1j(ro+5w$*1v z9v+LgkBglD)>h7ze0FB+o;Y%>o1MYm-cD_M1)Z|zW?PZ|wvN8AtU5hcL2RXL@)kA4 z^%C*^zxz(f8GGU0(?9=EO$%+4Pus5-clLx1Y4V)O4#_snM_deqszWz^I__a9Qa3Ip zq}hAli^1>4SB;lDqdhlOYxUywamPZAImVmCTgRKe&6t|h5EFSOV^*5e7hg%Eyg4e1 zRZPi&h5aMzY@gabj}eWLnWs17Ly|_^`qOeJ(o8&WY=~(Ljk>eC+|HDn-Za? z^<+|AL|w#_h>9!A7j9XomJ*wCb+!4$nuTYa8dK6Y_$}0NI_+q`a7ps)#K^=kkJA#< zVg|&dS_WIjM?EHIpMRfnJLT*Z+4Hrff@Mi5t|{A{$t#AEuiQ$?ZVb){-hOTSf7mE^^_pbIBI%;i$<--?3dZNGjkJw;U`ifJ zPTjn#Ibi=@i=71;A^I8-a=Fj*Giv5|eAu|8a$CuV$cW^KtcKXKbB$9Q*Ea4c|Ld;y zU*n^kCU3rnjqxtw>hB6}xaGeuQDPGg(;&|=2SvAL$!C#AYZgx}4k#rpRvl^CWTrZA z+u?tL(x+@yzBT!@T5alXm9vM^=Ss|d9x)?ICj1Wt*GYOaGPHIb4mz~aI8Je1a0>Yi z`IXBb1qrMDF1Fv=u>XqY$fH8H*C!uJ=R?J?s)^GdU@+S>TtQ<9+DlR*J_K%d) zAF_8}(%`b8AwzbQjw|0%E4Rn(&W*70BbUy`=cKMGaw&1CfAvB=YLVozxR6&Nk{cwR zKD#7QvEWj}hmW($G(+x>X_Sw_huT{{cYD`_t|c0W6AT&&QCsV zC~lPVO8=<+&!e(M>8)-0x38Dk^V!dP|M zXMY^zro0 z+iRcI?|cwUZYnwuc{Fmnx5mHa%gautc-5^etXL=I_U@XrM`g*Zj{S8r(`ObgZo2Bx zbg`^f-gOjoUIVd%3jM%SBBqeBP3=^}S5T z<3~|Cde1YOx4E_6YW+|l^W1xrN?Tz;+EY)J#>8~1^kprE4MtB%&-XksSkzu#`mTJ( zx=hdL=HhbGRzbgAMeRW!0;Nd(1H%Ff{3ZO~Morh((Wx@n)K>pBhE%kwXl&Hb_LJ=e zNke5cy+1vA`=qcqwD?3wQ%LX)*FR6Uy~%tld#)@uD|h7e+gm1UEp1uwrQxP$xu^WQ zQx#HHHGeAX7}v4p-wPjX@5g)zmJJT>5a17O{^7}*td9xfrW`rWhP`AU&Zp}uJNL6zaBfBkp$c28EZG0UafR#b$#~}YV_C6DW z{tm}@0LR^85Wo=8Az$Y}q?7p-=#5Y!?CDKJCEy)}3gTlz-KgngQ10wUq5`m|yF#rZztoc zmSI!97C_TR)FXHcXv$y@?p(TZYlMc6FAR#u_mu!K3L>!r&<&^=-$OnW*JEWu0t9^j z9Si>AW9T9f4JZjfe<8g8-gW0IVL1#Y#H>Wx!G6IFrT*I+a=lm_40H_8H($(RF77(Qi9|_3G^7)`7DF_|j59IgZ$m~S!ONp_Y=k|cV>A*}DZa15Bd~L#NZ{qK z2Fr*UL$C4PQjLUY3B${uGEOmO+O^WKIKnZJ5hwt+BiL&!)>}x&&moQ?5T%Q51r)U6 zQ_1))oq|%DC~E1VDNHW|Jx1{1W9Rst21UE{)T9zfj>1S|=kN}@5l6>5@lA{#BN+X3 z4SN`&CtY-Drp82cTIt~pH6^rYY>DL8F@l^JwDcdMB}OaPTt{b1UDy#dFA#QQnGqX( zRS|e$`P|vym=WlWY?qzh9PDF(mZx2sC=XNs8a|Z41H_l&k+?b34|h!T0em6BWCLQ~ zz!dz&>oD)6!LAWUhjSFnzyL1`aVX$vg!A51gq}?01Ey&d7;gjIbP9N;QLGMxQO79l zjp^EK5babLb)c{KeVJ9nNJXgKc+s*?uPoCQVdV6SKHJ3J;9&!RPSju#m@zF`3@dX( zMgl=Cz*8c08hay&(%`cZNJAg&qIk5YCX4bg)ibiRD3u)=odsGsXccgRgC;Q71dS36 zvZAtZ41p3KT?cz#1oGVl*8Qa`5N4JZ>s;=IW?mqeTL5H+tQ9hbI z?--$(A~rKHvPB_UI&5~CvN_(tPB|}}!}2P^x!e<2Hde_fW#k-8poTlpy!FK$b@<^0 zuOdHk!5t%BMYy95KfK^o`b9B@5}2SOHpNW|x*D zP>crg0E}S(P#5gs90H`fej9cFv!Rm)v3S{sovbhc&<6bg-bN6f}_eEh32XF|s93$}66cNA|g)kT*pe9Qs z!w{a4gIx(|uA-tH21E3=6v`64Ev2H8ei9>rK&|qiQF92s@gxcczAdFD3&_j^qk%w6 z(4l%NCSfp?Ui(53C`VJELQNKs83zHzMY<%QL+?O? zcX^Zm27`YGjq*WRxYvU3ulocTIsH;PHTH=UG?e^*ZBdv#Mrb6F{bXJs?9VxMi@b_p z@&nH*u=!$e=rE|0Ms(((CX4EztN&#x(ihi}%FdL*ry}s_2^QdkHu#Gc2$b$CsL6hp z`d)2xOxX8DAcV^Mh(NR~yQ%+WmKHCNZgu5?2_w5-y4EVEV&W|=PGz3RF0Ud)nc)v#`aG5*2BZOBFF3SLyxx?ur1b)|Y4m9}wo>qf=kiRbg>NyV@Et`;@1X^F&1*)h6 zr|#5^fm>HV6Qu4QMJoK)KIWiZr%0uagm$lj)}J~XMQU&CQdCF@$?hYBA2@Lrv<%Sj z#ei=aH-QE}f`TtEU=Qc$+ea|`22c*lLp}8RkF|?01}p7;bC{t&jC?`g2fSWD2Oeqw zLI$+1FZC&mAszDJp%oysL8B%M>5vZ(y|KFkD5GYRX&Tdly>MtDkSzo)7qmqT>WKyX zM34XocA!n~?BSdUpdLnIcLw~oK`R1n8EA~iGQ`WNYY0O}F^*XQ%(FqG_IWW*q-zR4 zZq)@1{m`O|z%2uM&%xZ{FZAOjXmHm9uO+{OhQG!DR5yTh$Oo?-P>ySh0eoZ2&v>An zpAq1emmcWTuP1)SBZQtL{j@xcd`I)s2Fax3IZVp+N{m+!;`G6L9k#>IxXWT!l75+M z2>eAGGh0%aXimwptH?C%u;QW)f0<#!O*2C5!sb_MRODL4!h*3x5Gh^b1jx7vFPA7Vihk=j<#98Vvj; zEBvJ^Glk)lEb2SUdsb|F>D?}}JUBKP;5|BFQ=&Oyh7+eOjs*I%808g&%PPey2(KVq zmH{qvhZ~;uCW4$C!R2K+m@mWOC`~yfOUai$!Er-D;2nG>E*eAJoM_4^St5UWjptoM zdY!_)RlvJ3?0r6YH-^2>A@^$FowB&BHoSuH3c_U>;4*huvF+{CiyW8bi{M1)}BC>^6T2Q^BV3cnSY=YVQ9(rfbZ-W`@^)&gXNSdw%D)e1E^+IrrQ-v)H%L%2Y&foFIZA zBIahswxC@ND?cxSaPifjDF7V-FEi&Y2qH8JRxTv!_!tBcv|ejuv~Zz^=T^@x9-dyZ z=0--cUYkAL*8Z{vLAE`Mv2(Y#Yn0S!fAP`KB8YUgHOsNjW&^JlJ>+tMY^g>?96Yfqa< z=DUh;ZM!eTkB}Eclhwxu_K3YTj9kh^+RH`W8uGIRKWQ|gzvGbMSw!E2ixd+v*$#>0 zL0s;xT3L%MR6$%6cfY=mkYYL_cXA<1j><`J#f2cUqt*l&BOY^+l+s1}=OIq&$Y?i< zLM`Np3ZicA=w^nbUqZ+w;zAh+zc8Y16XZV?;n|6}+>)2yhU|?*Mw_%aYX3bgO}s$~ zL@F{vJ6l0(p6?QVl}&t(j;a%;l$c9R8$HW)m}`{2YQgr%u`_%%#cEpbAxK<^1n{=C zYg>tET1m;QLs_CLRNh|W?U}f8Wo>tTX|k6-g1p@7Q{JttmN||zmzT7m`_!an9*^Zh zalf`7aLW+Wzlg*&K67mKg0Y!*@^JRkr}cGpPv#dIE^)o%xU1W}Uz99gw7;~s z)m(k0;5%cPuPIMQO~Jj7mS@J79ue5Pvg&oP>6c4FJzr$*Pb@TFneC)By4GgorbEV2 z2U};HnYhpJ$kZE?DtcDGs#fmg)~%k2q_5NE+8Lsfuxu6gCksV!r>*2y?FiD6_Mi_Yd@T7gSVu7u3Jh0O5#5|C>;{itt-jm`t%i$>WAv&Zc3MISk-qcD0<(C$4P{*?7??R(I$1q2OOPF}pgH21z-$5Ty*34k6GIa$E=;~M z;-A7XD`!j(bTU(xe>5_9l$!X?Afv+B3M2O!%}~rfJk0$3pY|0aD@-aj+R8U7Cq`?U zjgt?({cQF63_h)+%CggL`PaqNU9Z!qldh9%St1y-Qh(E*9d@s#*xp$;e{8*Yy=Fb{ znur+&4yU7RpC_EOA2Bm{v0>`TEZcK7feE8De~r>A-Xm#laVGWDvHRmZq&(W!o_n+P z%82L3CRl}+Iab_lG<_5PhWn$putrkz$da4o*s0O212l+z~uB|JdYX(n@OfiAiUZUL*-Qv^w0i4^CWew=2!WLBp;# zQQ$#XvO`kL!gqGkcJ7ID69SXm6Flwp{`7I~+Q;jB-SWD%(VsSP=U3F`7Rd^&8k@OI zS#G^Za=@>?GYco5FMj&_Z%R24T{1ZbbdnNJY8h$F*Ko|VZ9VFy$5$J%spI%oD}jb7 z@!_pL`(KQHKlRmA>9d-a+0)l7U7r*d9_Ey6mTZ%3`Yvx)T2p+?*}Qo<&YixZ1~=y` zE>$#j4=x!V(_r`1?s>dmyyOC%Ic;gGN$bx@pUg4#zP2&GIU@Gza#F0NXZ(xpc@3Y( z?^5fs@7nM=zRgtFi8oVNfwxk)WQ_KWnVUSdWz=p~{%vEl?7F_u8P{X3;V<`wWS487 zerWQCiP*ulMN4ZHYBv;ZC^|ivce31Miv@2NG)LJk$UZyu>|D#amN$#<6`v}86ge|m zXZqtA4bctJkE5$Exh&qcSUD>p>+%}&jJm~Votv|AH~KHuaz5kauy|RfNoq{$q(?ca zIq@Unv#mm{l4BpaUr+x#>vmS+rLpPtPk1ZSvNmMxa&=!R<$mc#+V$qpywF`&cKy+% z!zU8>R5V#;v5e1_3!6vJSv2QGRLSvXy#VV*?D{RE8k_oZJ)slF)Yn(1_*ffR`?_CjkXKu!7UG!tIQ`NY@1%Cu_foo_ zbT^-<)veW@{bI%o=N0#6lP}%6bl3X2XY309YNOrqJ*#_m^pqpv@l}`_!>0MrBw58hkvvHX5i)i=h)>`LO=Fe2pO;TN_ z{cQFX%`19Es&3Br9y-N1ng3!jUQ1OeZPvzLu2z3(Y7Kl9^Gc|8r&NU6tz}-@PnHyX z^pBTJR2`{2CrsZm$m-{#9}L8m5+n~!Y8mA{>5$;|0+|B$iE8Du%7dO5EmfLe)ncZ! zV8@ZaLULzrSGb{ZM!7zFuVUiiTuTwl=h1UwC8K_m-7rIEPTurAM?wy7GE9uOIfFtp}lE)rC_bZ@M!^ycvG}5 z@6S@&@X$KB$uT_5CvWnO1?zp6=il+mzsR-zosffIz5lLvRgasNSv#pYS6_7f91tU| zE3t2X+UQEDaEaYdrc`aKmk#v2b1ky!=!L}O!tB+hZWV5guV1LdE)fk&3V$6gx>4lm zvkM~Ci!L;^eVSLP7G6B1GG|YgQTFL;+Lv?J#NRF{o~vj7r~OC!&-SyLE1q9;ecZ9J zyjgl@?kCN^9#$^NZST^(eYMho%VEJow})#w%{w#O_0skwHFkt`ZdjITwP91!P3{Wr zEfBH?vT}Ex4VN^?$Nwi&5=aQ96u2|pGEr0a(#f~qgl|P9c*VK02KEKue z_S$ESe)mJ&TS^bc9E;iIqxw&kOXaDooeir>s@I8mzP}>A^<~Apo&ybYbLW;UZMnR) zC8M%_l;dT`sB?2xYMiN6dh)(% z_d2q7Tx)riX*;j~p3?4+wqP-%;lYu?cLPKM-o^f`tEKfyZ*y1Umw2Pn)uoeTrMgdb z-%XQ}RP*V0`0jB@c|`fi@Rsnl$hr7CdN)nrSxZ_p*c~ z1TD#eiWcaT6xx9;7Cb^eVTJtzwI$ja0R{dBRh*iM_L|nG|0a-@k-CrN6ZJUu^{!!l z_-8F{Q?w3Yg$>2`)md7Bmta&DR1&CY*^OSnmKIX4IYP~dUegNHpaXriw2+_$7f@?J z#VlAB;sB>CRRx#-E3^W*efaP{UD#K&vk{96%?)NAumrv`q64%(p!B}mTppuNMsW45 zfx!{{&=^!q%|_1%8rgo+1QepYXiIGap`D7o25CAZnm*cv_e8pdo+oq#@eH!X2))?_ z;|nJ+%!znE$WdOj?ZwW?Nw0A9*P)k_{$v>*XUptDo(oL;^y9e0mYA`{2)z}Fd0Xvg zUiI4NP+oeTLFf%5g)SdGPZ&|o5D#07&6}a9XbLH>QgMhU9kpKbx=v5;w|ui<}s*HFEw!5K3%;;G6EICETG%E7+nka22q{( zqyRV3#a;+x#VHj|GiDW3Cv0&Qq8Wkn7p9)sg|JSd8G&mA&SzMenGsYcY;lzzCL_$g zYvGC_4KwXsindR~-n&cGk=|NZ*JF5!5uIB30J}Z~KfGnufT|AaCQ$K~OdtTy3TQKc zYvB`hM2}*a7BrDPWjK`*T;QqX2=5~>BQWi-a_(Bx5v5#nGQ#XNf)Qj~B*GaX>Im&! z3q{-STa73qRa-}O4c8o6a5?pVy^l~w4UOKQw?rQr2OT&q0FEQH5gGKpp<><>A}fB- zfnx#S%rC5{3?_|}k->~UmTgW(u%a@Uv>zrTL>_^0J(>Mxu`3wZn3L+$p3WN@oEwA)pi03qNazs}Oa>8kZHum?0Lz zdWlXgxG>Sm7|i~;;2J@7=J(Iun}et$y|oO19?_|Fm<8AcfKF7e0$%+@9r46#hyi}^ z;~5BHy+o%LI+tO~tTLcALNp^-;A;Spgf+kp8c|1FXu#3-X@>jl!p{N2spUf9#Qm&A z^f8`dkL3-+Qoxh@AG88T~RJOJZBAVTB(}aBehMgD&olz3R zqEBHKXH*E~BkIUCQ~?uP_|QmLFSFJNGyECQ8X@WkGk`Ny2hpj8dk!;z8s6}FqH6>mlQO%&&6KcSq8S-- zYlLVIm&zrtK4ThOizYj==RX$kYLuRswP?5gDopkp$j4vc%)> zm7+gg^!>;nP}rFeJ>cKJWj`6vJF)}G<51c|2I2>^We05!VP`^^9kd@(A15J0EUlb9 z1Un)B7kkJJ;QI)S+JYUEL8U@WSXiMCEG_I@Azy$eA27Tbicek;6BbtJ14|2M4`FF| z@hfNN3gNsCVIV*3Oh`Gv#*Wg7VFcPIW6-ho6%01wBz7hQ56U{g9E?ZcN8x41=dy<4Qxr4u2an~MUf8)p zo&xki7#@TH8vNdREvP;iY zX(VLlyz65i zf{qWhRRTZcAd7*O3}`IfL)e)R4FCEh)qoLFpQAtU06R~6;R$LPMl9jp0&fHG$>tu$ zI6F!3SN7rC$z7lpVi;BjG;}qy|^) zaS}2ZQKw^*lMp(=8H^!LLIxx1bZl}GLMJ$bF~mv8U__mcO-@4S1ZOaYz-xq_o^<;Y UmSH~kbs+%rc~-`0hAw{p0l+EP=>Px# diff --git a/resources/sprite/projects_2x/forked.png b/resources/sprite/projects_2x/forked.png deleted file mode 100644 index 32f4c549b3381580ef6576828a7d7939baba264c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 CkqNN? diff --git a/resources/sprite/projects_2x/games.png b/resources/sprite/projects_2x/games.png deleted file mode 100644 index 7b67835b4a7ee37883ac5b4e13f02cd7ae497162..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/ghost.png b/resources/sprite/projects_2x/ghost.png deleted file mode 100644 index 796acb51fa94c8701ccdb3dac72987d8eff770f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 zcmeGl2{=_-_lS%cnrPA^DoLcIrwkb~M9CDIHP9pt-qY~%sFa3RNkzm{J&~zFDWOnl zL^LU+LQ;?ZN1_4$UVg_rPUp_|y48Qz_pSEcYp;3jbI!f{Y_}cLr&&l#4v@q!OxnuQ z%pSFi0L4WyOh~LUIvWinR$02P#W1PffI?Wlc?o;`lM``T&r*eO{gR-t@s&z9qXJ8yq}vGMrwN9m2Pa$C+nHmpjh zk4VlJ%M|Z%$a1XRIKLhzO$PUTzU9WXoEH_Ell&!BS7CDE$%~ZNHme9>O}_g2BZp*) zUB-mg-Io%_GN*=TjvlnVRrZa^;n_ldTZJ;cgMPLa_v?dA+OWsu1UAWB$S)#vm;)9i zg3Z6Pa6vgXeH1o-`0uaoV}21$hc^mgvkoZt6^aVNlzJ}?G{crm#1isn?3|3bjK=!7 zTVK<|ibi3ht(@I0vC|i@%se@%vzT}fY_wfqzz9raBR2o0ipn}{>tU>qd7ZQVKO>Xm zs?<@Y4xiOeRn?p9KTCYnYB6VL&B1DURth8g=(=@t3!9{wz5a0jG5$KT&+G4ESX5A7 z6m5O;x;&Yrygc1KDKhg$y}2UVI%L6u@|Mc{_*IiI?1i^)L5qe~@&LbyqJEw&$A;F5 zESW16^-JR}_p`E-&SO#4Po3*mL2f1=-Ix00No7Sv(UfZ@v)pbwZ))+#o|oy|yyBy; z{+Gsv=a*lq`j468Zz0n3Jp1l@o9IFL`z5w6D0#Kl;>!i8)-Q_phg`E-km{n|r`)dB z>OE#*yX(h957}X|f5i2ng{_NTmT7zzHY^*5onB@rv@vK@?3{(dAFPMVxp-&3Y{am- zG_R}&YU09vOSZho_i24+)NBzo6!UYp+P@mZ=9;N$I^Iq;x*?8XW>Nm?r;P``&+4a< zDLN>tdr6kmm-)I|O;oRCo5-0+F7g|+X8wqT%_eHwa!)I&&)0e|Nl_=$ZppUbRWh2{ zP8VeiR>^*H6OYVNOZS%$F}^9@+fDgtpwNPyE-HJ(6%Ge9DQ8)V^xCDWbStor-4N@b zahBTlI~|prEEVev)^yX`KHL0K(8QbAn9X0drCVqp@IPy3@Sw+e)704U1GbtUle)La zTRUv8d{p?oHRlEx?AAS6buWI2?9;u5rZ+}szV0VB_S%ZknmJcZ&it$)5xnrunIQ>1 z;&TR^o{=D&wxeNT{uv*UUjCCaC3Ho6OqARP8(X^AxJ)auj8z(>s?+nS#CQqet#;YN zhXlu3pBr|m=f`XP7L3u}?qaE-@~GF|-db`S15K}uSM9aKbjsFU%K<9Ex1KIqepXEHfQHh@n*kLO6;~_9Rt&6AuA3zpv0&2bznUCgs@dOO zHl=^1T%}H>=;F{Z#!kn>>`P;hI`$m5ccw|=(G>ercH3in>--X?m%ByY$~rpn*unb) zmMAP~TzcxY_obet2M13Jx#wJXr`qCm$ZO&EK0Tzj_1$tK&_k_%ct5dz9{qj#oeH%% z(f|Ig{x=*)kJo-1T6I|Vu$PmIdW!mQeS>aG9-MM;*ujD7T8<~rW1W-j>kqga ziIs=0ZaU&UO`=LICZyhX=d(WVM!Xy`@Pv*{s`ld9%i|7(9CC@bjJJ!oc$=Y{R1*_% zB4cuz>t}x%;~P_k&mL~!u{W=KM3uu6hte3y82PCN6B?2< zxqgv0UNO(sXHb{8;D77ean4&nDLJQO@q*KVl~+_l4c^Bv6)L(TAkIi)uFV0THV^EwcAVnysPu)h)CD5YwumXY5Lr*vcO2{&x50vmnHbxn%eq%oUc;RTBsG| zocQ?kg=n9+Mz?ngh93;q{8?^Tu0Q_Sm}jo@?vBsAaPz_)+pAuY^8(6De^+T;)ViUy z0E_V(D&!%&!{69{R=3Yh8-7#1vd3sb@!}6>pVS!dj!HG|YrJ=J;^xY%MCBzn|K69V z+*lQw7nHYDCSbbn>qqy*++Mluy6W3wc)<1m=WRxNRt35YD9{cW=TlH(y0*;hli4A& zXW<^&wtA;VO&ObJj) zcqvuBQ6W_8=A2dQkLG2+4~UUJso6_o!l6kvfzy6I@E>D2^;r4cL+g6`4BaESK3g%{ zV~AFPZb4v?>1_4E)9NhMr*7E)cToDc^{Us$Mr%~2ZXJGdU%HL7O=nnF%&>DPD?AG$+eF@!NM@goboOtax zQ|+<3*jbOo&hA%ocih%H6dySRJN?sfah;gSRAPR3tLU6k)$ z=wAKm*{H}_GKbOO;h->no}oCCVBHOHX+E>+X#SFU0Qu^sAzWqSi8#u(~kwaEGwZvlh&{WP8`J z;L)3B8@^Z+|0H`vN8fe*lzPWoOP^M6z8~ySm%lsWV8kY0&5tGXi;tyjtXh~?woKOR z-6c8i7lo5scU4VHpO`nh?xJ_y+2YFH&KI4-PEDBS`NsQ=eoOFu+Z$;|(!!EbXD?5! z-H>s9qkCiZz{v4=rSCJ=|0Cb}=wYOuL1{+)2Cv5JjSXe;rM_#1H|O0+d*U;^HZk2c zect;?HO5a&OSeBXn$=QL^seOhWtl!v^#vssjiLct@>_x$_R5-e-+OrPoo&+F-bVgx zsHgYRXianVml)IhMft-b6u)#^;(WpAsL%cgM?QZ7Y6L`dzJc$;UGd4)KF*&=n|GZ8yEL=_V-3$+UYGkDX25NK^6f_K_m^x+Yc zBhWe+2{epsiC!u@6wpgV2NTf>^yvxRA~WM-w%j8pf~HHj6=>c zC-9YaDuISJHUIu|?%(eJdgLWcp8sl0&!w-Jfxxl=mM&uYnPtByZ8IRU?ivGyRMV^& zftr%>5tULhjZwOKA%PmQ5REbAN(5edk-)V829yzk0>B*zalmQN0#L4An4lL4QHYiz zG94d-?hc^3ayupo9il-3nYQ;tCVJ^2^5OlDr~}?odWT@L$Q2c~KdnN_#UlQ!Q(7?s*bkwx*grl~ZL=%BY1fTXp z58S%gWsz(DVbi@6NNyIJvK?Za1~MIKI@O_#vkvU0!Y3}afRjLopYL(w&8Wk+Gwn*O zQJaD*WVU7Z8X*QzhK#|7EkO7JiT6>L5^N9^=fPX}IEur0)G@;cOt-W?C()s=hYwc- zp!}SL=1mAZ#4auV5+W1o)8eC~v$M3|b2c%9>1aHeB6FQyiV@~jQNNTh#=FES0}ZOh zG_Vs0*&uH0AJl=h?ShaQC*aF^Eka9#RKSdm4moZH(xH?~9hL%N_hM(o*Iy8`F+!^4 z#EKreyu7T)J7gK&Sdf9%(j@bJGZpEHJVOUlJ3&RK5f=x%tO%!Welr!}G!T~LIl0(D z)|q5&6dJ<^NFwY;19EoD+i9POjP0~c5{N>NMAjPfhI zjwjIulg5-!b0QBr*9dbN>S8WVmR1+LO5dCy5c>J)`q>|*BAChWj3U7m-}NhqzQrGA zeF*}gU+Au%6;!0_b57r)pd$41)Ah5wst9bmME`8Gvng*pBB4a4V2#m_?X>5 z;EfCsKo9Ku0Ll|5DEhD!4}5T!gLV@_BDfI;O!tZVDopmx5FZi9`#!LLV@+fr^{MuE zo-x5gCD%dg=paSR_F;322(;vgJa|74b*T82aEA64jv!I-(WJ4nw4@2;X7zo+C4wxm z`z(il01`m0!)qw^dO)@*TU-C;1xM0bkf(RvKA{v7%Rr26C zqZxs}3H4ce$WkdK=wqr&b<3m*0+d0}fh4WEXiN+OripJ{N$k`^Zd3%(x6!kcyR-*X@-(@5d5us#3nXcJ!r=rj z10g>Y;RJyghyKzO=jGDEjfSGm7=+9`C~+BRSz20M5eU&aR{AUj!po(_iqjnP3IahX z%%n);SAT_%c&Prug+jEA)Ie*3A)VE)l zL2%dNN7m`t6jX#>cK9(Ts0cr@PS2*GBJ{GukGUVFBAETO#4|t42xTd(*YTfWuzZ`patMN#K1@g$MYO3VA9EBv?4`xFD7+>ukg%! zh>%$T-nQo?YMF@@e4zyp12Z}};^9b`NeAJW7A<&(CRp_W&ZIF5z{{$B@QD@>kDRfp zmnnX@m+~4`&@u3l&K#{NR(`#l6<*vPJ)h{sg3EK%c11xf=y<4r=HO4IS%GCNFtfr7 zYQY!qi5Ad{g_aCU^se|G0((!4fSJEvhdn4bM?8g*GSYks8rvXbdDw%q< z$N?YzIuw3z;wO?G_+bkw*ocTkzs#wa5UmKIIDr@XK%)ZCLDUI0r~rH-^8JLy#9sp? z&T+lZb%ms0KtI4Ggl(VbP)oMy1PtxagjzL(WF8p9Z@$0@5*)Un4iz8JU=9b60a+?u zumv`80AHy1z;}oNfNGv=G_EP4<0$^$RnxQ88_AzWC`?BWE+2$=beP}+9^l30XtiJy zY=aN9cyKy1vEaOHwO#Q&&6BLAx$)_?cC$y^{ z*?7J!GNptkn|DO8fwK8r&k=FDlSe)GF38J&QLmuw#Xn^$GLkoCo#c*gX%3{*LtTBQ zR5s6bgk$Fe0bV3~aYXj4Nq)V;uXV$gb9nCO$aW2!Z_MjC7SY~)ME4w`y@$4p}0Ptd{xhu8*(iae1=W*OQz8XyC}X zZCEJ~{Y%Fo$7EscD@b(HGn=-pFg6QM9Zi4ww4uKKiBX=ey~7=wy**C3tFmpnfBxX1 z{;8w=`Ssc2q~H&%OK3^eD z9nlLv+&25H)B)XNGj2^S>s?n{BiF^LSu+>8xJi@4Jy1S&#ahny#xf&qU9)RD5TrH3 zCFkLEUQW*q-Y-hrdf#ew>qk#TJRJ>>Z9|ZidQ%jv?xbiH@FIv_w3qBf9kF*g6XdeF zC*=&U%n|ssT4lfPl)PNsk-GfrJSS~mJ>&d7-RZvfE{e;pR(z-}J}29JgKyAQA%$G) zt3n!Eg+Ds*M&(S;^y1^vDdZjFAoSK_N1G-zVQpeWl}G$>tglM_i$#$IhF$f6-}y`|Dhl z!UM)dN8I0jd7{Q)l~axP6E+Ax3(%w#%*uW>fk!#-=UEE*H+3(~m*WdsTXae4{D_47 zi5Hii=gc_JzP99&8`o&Bh1q;6TyDA&4wH2ZY)x!UpBThSOqw!h)HA+$e4P8ub7iE0 zVvR3PyEf`W-h?%?mHccCu4j7|2(%qkuH*d=51C-e^=|_hdUi#CjY;@V8vMm%J&a||X*2i<Tx-VnT0;}k@Yw0mFvaoC0p(JBiCqe`?J%scDlu#O-7;( zBOB&4aIX)Ytz&&A+@dP>l+~!Y0n2m~Po-L1F!zfcGv}9Z)qCFK42{nwo<8wl;)d}X zIyPQ-<$7&Y)rrZbA@^;{ikkFag}mZ?=QcvnSH!!(-)XvN!~~uRPNHrTE`*w#6Mb+< zw7_cCJf%0GjbXxJF4nfPsj_=S0`KsjFgh{qgqWo)5mtAMzbmV1*H zSu0!C#qm81POy%TT=K?J%+e`tL9AcAQ>=@X)}J1B-3PesZkpUQqx@+eeQ8x)X1;{L zTG5o9a*~?`6MTR1nwvN6(!Hm9ewED#?H12Cq!Ax?N|mB)q->L7(RSQXi>EGhTjxnv zQ@+OOF(GXp2dl@vol!eO?A#oabfxvnH^&Eu1luMUB$y}YzsXWbYL1CKm$fj%uFFeE zr@%;Nxs1M3K=JU%M$4y`RWbZA;}&bEwI?aWZ$2w_Dnrlh#+I0t(5UMxJ)=xqVybs# zHGZ75SFziw+xcTmyZ#7U?vxQzxGP2!Pf))#cbkj4xMD%Y-{zDRH?=8e9Zooeyx1R@ zUaEfP(W2iM2_N2=zr1cropZi({+Vgq(<)xzyOytLqJu>zAFgYe~)A;PqkiC%1Y!d;P+>YTdQ!D-ESr?gv1H(P?Tg7#k9 z`+K(rkD%XEp#j%cY>tbd>Uv{~nHbh?g+PQbpzeGNH@k{b&DI+`fi(HL4BSiDilXNkwF z$M<<0UOF7Q=`lja$Ir*cSL?`Df7^+rN+EOIN-HTlYVrOM#{#HJ3O^@jN8;B{JV0+bDg9VOI1q!pHP;|PBv{d zkX^j{*k6H}b9YU-rF>SdA$`A0+|f)EL6fQowWx97ze+gI)=-I zr`Jv|9e*u4zuqUg=hl`(X^N9i@Z8>RDf78+mctms#gGsV1v$+f~6|Co+7d?^5pb z>Q@h@$~r$XOK7$UN%F{=wtMkrua!A>_T^mR*!)Jon!mwk@0-f<<`rhPigqCj3#5Z}}p+~vF?(bRcca{*@= zXE%?uP-=Pl!$;y}8deqok7vHo7b^JadQaqAH+ex7LF?a7=GRJZ)!S9y)WKKNFfN98D}E9_IY-@Ymrx;65y@whXWG*OP-g?!w zHMyc;jLlV>@C$0IoL{@XR__UVU{;WEG9x@Gefj3}mfcxb+#Nfb#G>XESG~*H_4l~m z$B&{^HL9}OcDr=k>S(VSSLLx?rn|T(aJ7MNI&0Nc#wIcwhY!C^-Or0cs)C3hV$oqHS1y5oDWB&{#lFL6x#&ge8JA0FIlE#0Xw;{b(-PAYQ5B_7Sd2ULd(Jz^Rz18 zgFt^X@hiV^JB?&=QM#DgH@~vo4*~zs`cX)WJrE;rfFL@xo?w)qG+0Vw=wDai$4oy6 z*uASTeP9~`DhKObm^MoPQhuq>=oAj6ae^@D|CLTgiT|?lsQib!-$j6CRCKiY)$TZu zoS?!?myA4NS}C<4BTuli2U~|aV7Ra}Y@ON${*CS{4FezydbkEK#sPMz;*)y+{kX$u ziVZLz{dfDZjL=$biXcd|=rm*3U%1ZoNx_}(PM=~}zYkCf;8!~$pnVOr_Gb)jLf?Lm z?%{pS-at$rNJIHFOPWL~A*cj`Ccq`1YyT*X>Z_-NlA#_(ixI}07Jw(h2pvOP&dp2JwDAG^_O_4lw}}|;0hu2B{3>YGl3`*l>PBBUH`ek{uiOIL2vdzHaWX! zMT~tkdh4W|eI`H>;pRp((DQ_?cE2AZ$f+?a|N170VQT{DDElUPp<|n^WYQ6~hLa7- z*p-pxU@YiEk|a}PBafL{v`?wpqa())-8tbqZmi+w&YQ^3H~2fzbI3qFG;_?y#L zM~f~{fzQ@az;*3_3c-@qjM!t8!9ifL1hjbo!l+jPM4b=-b+jKi!}Iwx4=7lK{x13l z!2bmLpkNCs*qex}D5I~$@?iZvhOYqX)cgUrS)E#F7-3}LG-3vVfzW1V1hF!BrxtjR z_OCl$IBg&@asr)3saV69`ldb|s4i@Y>BhK<*O5Jp)iLD4g-saXb%d~iu&S7Jgw+VL zTb^CJ7Q4rVTOZy_1Nh_|FD&U3*agaYIE7K!e#P)+1a6IZ0dBt#U=ZlNZTZ}R#vfFc z2J7D>aod^d&R$EuxIa20JnWFN@)0b$AO|3(x@|BY=F zXyEA;_=uh!r~*bIJ!XG&c1$g31AgNGKFx+t45R>}kOL}^b`>D%1U%gYX()o~XK+C) z%#`f9?UTe9uK{)VBBZ^K2B#kC9DH#?@3~NOUw`HbR$fd1S$G~81?m?X0Vo4gQukSf z;faDeHGjbE0e7ThL>@B`_~wRMABNqVMa8$lFyR{`YFS)uR@cY_Fb}Tv%>{To4KDsD zfSi3aY;mTq0beM>FXzN!nCSY!knmMm-L+6_CqMVY;)NU_pp93E zUHu1hg?IrcsFU#!(3Anf6T@(Js{w?EaH$W{!a!dE2oIo(0Ym}TAr11VlL2)=T~H^~ z4Q)VM&?Xk(nBdq32UtDB&4PS1<}5i{Rb-%#2kNeysp z^!gJ@CscVqPT5mO0kjJNe%?kI$j$(~j{y4v*a!AyKwu_W;19T{s zIuf7_zqO&-kNhOS$Nr`lX#NWzZ!$ne{>=w`>~DLa3gDO+$q~vURQUiM^Fbp)ql^PI zdV$?eqd!V=2NhbrL0wQMJ@5kzT5{ivHrQ8L=m#hK0EXuS7or3@<==o_1`uAx&IBk0 zkQUScBJ4LBpaMYnWfw+}37GI$AG~@SRQOg2fmby@0fgVZ>JQ*m&Q5?6`s>Id{}qt; z2M8~7`vdq*q!$3;7eNUHA`=3?N0|q37NH*eb1$-^&&KbdG$PpEeV|_*U^@|Zh)hT| z7_cM}gU0BD|AT1>rVXnX0TOzu80d#vBE9Vru$TuTZw!e}2J>FCE=ibgL?(oFw|_tl zWI~2m(#eF72^nG$7-GXAR|uJqAr^rlHXL$=46%gZ{R$|a;RoXB%w%8qlQ`6n0tnBk ziT{;0k$3995?1Dwk_llx zc7#Zh2_Yn`%qt}m!hGxqkt7pBNLZOyN+yK)*byR0CWMf%GOv`#gb;SE&b+&9lO)VH zA`^n11YuhghL9q{d?PX;0U&_zcjDn0tBN5MOlF4yeSp3|pP+Aq0Qqo{kgzhZl*kpr z{HT6lNircrEcs+Y$b<~B2n?~|kSl~t$PkOb5E~A;LWWpEIKbP^UX@$Ex$auGropip ME;Q9k(p|mp|C}hmGXMYp diff --git a/resources/sprite/projects_2x/globe.png b/resources/sprite/projects_2x/globe.png deleted file mode 100644 index 9fc691e165f1b7339b2b9cb4b82fba21e1596714..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/golf.png b/resources/sprite/projects_2x/golf.png deleted file mode 100644 index 60524764608d07493420cf2373680033bb9ff0a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 T_VV)?m)-vdQo%~^ diff --git a/resources/sprite/projects_2x/heart.png b/resources/sprite/projects_2x/heart.png deleted file mode 100644 index d92dd454d763fa8053a890b11ec81beee4a8beca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 a2}M7=Rt@mP&P#ROVmCE1H%u~EvHQPGb;rQ~ diff --git a/resources/sprite/projects_2x/intergalactic.png b/resources/sprite/projects_2x/intergalactic.png deleted file mode 100644 index 03e1565fb9e4969a71f1cca965c0894908640d6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 diff --git a/resources/sprite/projects_2x/lock.png b/resources/sprite/projects_2x/lock.png deleted file mode 100644 index 23eb42d8b6c104a16cc4832d28920168d2417ed5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 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 okPIPt4bTZ8FPf?6Ys1CfQml%Jq;V2tv`? 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 Z95y-=+pdjiCVr|UtjE||B$>Ib{Xaf$-i!bM diff --git a/resources/sprite/projects_2x/martini.png b/resources/sprite/projects_2x/martini.png deleted file mode 100644 index ba904239524ba8217c933e3007f9957318fc6322..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43007 zcmeHQ2|QKX_dg62f^1VL^i66Do;FgNTT$@zfOrA=VYaM+EQhNf4su3k?h=PhQ}%(q+X07gsqG z0|PnN#^I^#Zp>W&QgDyM>qe0O7bF76MW?l zK9;t)+)hyGDQcRZg*XwX0_ zB3yv5zcqJG5ixlvVLxcY%X@@J=+}Mg_=xGd<)!(;{Rz3Q^L-781!IZWtSMW^5q86f zZjPo`G>At-iD4$Tj>g2vvqWm9lvq3=+=&=w;p;V+5LidpU+>?4HL-ag(QW)kTg?wc z;-pHIz*76-HIo!H#(7Q`9=c4()>fsjVx~!tA>Gs+IyeODs-&&i*K35Qn&h*J+XNBr zFAcq|s9BvU5to^%z9Ug$_R!at1nc_EnNw6-k`?2sOAyajx@Xrat0wgJ7%S-ETzhCh zxxj*1V&Q*PZgY&6)ICFlmp!qqa7EjUJGe9H@#B)>;ztv%=udaJX}iAGDQ$MDZOxKz z?wZw=pPyZPq2M`Url*m>*Jo+BKTVA2leJ4^^PK#ben!=2#pb->k22B~4#SUv!>FpXK(0V>jw6dfz!It7NZwUsqNw)nb8nfUAT` zn$0;0Emz6!4#HuV6;nJ#1oW;8cXg0|;>$N@t6l#c!aeqReU-m#EYM|}g4_+?ZWjGa z{YM!Ox7=ziXJah;QEPbz4WAj~&-;(PPK?-C?VVyYe79%3h1UH}XAF{}M)%%4{*c(+ zc`Jtp`*jZwxx4&yZ>{a>2TSk9ERcNSr)_X;Sn8{uLL;v%8K#nvu7B!JWs!inw@&qo z?G%&I`{a~Z{^Tv6=VqO96X@bOE>%Qbz)fGyp|75?-9$UHN5)ZdeH7F>KM@%%!oS%f zZBV~}DAUse&v*WIrRSUx!+q?GmHR*F;@4GGYMrmamC*`awit{Ul(e&h$*CjOIbCwb z=Pb4CU#5I4M9sK&|9~4$<}HpF(%7vmH{`lkacFUR@yKGCV)>8LMMLN4E<5to>V=}^ z%|#P>l}MGSl?cuc8lh)%IM}iv>Y#P!QGV0(j~`65JYnGz)m81UV2wMQx|^6r96z+@ zUhf4x7E~@g@oMGy&INn=ng!mq&AC-(^eXTb|0lOj;@;AmuK7AC_6q4K)YGY#Th9|g z6OZ<~x2@MT>tUmZzX>YcC%MnX#!e|w>2GQOo1%Lr>>0R6MoHEBSoG28r_o|I6*jl5 z{f^DDS|2ywW~5coF_HUwV{D>BC%>_hv2r>#Hp(a3DayrK=ZO2%nk|A;(AR3n?bO)L7?K@EeE6Gqx5SXS(I z)DbEQTK0ASN;8pC#mK-4_pML6y&wEyu*^}liAlrf&sZG2H*l|AjB$)bjM1A5>T&NP zLyuk*lGd2daVpV^BV-OH8@gRu8d)9` zc5#+R*hH7er)w^he($qhwZ^)}`FrGNqfT~$37r%K^Ezer)Vw-snTw{Z>b1NN76voZ zbqyjM_BaGS-|U~1t$8?i{6FI*w=c|?QKV4hoZ*~tc%a}w`GKaBUQa3yww#o7bnwx! z6UR=xcIWn;Lw6qR8x^88{NaewkkXKcA%$n{r>&l*oEVjOZoWx;@wB5;%M(+UdQH=q z8ewNMZDzvw}oQ^q_E&fH(Fv;OL*y=AISc3Dzc zk46?HcD*(D%EC~qkb6c>J)DwOY^w0xw#9VgEtNoRl@OVXg6kKGC#?LuZ07T|IiEvA z5<=46Mdh6+S1(^!?vsDuw%UQgVN*x0xSM|6;F(29wvO0=J;N3k#=4sun0q>%DebR1 zSJmJ4_`{QDBiy1Z9p3lQ{-VA7K#_Kl=IEy*o=%;8dvxmA>t}D7r@MsB_9`^k(7$e8 z-P*crBGO|3pA-KUPd(4+9jd;r{agOh4xKT1^S{JDey6uRJV{Sl&u`=LjU|_l%P+Y8 zcIR>V%F>`r|ICFFUX$HlJ-936@X}#hx_hTVUOry7-a0#6eeHT@4-XvWmYr{~qR{ZW z;axAy%}mN093EnXYRNW~P1eitK(&rHk^Iy}A>9&Hmi|e|l0%QQfx>_}JBLzz)$h zX|icf{ZzBnvwa^K%uwoU_R&~r(%M~b{ZmG*QMfuXLb)Vq^PpopQznW}EC?AB);)NY zobw2+F&Bn!+U375fCZrwGPsp4*zJk)v1MN9KL&p%4kb(*&5d^uScNthDVC|t4m~jTy9?4m%sb;v6w4K z^RgUs9Lrul9U3-WVsCWd%Rq^x;*X!47B8G~`rYR*R2DK{$%~#TD?4{;Ecn=uS>JbW!9y9QG1)4H$A1YM*GIaJR3fnNx6=>^Q%m% z5-N4#wnUeG-CN~6^SGJwvUk_`bNFk7`b#7}OuC;do1