1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-06 21:01:02 +01:00

Merge branch 'master' into redesign

This commit is contained in:
epriestley 2014-05-29 15:01:46 -07:00
commit 09a3506821
83 changed files with 820 additions and 492 deletions

View file

@ -992,6 +992,7 @@ return array(
'bash' => 'Bash Scripting', 'bash' => 'Bash Scripting',
'brainfuck' => 'Brainf*ck', 'brainfuck' => 'Brainf*ck',
'c' => 'C', 'c' => 'C',
'coffee-script' => 'CoffeeScript',
'cpp' => 'C++', 'cpp' => 'C++',
'css' => 'CSS', 'css' => 'CSS',
'd' => 'D', 'd' => 'D',
@ -999,14 +1000,18 @@ return array(
'django' => 'Django Templating', 'django' => 'Django Templating',
'erb' => 'Embedded Ruby/ERB', 'erb' => 'Embedded Ruby/ERB',
'erlang' => 'Erlang', 'erlang' => 'Erlang',
'go' => 'Golang',
'groovy' => 'Groovy',
'haskell' => 'Haskell', 'haskell' => 'Haskell',
'html' => 'HTML', 'html' => 'HTML',
'java' => 'Java', 'java' => 'Java',
'js' => 'Javascript', 'js' => 'Javascript',
'json' => 'JSON',
'mysql' => 'MySQL', 'mysql' => 'MySQL',
'objc' => 'Objective-C', 'objc' => 'Objective-C',
'perl' => 'Perl', 'perl' => 'Perl',
'php' => 'PHP', 'php' => 'PHP',
'puppet' => 'Puppet',
'rest' => 'reStructuredText', 'rest' => 'reStructuredText',
'text' => 'Plain Text', 'text' => 'Plain Text',
'python' => 'Python', 'python' => 'Python',
@ -1014,6 +1019,7 @@ return array(
'remarkup' => 'Remarkup', 'remarkup' => 'Remarkup',
'ruby' => 'Ruby', 'ruby' => 'Ruby',
'xml' => 'XML', 'xml' => 'XML',
'yaml' => 'YAML',
), ),
// This is an override list of regular expressions which allows you to choose // This is an override list of regular expressions which allows you to choose
@ -1035,6 +1041,7 @@ return array(
// '@\\.([^.]+)\\.bak$@' => 1, // '@\\.([^.]+)\\.bak$@' => 1,
'@\.arcconfig$@' => 'js', '@\.arcconfig$@' => 'js',
'@\.arclint$@' => 'js',
'@\.divinerconfig$@' => 'js', '@\.divinerconfig$@' => 'js',
), ),

View file

@ -7,7 +7,7 @@
return array( return array(
'names' => 'names' =>
array( array(
'core.pkg.css' => 'ac63f8ac', 'core.pkg.css' => 'c94a698c',
'core.pkg.js' => '7db41c19', 'core.pkg.js' => '7db41c19',
'darkconsole.pkg.js' => 'ca8671ce', 'darkconsole.pkg.js' => 'ca8671ce',
'differential.pkg.css' => 'fbf57382', 'differential.pkg.css' => 'fbf57382',
@ -64,7 +64,6 @@ return array(
'rsrc/css/application/diffusion/commit-view.css' => '92d1e8f9', 'rsrc/css/application/diffusion/commit-view.css' => '92d1e8f9',
'rsrc/css/application/diffusion/diffusion-icons.css' => '384a0f7d', 'rsrc/css/application/diffusion/diffusion-icons.css' => '384a0f7d',
'rsrc/css/application/diffusion/diffusion-source.css' => '66fdf661', 'rsrc/css/application/diffusion/diffusion-source.css' => '66fdf661',
'rsrc/css/application/directory/phabricator-jump-nav.css' => 'f0c5e726',
'rsrc/css/application/feed/feed.css' => 'dd43ce00', 'rsrc/css/application/feed/feed.css' => 'dd43ce00',
'rsrc/css/application/files/global-drag-and-drop.css' => '697324ad', 'rsrc/css/application/files/global-drag-and-drop.css' => '697324ad',
'rsrc/css/application/flag/flag.css' => '5337623f', 'rsrc/css/application/flag/flag.css' => '5337623f',
@ -137,7 +136,7 @@ return array(
'rsrc/css/phui/phui-info-panel.css' => '27ea50a1', 'rsrc/css/phui/phui-info-panel.css' => '27ea50a1',
'rsrc/css/phui/phui-list.css' => '43ed2d93', 'rsrc/css/phui/phui-list.css' => '43ed2d93',
'rsrc/css/phui/phui-object-box.css' => 'ce92d8ec', 'rsrc/css/phui/phui-object-box.css' => 'ce92d8ec',
'rsrc/css/phui/phui-object-item-list-view.css' => '16003f41', 'rsrc/css/phui/phui-object-item-list-view.css' => '15c582b1',
'rsrc/css/phui/phui-pinboard-view.css' => '874c22f9', 'rsrc/css/phui/phui-pinboard-view.css' => '874c22f9',
'rsrc/css/phui/phui-property-list-view.css' => '2f7199e8', 'rsrc/css/phui/phui-property-list-view.css' => '2f7199e8',
'rsrc/css/phui/phui-remarkup-preview.css' => '19ad512b', 'rsrc/css/phui/phui-remarkup-preview.css' => '19ad512b',
@ -483,7 +482,7 @@ return array(
'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8',
'rsrc/js/phuix/PHUIXActionView.js' => '6e8cefa4', 'rsrc/js/phuix/PHUIXActionView.js' => '6e8cefa4',
'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca',
'rsrc/swf/aphlict.swf' => 'abac967d', 'rsrc/swf/aphlict.swf' => 'f22c1e40',
), ),
'symbols' => 'symbols' =>
array( array(
@ -707,7 +706,6 @@ return array(
'phabricator-flag-css' => '5337623f', 'phabricator-flag-css' => '5337623f',
'phabricator-hovercard' => '4f344388', 'phabricator-hovercard' => '4f344388',
'phabricator-hovercard-view-css' => '46a13cf0', 'phabricator-hovercard-view-css' => '46a13cf0',
'phabricator-jump-nav' => 'f0c5e726',
'phabricator-keyboard-shortcut' => '1ae869f2', 'phabricator-keyboard-shortcut' => '1ae869f2',
'phabricator-keyboard-shortcut-manager' => 'ad7a69ca', 'phabricator-keyboard-shortcut-manager' => 'ad7a69ca',
'phabricator-main-menu-view' => '72d1d2ef', 'phabricator-main-menu-view' => '72d1d2ef',
@ -768,7 +766,7 @@ return array(
'phui-info-panel-css' => '27ea50a1', 'phui-info-panel-css' => '27ea50a1',
'phui-list-view-css' => '43ed2d93', 'phui-list-view-css' => '43ed2d93',
'phui-object-box-css' => 'ce92d8ec', 'phui-object-box-css' => 'ce92d8ec',
'phui-object-item-list-view-css' => '16003f41', 'phui-object-item-list-view-css' => '15c582b1',
'phui-pinboard-view-css' => '874c22f9', 'phui-pinboard-view-css' => '874c22f9',
'phui-property-list-view-css' => '2f7199e8', 'phui-property-list-view-css' => '2f7199e8',
'phui-remarkup-preview-css' => '19ad512b', 'phui-remarkup-preview-css' => '19ad512b',
@ -2113,47 +2111,46 @@ return array(
8 => 'aphront-tokenizer-control-css', 8 => 'aphront-tokenizer-control-css',
9 => 'aphront-typeahead-control-css', 9 => 'aphront-typeahead-control-css',
10 => 'aphront-list-filter-view-css', 10 => 'aphront-list-filter-view-css',
11 => 'phabricator-jump-nav', 11 => 'phabricator-remarkup-css',
12 => 'phabricator-remarkup-css', 12 => 'syntax-highlighting-css',
13 => 'syntax-highlighting-css', 13 => 'aphront-pager-view-css',
14 => 'aphront-pager-view-css', 14 => 'phabricator-transaction-view-css',
15 => 'phabricator-transaction-view-css', 15 => 'aphront-tooltip-css',
16 => 'aphront-tooltip-css', 16 => 'phabricator-flag-css',
17 => 'phabricator-flag-css', 17 => 'aphront-error-view-css',
18 => 'aphront-error-view-css', 18 => 'sprite-remarkup-css',
19 => 'sprite-remarkup-css', 19 => 'sprite-gradient-css',
20 => 'sprite-gradient-css', 20 => 'sprite-menu-css',
21 => 'sprite-menu-css', 21 => 'sprite-apps-css',
22 => 'sprite-apps-css', 22 => 'sprite-apps-large-css',
23 => 'sprite-apps-large-css', 23 => 'phabricator-main-menu-view',
24 => 'phabricator-main-menu-view', 24 => 'phabricator-notification-css',
25 => 'phabricator-notification-css', 25 => 'phabricator-notification-menu-css',
26 => 'phabricator-notification-menu-css', 26 => 'lightbox-attachment-css',
27 => 'lightbox-attachment-css', 27 => 'phui-header-view-css',
28 => 'phui-header-view-css', 28 => 'phabricator-filetree-view-css',
29 => 'phabricator-filetree-view-css', 29 => 'phabricator-nav-view-css',
30 => 'phabricator-nav-view-css', 30 => 'phabricator-side-menu-view-css',
31 => 'phabricator-side-menu-view-css', 31 => 'phabricator-crumbs-view-css',
32 => 'phabricator-crumbs-view-css', 32 => 'phui-object-item-list-view-css',
33 => 'phui-object-item-list-view-css', 33 => 'global-drag-and-drop-css',
34 => 'global-drag-and-drop-css', 34 => 'phui-spacing-css',
35 => 'phui-spacing-css', 35 => 'phui-form-css',
36 => 'phui-form-css', 36 => 'phui-icon-view-css',
37 => 'phui-icon-view-css', 37 => 'phabricator-application-launch-view-css',
38 => 'phabricator-application-launch-view-css', 38 => 'phabricator-action-list-view-css',
39 => 'phabricator-action-list-view-css', 39 => 'phui-property-list-view-css',
40 => 'phui-property-list-view-css', 40 => 'phui-tag-view-css',
41 => 'phui-tag-view-css', 41 => 'phui-list-view-css',
42 => 'phui-list-view-css', 42 => 'font-fontawesome',
43 => 'font-fontawesome', 43 => 'phui-font-icon-base-css',
44 => 'phui-font-icon-base-css', 44 => 'sprite-main-header-css',
45 => 'sprite-main-header-css', 45 => 'phui-box-css',
46 => 'phui-box-css', 46 => 'phui-object-box-css',
47 => 'phui-object-box-css', 47 => 'phui-timeline-view-css',
48 => 'phui-timeline-view-css', 48 => 'sprite-tokens-css',
49 => 'sprite-tokens-css', 49 => 'tokens-css',
50 => 'tokens-css', 50 => 'phui-status-list-view-css',
51 => 'phui-status-list-view-css',
), ),
'core.pkg.js' => 'core.pkg.js' =>
array( array(

View file

@ -83,8 +83,6 @@ return array(
'aphront-typeahead-control-css', 'aphront-typeahead-control-css',
'aphront-list-filter-view-css', 'aphront-list-filter-view-css',
'phabricator-jump-nav',
'phabricator-remarkup-css', 'phabricator-remarkup-css',
'syntax-highlighting-css', 'syntax-highlighting-css',
'aphront-pager-view-css', 'aphront-pager-view-css',

View file

@ -32,7 +32,7 @@ foreach (new LiskMigrationIterator($table) as $revision) {
if (phid_get_type($dst) == PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) { if (phid_get_type($dst) == PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) {
// At least one old install ran into some issues here. Skip the row if we // At least one old install ran into some issues here. Skip the row if we
// can't figure out what the destination PHID is. See here: // can't figure out what the destination PHID is. See here:
// https://github.com/facebook/phabricator/pull/507 // https://github.com/phacility/phabricator/pull/507
continue; continue;
} }

View file

@ -119,21 +119,21 @@ confirm
if [[ ! -e libphutil ]] if [[ ! -e libphutil ]]
then then
git clone git://github.com/facebook/libphutil.git git clone git://github.com/phacility/libphutil.git
else else
(cd libphutil && git pull --rebase) (cd libphutil && git pull --rebase)
fi fi
if [[ ! -e arcanist ]] if [[ ! -e arcanist ]]
then then
git clone git://github.com/facebook/arcanist.git git clone git://github.com/phacility/arcanist.git
else else
(cd arcanist && git pull --rebase) (cd arcanist && git pull --rebase)
fi fi
if [[ ! -e phabricator ]] if [[ ! -e phabricator ]]
then then
git clone git://github.com/facebook/phabricator.git git clone git://github.com/phacility/phabricator.git
else else
(cd phabricator && git pull --rebase) (cd phabricator && git pull --rebase)
fi fi

View file

@ -64,21 +64,21 @@ fi
if [ ! -e libphutil ] if [ ! -e libphutil ]
then then
git clone git://github.com/facebook/libphutil.git git clone git://github.com/phacility/libphutil.git
else else
(cd libphutil && git pull --rebase) (cd libphutil && git pull --rebase)
fi fi
if [ ! -e arcanist ] if [ ! -e arcanist ]
then then
git clone git://github.com/facebook/arcanist.git git clone git://github.com/phacility/arcanist.git
else else
(cd arcanist && git pull --rebase) (cd arcanist && git pull --rebase)
fi fi
if [ ! -e phabricator ] if [ ! -e phabricator ]
then then
git clone git://github.com/facebook/phabricator.git git clone git://github.com/phacility/phabricator.git
else else
(cd phabricator && git pull --rebase) (cd phabricator && git pull --rebase)
fi fi

View file

@ -99,58 +99,3 @@ final class DarkConsoleErrorLogPlugin extends DarkConsolePlugin {
)); ));
} }
} }
/*
$data = $this->getData();
if (!$data) {
return
<x:frag>
<div class="mu">No errors.</div>
</x:frag>;
}
$markup = <table class="LConsoleErrors" />;
$alt = false;
foreach ($data as $error) {
$row = <tr class={$alt ? 'alt' : null} />;
$text = $error['error'];
$text = preg_replace('/\(in .* on line \d+\)$/', '', trim($text));
$trace = $error['trace'];
$trace = explode("\n", $trace);
if (!$trace) {
$trace = array('unknown@0@unknown');
}
foreach ($trace as $idx => $traceline) {
list($file, $line, $where) = array_merge(
explode('@', $traceline),
array('?', '?', '?'));
if ($where == 'DarkConsole->addError' ||
$where == 'debug_rlog') {
unset($trace[$idx]);
}
}
$row->appendChild(<th rowspan={count($trace)}>{$text}</th>);
foreach ($trace as $traceline) {
list($file, $line, $where) = array_merge(
explode('@', $traceline),
array('?', '?', '?'));
$row->appendChild(<td>{$file}:{$line}</td>);
$row->appendChild(<td>{$where}()</td>);
$markup->appendChild($row);
$row = <tr class={$alt ? 'alt' : null} />;
}
$alt = !$alt;
}
return
<x:frag>
<h1>Errors</h1>
<div class="LConsoleErrors">{$markup}</div>
</x:frag>;
*/

View file

@ -2,10 +2,6 @@
final class PhabricatorApplicationAudit extends PhabricatorApplication { final class PhabricatorApplicationAudit extends PhabricatorApplication {
public function getShortDescription() {
return pht('Audit Code');
}
public function getBaseURI() { public function getBaseURI() {
return '/audit/'; return '/audit/';
} }
@ -14,6 +10,10 @@ final class PhabricatorApplicationAudit extends PhabricatorApplication {
return 'audit'; return 'audit';
} }
public function getShortDescription() {
return pht('Browse and Audit Commits');
}
public function getHelpURI() { public function getHelpURI() {
return PhabricatorEnv::getDoclink('Audit User Guide'); return PhabricatorEnv::getDoclink('Audit User Guide');
} }

View file

@ -14,6 +14,10 @@ final class PhabricatorApplicationAuth extends PhabricatorApplication {
return 'authentication'; return 'authentication';
} }
public function getShortDescription() {
return pht('Configure Login and Registration');
}
public function getHelpURI() { public function getHelpURI() {
// NOTE: Although reasonable help exists for this in "Configuring Accounts // NOTE: Although reasonable help exists for this in "Configuring Accounts
// and Registration", specifying a help URI here means we get the menu // and Registration", specifying a help URI here means we get the menu

View file

@ -155,12 +155,10 @@ abstract class PhabricatorApplication
} }
public function getHelpURI() { public function getHelpURI() {
// TODO: When these applications get created, link to their docs: return null;
// }
// - Drydock
// - OAuth Server
public function getOverview() {
return null; return null;
} }

View file

@ -3,7 +3,7 @@
final class PhabricatorApplicationCalendar extends PhabricatorApplication { final class PhabricatorApplicationCalendar extends PhabricatorApplication {
public function getShortDescription() { public function getShortDescription() {
return pht('Dates and Stuff'); return pht('Upcoming Events');
} }
public function getFlavorText() { public function getFlavorText() {

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationChatLog extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Chat Log'); return pht('IRC Logs');
} }
public function getIconName() { public function getIconName() {

View file

@ -19,7 +19,7 @@ final class PhabricatorApplicationConduit extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return 'Conduit API Console'; return pht('Phabricator Developer API Console');
} }
public function getTitleGlyph() { public function getTitleGlyph() {

View file

@ -22,6 +22,10 @@ final class PhabricatorApplicationConfig extends PhabricatorApplication {
return false; return false;
} }
public function getShortDescription() {
return pht('Configure Phabricator');
}
public function getRoutes() { public function getRoutes() {
return array( return array(
'/config/' => array( '/config/' => array(

View file

@ -42,6 +42,7 @@ final class PhabricatorSyntaxHighlightingConfigOptions
'bash' => 'Bash Scripting', 'bash' => 'Bash Scripting',
'brainfuck' => 'Brainf*ck', 'brainfuck' => 'Brainf*ck',
'c' => 'C', 'c' => 'C',
'coffee-script' => 'CoffeeScript',
'cpp' => 'C++', 'cpp' => 'C++',
'css' => 'CSS', 'css' => 'CSS',
'd' => 'D', 'd' => 'D',
@ -49,15 +50,19 @@ final class PhabricatorSyntaxHighlightingConfigOptions
'django' => 'Django Templating', 'django' => 'Django Templating',
'erb' => 'Embedded Ruby/ERB', 'erb' => 'Embedded Ruby/ERB',
'erlang' => 'Erlang', 'erlang' => 'Erlang',
'go' => 'Golang',
'groovy' => 'Groovy',
'haskell' => 'Haskell', 'haskell' => 'Haskell',
'html' => 'HTML', 'html' => 'HTML',
'invisible' => 'Invisible', 'invisible' => 'Invisible',
'java' => 'Java', 'java' => 'Java',
'js' => 'Javascript', 'js' => 'Javascript',
'json' => 'JSON',
'mysql' => 'MySQL', 'mysql' => 'MySQL',
'objc' => 'Objective-C', 'objc' => 'Objective-C',
'perl' => 'Perl', 'perl' => 'Perl',
'php' => 'PHP', 'php' => 'PHP',
'puppet' => 'Puppet',
'rest' => 'reStructuredText', 'rest' => 'reStructuredText',
'text' => 'Plain Text', 'text' => 'Plain Text',
'python' => 'Python', 'python' => 'Python',
@ -65,6 +70,7 @@ final class PhabricatorSyntaxHighlightingConfigOptions
'remarkup' => 'Remarkup', 'remarkup' => 'Remarkup',
'ruby' => 'Ruby', 'ruby' => 'Ruby',
'xml' => 'XML', 'xml' => 'XML',
'yaml' => 'YAML',
)) ))
->setSummary( ->setSummary(
pht("Set the language list which appears in dropdowns.")) pht("Set the language list which appears in dropdowns."))
@ -77,6 +83,7 @@ final class PhabricatorSyntaxHighlightingConfigOptions
'wild', 'wild',
array( array(
'@\.arcconfig$@' => 'js', '@\.arcconfig$@' => 'js',
'@\.arclint$@' => 'js',
'@\.divinerconfig$@' => 'js', '@\.divinerconfig$@' => 'js',
)) ))
->setSummary( ->setSummary(

View file

@ -10,7 +10,7 @@ final class PhabricatorApplicationConpherence extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Messaging'); return pht('Send Messages');
} }
public function getIconName() { public function getIconName() {

View file

@ -11,7 +11,7 @@ final class PhabricatorApplicationCountdown extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Countdown Timers'); return pht('Countdown to Events');
} }
public function getTitleGlyph() { public function getTitleGlyph() {

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationDaemons extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Manage Daemons'); return pht('Manage Phabricator Daemons');
} }
public function getBaseURI() { public function getBaseURI() {

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationDashboard extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Such Data'); return pht('Create Custom Pages');
} }
public function getIconName() { public function getIconName() {

View file

@ -26,10 +26,14 @@ final class PhabricatorDashboardViewController
$crumbs = $this->buildApplicationCrumbs(); $crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Dashboard %d', $dashboard->getID())); $crumbs->addTextCrumb(pht('Dashboard %d', $dashboard->getID()));
$rendered_dashboard = id(new PhabricatorDashboardRenderingEngine()) if ($dashboard->getPanelPHIDs()) {
->setViewer($viewer) $rendered_dashboard = id(new PhabricatorDashboardRenderingEngine())
->setDashboard($dashboard) ->setViewer($viewer)
->renderDashboard(); ->setDashboard($dashboard)
->renderDashboard();
} else {
$rendered_dashboard = $this->buildEmptyView();
}
return $this->buildApplicationPage( return $this->buildApplicationPage(
array( array(
@ -50,9 +54,24 @@ final class PhabricatorDashboardViewController
id(new PHUIListItemView()) id(new PHUIListItemView())
->setIcon('fa-th') ->setIcon('fa-th')
->setName(pht('Manage Dashboard')) ->setName(pht('Manage Dashboard'))
->setHref($this->getApplicationURI()."manage/{$id}/")); ->setHref($this->getApplicationURI("manage/{$id}/")));
return $crumbs; return $crumbs;
} }
public function buildEmptyView() {
$id = $this->id;
$manage_uri = $this->getApplicationURI("manage/{$id}/");
return id(new AphrontErrorView())
->setSeverity(AphrontErrorView::SEVERITY_NODATA)
->appendChild(
pht('This dashboard has no panels '.
'yet. Use %s to add panels.',
phutil_tag(
'a',
array('href'=>$manage_uri),
pht('Manage Dashboard'))));
}
} }

View file

@ -36,6 +36,14 @@ final class PhabricatorApplicationDifferential extends PhabricatorApplication {
); );
} }
public function getOverview() {
return pht(<<<EOTEXT
Differential is a **code review application** which allows engineers to review,
discuss and approve changes to software.
EOTEXT
);
}
public function getRoutes() { public function getRoutes() {
return array( return array(
'/D(?P<id>[1-9]\d*)' => 'DifferentialRevisionViewController', '/D(?P<id>[1-9]\d*)' => 'DifferentialRevisionViewController',

View file

@ -44,7 +44,7 @@ final class DifferentialTestPlanField
protected function getCoreFieldRequiredErrorString() { protected function getCoreFieldRequiredErrorString() {
return pht( return pht(
'You must provide a test plan. Describe the actions you performed '. 'You must provide a test plan. Describe the actions you performed '.
'to verify the behvaior of this change.'); 'to verify the behavior of this change.');
} }
public function readValueFromRequest(AphrontRequest $request) { public function readValueFromRequest(AphrontRequest $request) {

View file

@ -3,7 +3,7 @@
final class PhabricatorApplicationDiffusion extends PhabricatorApplication { final class PhabricatorApplicationDiffusion extends PhabricatorApplication {
public function getShortDescription() { public function getShortDescription() {
return pht('Repository Browser'); return pht('Host and Browse Repositories');
} }
public function getBaseURI() { public function getBaseURI() {

View file

@ -9,6 +9,7 @@ final class DiffusionBrowseFileController extends DiffusionBrowseController {
public function processRequest() { public function processRequest() {
$request = $this->getRequest(); $request = $this->getRequest();
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
$viewer = $request->getUser();
$before = $request->getStr('before'); $before = $request->getStr('before');
if ($before) { if ($before) {
@ -17,7 +18,7 @@ final class DiffusionBrowseFileController extends DiffusionBrowseController {
$path = $drequest->getPath(); $path = $drequest->getPath();
$preferences = $request->getUser()->loadPreferences(); $preferences = $viewer->loadPreferences();
$show_blame = $request->getBool( $show_blame = $request->getBool(
'blame', 'blame',
@ -31,7 +32,7 @@ final class DiffusionBrowseFileController extends DiffusionBrowseController {
true)); true));
$view = $request->getStr('view'); $view = $request->getStr('view');
if ($request->isFormPost() && $view != 'raw') { if ($request->isFormPost() && $view != 'raw' && $viewer->isLoggedIn()) {
$preferences->setPreference( $preferences->setPreference(
PhabricatorUserPreferences::PREFERENCE_DIFFUSION_BLAME, PhabricatorUserPreferences::PREFERENCE_DIFFUSION_BLAME,
$show_blame); $show_blame);
@ -354,7 +355,7 @@ final class DiffusionBrowseFileController extends DiffusionBrowseController {
->setHref($base_uri->alter('blame', $blame_value)) ->setHref($base_uri->alter('blame', $blame_value))
->setIcon($blame_icon) ->setIcon($blame_icon)
->setUser($viewer) ->setUser($viewer)
->setRenderAsForm(true)); ->setRenderAsForm($viewer->isLoggedIn()));
if ($show_color) { if ($show_color) {
$highlight_text = pht('Disable Highlighting'); $highlight_text = pht('Disable Highlighting');
@ -372,7 +373,7 @@ final class DiffusionBrowseFileController extends DiffusionBrowseController {
->setHref($base_uri->alter('color', $highlight_value)) ->setHref($base_uri->alter('color', $highlight_value))
->setIcon($highlight_icon) ->setIcon($highlight_icon)
->setUser($viewer) ->setUser($viewer)
->setRenderAsForm(true)); ->setRenderAsForm($viewer->isLoggedIn()));
$href = null; $href = null;
if ($this->getRequest()->getStr('lint') !== null) { if ($this->getRequest()->getStr('lint') !== null) {

View file

@ -36,7 +36,7 @@ final class PhabricatorApplicationDiviner extends PhabricatorApplication {
} }
public function getApplicationGroup() { public function getApplicationGroup() {
return self::GROUP_COMMUNICATION; return self::GROUP_UTILITIES;
} }
public function getRemarkupRules() { public function getRemarkupRules() {

View file

@ -6,14 +6,14 @@ final class PhabricatorApplicationDoorkeeper extends PhabricatorApplication {
return false; return false;
} }
public function getBaseURI() {
return '/doorkeeper/';
}
public function shouldAppearInLaunchView() { public function shouldAppearInLaunchView() {
return false; return false;
} }
public function getShortDescription() {
return pht('Connect to Other Software');
}
public function getRemarkupRules() { public function getRemarkupRules() {
return array( return array(
new DoorkeeperRemarkupRuleAsana(), new DoorkeeperRemarkupRuleAsana(),

View file

@ -30,6 +30,10 @@ final class PhabricatorApplicationDrydock extends PhabricatorApplication {
return true; return true;
} }
public function getHelpURI() {
return PhabricatorEnv::getDoclink('Drydock User Guide');
}
public function getRoutes() { public function getRoutes() {
return array( return array(
'/drydock/' => array( '/drydock/' => array(

View file

@ -3,7 +3,7 @@
final class PhabricatorApplicationFact extends PhabricatorApplication { final class PhabricatorApplicationFact extends PhabricatorApplication {
public function getShortDescription() { public function getShortDescription() {
return 'Analyze Data'; return pht('Chart and Analyze Data');
} }
public function getName() { public function getName() {

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationFeed extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Review Activity'); return pht('Review Recent Activity');
} }
public function getIconName() { public function getIconName() {

View file

@ -3,7 +3,7 @@
final class PhabricatorApplicationFlags extends PhabricatorApplication { final class PhabricatorApplicationFlags extends PhabricatorApplication {
public function getShortDescription() { public function getShortDescription() {
return pht('Reminders'); return pht('Personal Bookmarks and Reminders');
} }
public function getBaseURI() { public function getBaseURI() {
@ -25,7 +25,7 @@ final class PhabricatorApplicationFlags extends PhabricatorApplication {
} }
public function getApplicationGroup() { public function getApplicationGroup() {
return self::GROUP_ORGANIZATION; return self::GROUP_UTILITIES;
} }
public function loadStatus(PhabricatorUser $user) { public function loadStatus(PhabricatorUser $user) {

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationHarbormaster extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Continuous Build'); return pht('Builds and Continuous Integration');
} }
public function getIconName() { public function getIconName() {

View file

@ -16,10 +16,6 @@ final class PhabricatorHomeMainController
public function processRequest() { public function processRequest() {
$user = $this->getRequest()->getUser(); $user = $this->getRequest()->getUser();
if ($this->filter == 'jump') {
return $this->buildJumpResponse();
}
$nav = $this->buildNav(); $nav = $this->buildNav();
$dashboard = PhabricatorDashboardInstall::getDashboard( $dashboard = PhabricatorDashboardInstall::getDashboard(
@ -92,8 +88,6 @@ final class PhabricatorHomeMainController
$welcome_panel = null; $welcome_panel = null;
} }
$jump_panel = $this->buildJumpPanel();
if ($has_differential) { if ($has_differential) {
$revision_panel = $this->buildRevisionPanel(); $revision_panel = $this->buildRevisionPanel();
} else { } else {
@ -101,7 +95,6 @@ final class PhabricatorHomeMainController
} }
$content = array( $content = array(
$jump_panel,
$welcome_panel, $welcome_panel,
$unbreak_panel, $unbreak_panel,
$triage_panel, $triage_panel,
@ -118,27 +111,6 @@ final class PhabricatorHomeMainController
} }
private function buildJumpResponse() {
$request = $this->getRequest();
$jump = $request->getStr('jump');
$response = PhabricatorJumpNavHandler::getJumpResponse(
$request->getUser(),
$jump);
if ($response) {
return $response;
} else if ($request->isFormPost()) {
$uri = new PhutilURI('/search/');
$uri->setQueryParam('query', $jump);
$uri->setQueryParam('search:primary', 'true');
return id(new AphrontRedirectResponse())->setURI((string)$uri);
} else {
return id(new AphrontRedirectResponse())->setURI('/');
}
}
private function buildUnbreakNowPanel() { private function buildUnbreakNowPanel() {
$unbreak_now = PhabricatorEnv::getEnvConfig( $unbreak_now = PhabricatorEnv::getEnvConfig(
'maniphest.priorities.unbreak-now'); 'maniphest.priorities.unbreak-now');
@ -330,73 +302,6 @@ final class PhabricatorHomeMainController
return $view; return $view;
} }
private function buildJumpPanel($query=null) {
$request = $this->getRequest();
$user = $request->getUser();
$uniq_id = celerity_generate_unique_node_id();
Javelin::initBehavior(
'phabricator-autofocus',
array(
'id' => $uniq_id,
));
require_celerity_resource('phabricator-jump-nav');
$doc_href = PhabricatorEnv::getDocLink('Jump Nav User Guide');
$doc_link = phutil_tag(
'a',
array(
'href' => $doc_href,
),
'Jump Nav User Guide');
$jump_input = phutil_tag(
'input',
array(
'type' => 'text',
'class' => 'phabricator-jump-nav',
'name' => 'jump',
'id' => $uniq_id,
'value' => $query,
));
$jump_caption = phutil_tag(
'p',
array(
'class' => 'phabricator-jump-nav-caption',
),
hsprintf(
'Enter the name of an object like <tt>D123</tt> to quickly jump to '.
'it. See %s or type <tt>help</tt>.',
$doc_link));
$form = phabricator_form(
$user,
array(
'action' => '/jump/',
'method' => 'POST',
'class' => 'phabricator-jump-nav-form',
),
array(
$jump_input,
$jump_caption,
));
$panel = new AphrontPanelView();
$panel->setNoBackground();
// $panel->appendChild();
$list_filter = new AphrontListFilterView();
$list_filter->appendChild($form);
$container = phutil_tag('div',
array('class' => 'phabricator-jump-nav-container'),
$list_filter);
return $container;
}
private function renderSectionHeader($title, $href) { private function renderSectionHeader($title, $href) {
$header = phutil_tag( $header = phutil_tag(
'a', 'a',

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationLegalpad extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Legal Documents'); return pht('Agreements and Signatures');
} }
public function getIconName() { public function getIconName() {

View file

@ -218,9 +218,9 @@ EOTEXT
->setSummary(pht("Custom Maniphest fields.")) ->setSummary(pht("Custom Maniphest fields."))
->setDescription( ->setDescription(
pht( pht(
"Array of custom fields for Maniphest tasks. For details on ". 'Array of custom fields for Maniphest tasks. For details on '.
"adding custom fields to Maniphest, see 'Maniphest User Guide: ". 'adding custom fields to Maniphest, see "Configuring Custom '.
"Adding Custom Fields'.")) 'Fields" in the documentation.'))
->addExample( ->addExample(
'{"mycompany:estimated-hours": {"name": "Estimated Hours", '. '{"mycompany:estimated-hours": {"name": "Estimated Hours", '.
'"type": "int", "caption": "Estimated number of hours this will '. '"type": "int", "caption": "Estimated number of hours this will '.

View file

@ -11,7 +11,7 @@ final class PhabricatorApplicationApplications extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return 'Installed Applications'; return pht('Explore More Applications');
} }
public function getIconName() { public function getIconName() {
@ -26,7 +26,7 @@ final class PhabricatorApplicationApplications extends PhabricatorApplication {
return self::GROUP_ADMIN; return self::GROUP_ADMIN;
} }
public function getRoutes() { public function getRoutes() {
return array( return array(
'/applications/' => array( '/applications/' => array(
'(?:query/(?P<queryKey>[^/]+)/)?' => '(?:query/(?P<queryKey>[^/]+)/)?' =>
@ -38,7 +38,6 @@ final class PhabricatorApplicationApplications extends PhabricatorApplication {
'(?P<application>\w+)/(?P<action>install|uninstall)/' => '(?P<application>\w+)/(?P<action>install|uninstall)/' =>
'PhabricatorApplicationUninstallController', 'PhabricatorApplicationUninstallController',
), ),
); );
} }

View file

@ -1,10 +1,14 @@
<?php <?php
final class PhabricatorApplicationDetailViewController final class PhabricatorApplicationDetailViewController
extends PhabricatorApplicationsController{ extends PhabricatorApplicationsController {
private $application; private $application;
public function shouldAllowPublic() {
return true;
}
public function willProcessRequest(array $data) { public function willProcessRequest(array $data) {
$this->application = $data['application']; $this->application = $data['application'];
} }
@ -61,16 +65,37 @@ final class PhabricatorApplicationDetailViewController
$viewer = $this->getRequest()->getUser(); $viewer = $this->getRequest()->getUser();
$properties = id(new PHUIPropertyListView()) $properties = id(new PHUIPropertyListView());
->addProperty(pht('Description'), $application->getShortDescription());
$properties->setActionList($actions); $properties->setActionList($actions);
$properties->addProperty(
pht('Description'),
$application->getShortDescription());
if ($application->getFlavorText()) {
$properties->addProperty(
null,
phutil_tag('em', array(), $application->getFlavorText()));
}
if ($application->isBeta()) { if ($application->isBeta()) {
$properties->addProperty( $properties->addProperty(
pht('Release'), pht('Release'),
pht('Beta')); pht('Beta'));
} }
$overview = $application->getOverview();
if ($overview) {
$properties->addSectionHeader(
pht('Overview'),
PHUIPropertyListView::ICON_SUMMARY);
$properties->addTextContent(
PhabricatorMarkupEngine::renderOneObject(
id(new PhabricatorMarkupOneOff())->setContent($overview),
'default',
$viewer));
}
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
$viewer, $viewer,
$application); $application);
@ -94,6 +119,14 @@ final class PhabricatorApplicationDetailViewController
->setUser($user) ->setUser($user)
->setObjectURI($this->getRequest()->getRequestURI()); ->setObjectURI($this->getRequest()->getRequestURI());
if ($selected->getHelpURI()) {
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Help / Documentation'))
->setIcon('fa-life-ring')
->setHref($selected->getHelpURI()));
}
$can_edit = PhabricatorPolicyFilter::hasCapability( $can_edit = PhabricatorPolicyFilter::hasCapability(
$user, $user,
$selected, $selected,

View file

@ -1,10 +1,14 @@
<?php <?php
final class PhabricatorApplicationEditController final class PhabricatorApplicationEditController
extends PhabricatorApplicationsController{ extends PhabricatorApplicationsController {
private $application; private $application;
public function shouldRequireAdmin() {
return true;
}
public function willProcessRequest(array $data) { public function willProcessRequest(array $data) {
$this->application = $data['application']; $this->application = $data['application'];
} }

View file

@ -6,6 +6,10 @@ final class PhabricatorApplicationUninstallController
private $application; private $application;
private $action; private $action;
public function shouldRequireAdmin() {
return true;
}
public function willProcessRequest(array $data) { public function willProcessRequest(array $data) {
$this->application = $data['application']; $this->application = $data['application'];
$this->action = $data['action']; $this->action = $data['action'];

View file

@ -2,10 +2,6 @@
abstract class PhabricatorApplicationsController extends PhabricatorController { abstract class PhabricatorApplicationsController extends PhabricatorController {
public function shouldRequireAdmin() {
return true;
}
public function buildSideNavView($for_app = false) { public function buildSideNavView($for_app = false) {
$user = $this->getRequest()->getUser(); $user = $this->getRequest()->getUser();

View file

@ -5,6 +5,10 @@ final class PhabricatorApplicationsListController
private $queryKey; private $queryKey;
public function shouldAllowPublic() {
return true;
}
public function willProcessRequest(array $data) { public function willProcessRequest(array $data) {
$this->queryKey = idx($data, 'queryKey'); $this->queryKey = idx($data, 'queryKey');
} }

View file

@ -25,6 +25,9 @@ final class PhabricatorAppSearchEngine
$saved->setParameter( $saved->setParameter(
'firstParty', 'firstParty',
$this->readBoolFromRequest($request, 'firstParty')); $this->readBoolFromRequest($request, 'firstParty'));
$saved->setParameter(
'launchable',
$this->readBoolFromRequest($request, 'launchable'));
return $saved; return $saved;
} }
@ -54,6 +57,11 @@ final class PhabricatorAppSearchEngine
$query->withFirstParty($first_party); $query->withFirstParty($first_party);
} }
$launchable = $saved->getParameter('launchable');
if ($launchable !== null) {
$query->withLaunchable($launchable);
}
return $query; return $query;
} }
@ -99,6 +107,17 @@ final class PhabricatorAppSearchEngine
'' => pht('Show All Applications'), '' => pht('Show All Applications'),
'true' => pht('Show First-Party Applications'), 'true' => pht('Show First-Party Applications'),
'false' => pht('Show Third-Party Applications'), 'false' => pht('Show Third-Party Applications'),
)))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Launchable'))
->setName('launchable')
->setValue($this->getBoolFromQuery($saved, 'launchable'))
->setOptions(
array(
'' => pht('Show All Applications'),
'true' => pht('Show Launchable Applications'),
'false' => pht('Show Non-Launchable Applications'),
))); )));
} }
@ -109,6 +128,7 @@ final class PhabricatorAppSearchEngine
public function getBuiltinQueryNames() { public function getBuiltinQueryNames() {
$names = array( $names = array(
'launcher' => pht('Launcher'),
'all' => pht('All Applications'), 'all' => pht('All Applications'),
); );
@ -121,6 +141,10 @@ final class PhabricatorAppSearchEngine
$query->setQueryKey($query_key); $query->setQueryKey($query_key);
switch ($query_key) { switch ($query_key) {
case 'launcher':
return $query
->setParameter('installed', true)
->setParameter('launchable', true);
case 'all': case 'all':
return $query; return $query;
} }
@ -129,33 +153,93 @@ final class PhabricatorAppSearchEngine
} }
protected function renderResultList( protected function renderResultList(
array $applications, array $all_applications,
PhabricatorSavedQuery $query, PhabricatorSavedQuery $query,
array $handle) { array $handle) {
assert_instances_of($applications, 'PhabricatorApplication'); assert_instances_of($all_applications, 'PhabricatorApplication');
$list = new PHUIObjectItemListView(); $all_applications = msort($all_applications, 'getName');
$applications = msort($applications, 'getName'); if ($query->getQueryKey() == 'launcher') {
$groups = mgroup($all_applications, 'getApplicationGroup');
foreach ($applications as $application) { } else {
$item = id(new PHUIObjectItemView()) $groups = array($all_applications);
->setHeader($application->getName())
->setHref('/applications/view/'.get_class($application).'/')
->addAttribute($application->getShortDescription());
if (!$application->isInstalled()) {
$item->addIcon('delete', pht('Uninstalled'));
}
if ($application->isBeta()) {
$item->addIcon('lint-warning', pht('Beta'));
}
$list->addItem($item);
} }
return $list; $group_names = PhabricatorApplication::getApplicationGroups();
$groups = array_select_keys($groups, array_keys($group_names)) + $groups;
$results = array();
foreach ($groups as $group => $applications) {
if (count($groups) > 1) {
$results[] = phutil_tag(
'h1',
array(
'class' => 'launcher-header',
),
idx($group_names, $group, $group));
}
$list = new PHUIObjectItemListView();
$list->addClass('phui-object-item-launcher-list');
foreach ($applications as $application) {
$icon = $application->getIconName();
if (!$icon) {
$icon = 'application';
}
// TODO: This sheet doesn't work the same way other sheets do so it
// ends up with the wrong classes if we try to use PHUIIconView. This
// is probably all changing in the redesign anyway.
$icon_view = javelin_tag(
'span',
array(
'class' => 'phui-icon-view '.
'sprite-apps-large apps-'.$icon.'-dark-large',
'aural' => false,
),
'');
$description = phutil_tag(
'div',
array(
'style' => 'white-space: nowrap; '.
'overflow: hidden; '.
'text-overflow: ellipsis;',
),
$application->getShortDescription());
$item = id(new PHUIObjectItemView())
->setHeader($application->getName())
->setImageIcon($icon_view)
->addAttribute($description)
->addAction(
id(new PHUIListItemView())
->setName(pht('Help/Options'))
->setIcon('fa-cog')
->setHref('/applications/view/'.get_class($application).'/'));
if ($application->getBaseURI()) {
$item->setHref($application->getBaseURI());
}
if (!$application->isInstalled()) {
$item->addIcon('delete', pht('Uninstalled'));
}
if ($application->isBeta()) {
$item->addIcon('fa-star-half-o grey', pht('Beta'));
}
$list->addItem($item);
}
$results[] = $list;
}
return $results;
} }
} }

View file

@ -9,6 +9,7 @@ final class PhabricatorApplicationQuery
private $nameContains; private $nameContains;
private $unlisted; private $unlisted;
private $classes; private $classes;
private $launchable;
private $phids; private $phids;
const ORDER_APPLICATION = 'order:application'; const ORDER_APPLICATION = 'order:application';
@ -41,6 +42,11 @@ final class PhabricatorApplicationQuery
return $this; return $this;
} }
public function withLaunchable($launchable) {
$this->launchable = $launchable;
return $this;
}
public function withClasses(array $classes) { public function withClasses(array $classes) {
$this->classes = $classes; $this->classes = $classes;
return $this; return $this;
@ -117,6 +123,15 @@ final class PhabricatorApplicationQuery
} }
} }
if ($this->launchable !== null) {
foreach ($apps as $key => $app) {
if ($app->shouldAppearInLaunchView() != $this->launchable) {
unset($apps[$key]);
}
}
}
switch ($this->order) { switch ($this->order) {
case self::ORDER_NAME: case self::ORDER_NAME:
$apps = msort($apps, 'getName'); $apps = msort($apps, 'getName');

View file

@ -2,14 +2,14 @@
final class PhabricatorApplicationMetaMTA extends PhabricatorApplication { final class PhabricatorApplicationMetaMTA extends PhabricatorApplication {
public function getBaseURI() {
return '/mail/';
}
public function getIconName() { public function getIconName() {
return 'metamta'; return 'metamta';
} }
public function getShortDescription() {
return pht('Delivers Mail');
}
public function getFlavorText() { public function getFlavorText() {
return pht('Yo dawg, we heard you like MTAs.'); return pht('Yo dawg, we heard you like MTAs.');
} }

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationNotifications extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Beep Beep Bloop'); return pht('Real-Time Updates and Alerts');
} }
public function getRoutes() { public function getRoutes() {

View file

@ -27,6 +27,10 @@ final class PhabricatorApplicationNuance extends PhabricatorApplication {
return '/nuance/'; return '/nuance/';
} }
public function getShortDescription() {
return pht('High-Volume Task Queues');
}
public function getRoutes() { public function getRoutes() {
return array( return array(
'/nuance/' => array( '/nuance/' => array(

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationOAuthServer extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('OAuth Provider'); return pht('OAuth Login Provider');
} }
public function getIconName() { public function getIconName() {
@ -23,13 +23,17 @@ final class PhabricatorApplicationOAuthServer extends PhabricatorApplication {
} }
public function getApplicationGroup() { public function getApplicationGroup() {
return self::GROUP_UTILITIES; return self::GROUP_ADMIN;
} }
public function isBeta() { public function isBeta() {
return true; return true;
} }
public function getHelpURI() {
return PhabricatorEnv::getDoclink('Using the Phabricator OAuth Server');
}
public function getRoutes() { public function getRoutes() {
return array( return array(
'/oauthserver/' => array( '/oauthserver/' => array(

View file

@ -11,7 +11,7 @@ final class PhabricatorApplicationOwners extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Group Source Code'); return pht('Track Ownership of Source Code');
} }
public function getTitleGlyph() { public function getTitleGlyph() {
@ -27,7 +27,7 @@ final class PhabricatorApplicationOwners extends PhabricatorApplication {
} }
public function getApplicationGroup() { public function getApplicationGroup() {
return self::GROUP_ORGANIZATION; return self::GROUP_UTILITIES;
} }
public function getRoutes() { public function getRoutes() {

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationPassphrase extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Credential Management'); return pht('Store Passwords and Credentials');
} }
public function getIconName() { public function getIconName() {

View file

@ -26,23 +26,18 @@ final class PassphraseCredentialEditController extends PassphraseController {
return new Aphront404Response(); return new Aphront404Response();
} }
$type = PassphraseCredentialType::getTypeByConstant( $type = $this->getCredentialType($credential->getCredentialType());
$credential->getCredentialType());
if (!$type) {
throw new Exception(pht('Credential has invalid type "%s"!', $type));
}
if (!$type->isCreateable()) {
throw new Exception(
pht('Credential has noncreateable type "%s"!', $type));
}
$is_new = false; $is_new = false;
} else { } else {
$type_const = $request->getStr('type'); $type_const = $request->getStr('type');
$type = PassphraseCredentialType::getTypeByConstant($type_const); $type = $this->getCredentialType($type_const);
if (!$type) {
return new Aphront404Response(); if (!$type->isCreateable()) {
throw new Exception(
pht(
'Credential has noncreateable type "%s"!',
$credential->getCredentialType()));
} }
$credential = PassphraseCredential::initializeNewCredential($viewer) $credential = PassphraseCredential::initializeNewCredential($viewer)
@ -358,4 +353,15 @@ final class PassphraseCredentialEditController extends PassphraseController {
)); ));
} }
private function getCredentialType($type_const) {
$type = PassphraseCredentialType::getTypeByConstant($type_const);
if (!$type) {
throw new Exception(
pht('Credential has invalid type "%s"!', $type_const));
}
return $type;
}
} }

View file

@ -18,6 +18,10 @@ final class PhabricatorApplicationPaste extends PhabricatorApplication {
return self::GROUP_UTILITIES; return self::GROUP_UTILITIES;
} }
public function getShortDescription() {
return pht('Share Text Snippets');
}
public function getRemarkupRules() { public function getRemarkupRules() {
return array( return array(
new PhabricatorPasteRemarkupRule(), new PhabricatorPasteRemarkupRule(),

View file

@ -3,7 +3,7 @@
final class PhabricatorApplicationPeople extends PhabricatorApplication { final class PhabricatorApplicationPeople extends PhabricatorApplication {
public function getShortDescription() { public function getShortDescription() {
return pht('User Accounts'); return pht('User Accounts and Profiles');
} }
public function getBaseURI() { public function getBaseURI() {

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationPhlux extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Configuration Store'); return pht('Key/Value Configuration Store');
} }
public function getIconName() { public function getIconName() {

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationPholio extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Design Review'); return pht('Review Mocks and Design');
} }
public function getIconName() { public function getIconName() {

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationPhortune extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Account and Billing'); return pht('Accounts and Billing');
} }
public function getIconName() { public function getIconName() {

View file

@ -3,7 +3,7 @@
final class PhabricatorApplicationPhrequent extends PhabricatorApplication { final class PhabricatorApplicationPhrequent extends PhabricatorApplication {
public function getShortDescription() { public function getShortDescription() {
return pht('Track Time'); return pht('Track Time Spent');
} }
public function getBaseURI() { public function getBaseURI() {
@ -19,7 +19,7 @@ final class PhabricatorApplicationPhrequent extends PhabricatorApplication {
} }
public function getApplicationGroup() { public function getApplicationGroup() {
return self::GROUP_ORGANIZATION; return self::GROUP_UTILITIES;
} }
public function getApplicationOrder() { public function getApplicationOrder() {

View file

@ -23,6 +23,11 @@ final class PhrequentTimeBlock extends Phobject {
public function getObjectTimeRanges($now) { public function getObjectTimeRanges($now) {
$ranges = array(); $ranges = array();
$range_start = time();
foreach ($this->events as $event) {
$range_start = min($range_start, $event->getDateStarted());
}
$object_ranges = array(); $object_ranges = array();
foreach ($this->events as $event) { foreach ($this->events as $event) {

View file

@ -14,10 +14,12 @@ final class PhabricatorPolicyDataTestCase extends PhabricatorTestCase {
$proj_a = id(new PhabricatorProject()) $proj_a = id(new PhabricatorProject())
->setName('A') ->setName('A')
->setAuthorPHID($author->getPHID()) ->setAuthorPHID($author->getPHID())
->setIcon('fa-briefcase')
->save(); ->save();
$proj_b = id(new PhabricatorProject()) $proj_b = id(new PhabricatorProject())
->setName('B') ->setName('B')
->setAuthorPHID($author->getPHID()) ->setAuthorPHID($author->getPHID())
->setIcon('fa-briefcase')
->save(); ->save();
$proj_a->setViewPolicy($proj_b->getPHID())->save(); $proj_a->setViewPolicy($proj_b->getPHID())->save();

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationPonder extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Find Answers'); return pht('Questions and Answers');
} }
public function getIconName() { public function getIconName() {

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationProject extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Organize Work'); return pht('Create Groups, Tags, and Projects');
} }
public function getBaseURI() { public function getBaseURI() {

View file

@ -305,8 +305,15 @@ final class PhabricatorProjectTransactionEditor
$slug_xaction = last($xactions); $slug_xaction = last($xactions);
$new = $slug_xaction->getNewValue(); $new = $slug_xaction->getNewValue();
$slugs_used_already = id(new PhabricatorProjectSlug())
->loadAllWhere('slug IN (%Ls)', $new); if ($new) {
$slugs_used_already = id(new PhabricatorProjectSlug())
->loadAllWhere('slug IN (%Ls)', $new);
} else {
// The project doesn't have any extra slugs.
$slugs_used_already = array();
}
$slugs_used_already = mgroup($slugs_used_already, 'getProjectPHID'); $slugs_used_already = mgroup($slugs_used_already, 'getProjectPHID');
foreach ($slugs_used_already as $project_phid => $used_slugs) { foreach ($slugs_used_already as $project_phid => $used_slugs) {
$used_slug_strs = mpull($used_slugs, 'getSlug'); $used_slug_strs = mpull($used_slugs, 'getSlug');

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationReleeph extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Release Branches'); return pht('Pull Requests');
} }
public function getBaseURI() { public function getBaseURI() {

View file

@ -14,7 +14,7 @@ final class PhabricatorApplicationRepositories extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return 'Track Repositories'; return pht('(Deprecated)');
} }
public function getTitleGlyph() { public function getTitleGlyph() {

View file

@ -384,7 +384,7 @@ final class PhabricatorRepositoryPullEngine
// This behavior has been reverted, but users who updated between Feb 1, // This behavior has been reverted, but users who updated between Feb 1,
// 2012 and Mar 1, 2012 will have the erroring version. Do a dumb test // 2012 and Mar 1, 2012 will have the erroring version. Do a dumb test
// against stdout to check for this possibility. // against stdout to check for this possibility.
// See: https://github.com/facebook/phabricator/issues/101/ // See: https://github.com/phacility/phabricator/issues/101/
// NOTE: Mercurial has translated versions, which translate this error // NOTE: Mercurial has translated versions, which translate this error
// string. In a translated version, the string will be something else, // string. In a translated version, the string will be something else,

View file

@ -58,6 +58,10 @@ final class PhabricatorRepositoryManagementParentsWorkflow
$graph = array(); $graph = array();
foreach ($refs as $ref) { foreach ($refs as $ref) {
if (!$repo->shouldTrackBranch($ref->getRefName())) {
continue;
}
$console->writeOut( $console->writeOut(
"%s\n", "%s\n",
pht('Rebuilding branch "%s"...', $ref->getRefName())); pht('Rebuilding branch "%s"...', $ref->getRefName()));

View file

@ -11,7 +11,7 @@ final class PhabricatorApplicationSearch extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Search & Find'); return pht('Full-Text Search');
} }
public function getFlavorText() { public function getFlavorText() {

View file

@ -97,7 +97,7 @@ final class PhabricatorSearchEngineElastic extends PhabricatorSearchEngine {
if (strlen($query->getParameter('query'))) { if (strlen($query->getParameter('query'))) {
$spec[] = array( $spec[] = array(
'field' => array( 'term' => array(
'field.corpus' => $query->getParameter('query'), 'field.corpus' => $query->getParameter('query'),
), ),
); );

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationSettings extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return 'User Preferences'; return pht('User Preferences');
} }
public function getIconName() { public function getIconName() {
@ -18,6 +18,10 @@ final class PhabricatorApplicationSettings extends PhabricatorApplication {
return false; return false;
} }
public function shouldAppearInLaunchView() {
return false;
}
public function getRoutes() { public function getRoutes() {
return array( return array(
'/settings/' => array( '/settings/' => array(

View file

@ -19,7 +19,7 @@ final class PhabricatorApplicationTokens extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return pht('Acquire Trinkets'); return pht('Award and Acquire Trinkets');
} }
public function getApplicationGroup() { public function getApplicationGroup() {

View file

@ -7,7 +7,7 @@ final class PhabricatorApplicationUIExamples extends PhabricatorApplication {
} }
public function getShortDescription() { public function getShortDescription() {
return 'Developer UI Examples'; return pht('Phabricator Developer UI Examples');
} }
public function getIconName() { public function getIconName() {

View file

@ -39,7 +39,7 @@ requests, general questions, or random feedback this way, too.
= GitHub Issues = = GitHub Issues =
You can also use You can also use
[[https://github.com/facebook/phabricator/issues/new | GitHub Issues]] if you [[https://github.com/phacility/phabricator/issues/new | GitHub Issues]] if you
prefer. prefer.
= IRC = = IRC =

View file

@ -95,9 +95,9 @@ Now that you have all that stuff installed, grab Phabricator and its
dependencies: dependencies:
$ cd somewhere/ # pick some install directory $ cd somewhere/ # pick some install directory
somewhere/ $ git clone git://github.com/facebook/libphutil.git somewhere/ $ git clone git://github.com/phacility/libphutil.git
somewhere/ $ git clone git://github.com/facebook/arcanist.git somewhere/ $ git clone git://github.com/phacility/arcanist.git
somewhere/ $ git clone git://github.com/facebook/phabricator.git somewhere/ $ git clone git://github.com/phacility/phabricator.git
= Installing APC (Optional) = = Installing APC (Optional) =

View file

@ -92,8 +92,8 @@ have PHP installed, you can download it from <http://www.php.net/>.
To install Arcanist, pick an install directory and clone the code from GitHub: To install Arcanist, pick an install directory and clone the code from GitHub:
some_install_path/ $ git clone git://github.com/facebook/libphutil.git some_install_path/ $ git clone git://github.com/phacility/libphutil.git
some_install_path/ $ git clone git://github.com/facebook/arcanist.git some_install_path/ $ git clone git://github.com/phacility/arcanist.git
This should leave you with a directory structure like this This should leave you with a directory structure like this
@ -162,7 +162,7 @@ several sources:
The first place where the setting is defined wins. The first place where the setting is defined wins.
Existing settings can be printed with `arc set-config --show`. Existing settings can be printed with `arc get-config`.
== Next Steps == == Next Steps ==

View file

@ -74,7 +74,7 @@ These options are supported, but their use is discouraged:
solution to certificate validity problems, and is discouraged. Instead, solution to certificate validity problems, and is discouraged. Instead,
use valid certificates. use valid certificates.
For a complete list of options, run `arc set-config --show`. Although all For a complete list of options, run `arc get-config`. Although all
options can be set in `.arcconfig`, some options (like `editor`) usually do not options can be set in `.arcconfig`, some options (like `editor`) usually do not
make sense to set here because they're likely to vary from user to user. make sense to set here because they're likely to vary from user to user.

View file

@ -23,8 +23,8 @@ Then install Arcanist itself:
$ mkdir somewhere/ $ mkdir somewhere/
$ cd somewhere/ $ cd somewhere/
somewhere/ $ git clone git://github.com/facebook/libphutil.git somewhere/ $ git clone git://github.com/phacility/libphutil.git
somewhere/ $ git clone git://github.com/facebook/arcanist.git somewhere/ $ git clone git://github.com/phacility/arcanist.git
Add `arc` to your path: Add `arc` to your path:

View file

@ -142,7 +142,6 @@ final class PHUIFeedStoryView extends AphrontView {
require_celerity_resource('phui-feed-story-css'); require_celerity_resource('phui-feed-story-css');
Javelin::initBehavior('phabricator-hovercards'); Javelin::initBehavior('phabricator-hovercards');
$oneline = !$this->hasChildren();
$body = null; $body = null;
$foot = null; $foot = null;
@ -186,18 +185,6 @@ final class PHUIFeedStoryView extends AphrontView {
$icon->setSpriteSheet(PHUIIconView::SPRITE_APPS); $icon->setSpriteSheet(PHUIIconView::SPRITE_APPS);
} }
$ol_foot = null;
if ($oneline) {
$ol_foot = phutil_tag(
'div',
array(
'class' => 'phui-feed-story-oneline-foot'
),
array(
$icon,
$foot));
}
$action_list = array(); $action_list = array();
$icons = null; $icons = null;
foreach ($this->actions as $action) { foreach ($this->actions as $action) {
@ -223,10 +210,9 @@ final class PHUIFeedStoryView extends AphrontView {
'class' => 'phui-feed-story-head', 'class' => 'phui-feed-story-head',
), ),
array( array(
(!$oneline ? $actor : null), $actor,
nonempty($this->title, pht('Untitled Story')), nonempty($this->title, pht('Untitled Story')),
$icons, $icons,
$ol_foot
)); ));
if (!empty($this->tokenBar)) { if (!empty($this->tokenBar)) {
@ -249,23 +235,16 @@ final class PHUIFeedStoryView extends AphrontView {
$body_content); $body_content);
} }
if ($oneline) { $foot = phutil_tag(
$foot = null; 'div',
} else { array(
$foot = phutil_tag( 'class' => 'phui-feed-story-foot',
'div', ),
array( array(
'class' => 'phui-feed-story-foot', $icon,
), $foot));
array(
$icon,
$foot));
}
$classes = array('phui-feed-story'); $classes = array('phui-feed-story');
if ($oneline) {
$classes[] = 'phui-feed-story-oneline';
}
return id(new PHUIBoxView()) return id(new PHUIBoxView())
->addClass(implode(' ', $classes)) ->addClass(implode(' ', $classes))
@ -282,6 +261,15 @@ final class PHUIFeedStoryView extends AphrontView {
case PhabricatorMacroPHIDTypeMacro::TYPECONST: case PhabricatorMacroPHIDTypeMacro::TYPECONST:
$this->setAppIcon("macro-dark"); $this->setAppIcon("macro-dark");
break; break;
case ManiphestPHIDTypeTask::TYPECONST:
$this->setAppIcon('maniphest-dark');
break;
case DifferentialPHIDTypeRevision::TYPECONST:
$this->setAppIcon('differential-dark');
break;
case PhabricatorCalendarPHIDTypeEvent::TYPECONST:
$this->setAppIcon('calendar-dark');
break;
} }
} }
} }

View file

@ -21,6 +21,7 @@ final class PHUIObjectItemView extends AphrontTagView {
private $imageURI; private $imageURI;
private $state; private $state;
private $fontIcon; private $fontIcon;
private $imageIcon;
const AGE_FRESH = 'fresh'; const AGE_FRESH = 'fresh';
const AGE_STALE = 'stale'; const AGE_STALE = 'stale';
@ -115,6 +116,15 @@ final class PHUIObjectItemView extends AphrontTagView {
return $this->imageURI; return $this->imageURI;
} }
public function setImageIcon($image_icon) {
$this->imageIcon = $image_icon;
return $this;
}
public function getImageIcon() {
return $this->imageIcon;
}
public function setState($state) { public function setState($state) {
$this->state = $state; $this->state = $state;
switch ($state) { switch ($state) {
@ -288,6 +298,10 @@ final class PHUIObjectItemView extends AphrontTagView {
$item_classes[] = 'phui-object-item-with-image'; $item_classes[] = 'phui-object-item-with-image';
} }
if ($this->getImageIcon()) {
$item_classes[] = 'phui-object-item-with-image-icon';
}
if ($this->fontIcon) { if ($this->fontIcon) {
$item_classes[] = 'phui-object-item-with-ficon'; $item_classes[] = 'phui-object-item-with-ficon';
} }
@ -520,6 +534,22 @@ final class PHUIObjectItemView extends AphrontTagView {
'style' => 'background-image: url('.$this->getImageURI().')', 'style' => 'background-image: url('.$this->getImageURI().')',
), ),
''); '');
} else if ($this->getImageIcon()) {
$image = phutil_tag(
'div',
array(
'class' => 'phui-object-item-image-icon',
),
$this->getImageIcon());
}
if ($image && $this->href) {
$image = phutil_tag(
'a',
array(
'href' => $this->href,
),
$image);
} }
$ficon = null; $ficon = null;

View file

@ -9,20 +9,12 @@ if [ -z "$MXMLC" ]; then
fi; fi;
set -e set -e
set -x
# cp -R $ROOT/externals/vegas/src $BASEDIR/src/vegas $MXMLC \
-output=$ROOT/webroot/rsrc/swf/aphlict.swf \
(cd $BASEDIR && $MXMLC \
-output aphlict.swf \
-default-background-color=0x444444 \ -default-background-color=0x444444 \
-default-size=500,500 \ -default-size=500,500 \
-warnings=true \ -warnings=true \
-debug=true \
-source-path=$ROOT/externals/vegas/src \ -source-path=$ROOT/externals/vegas/src \
-static-link-runtime-shared-libraries=true \ -static-link-runtime-shared-libraries=true \
src/Aphlict.as) $BASEDIR/src/AphlictClient.as
mv $BASEDIR/aphlict.swf $ROOT/webroot/rsrc/swf/aphlict.swf
# -target-player=10.2.0 \

View file

@ -1,117 +1,38 @@
package { package {
import flash.net.*; import flash.display.Sprite;
import flash.utils.*;
import flash.media.*;
import flash.display.*;
import flash.events.*;
import flash.external.ExternalInterface; import flash.external.ExternalInterface;
import flash.net.LocalConnection;
import vegas.strings.JSON;
public class Aphlict extends Sprite { public class Aphlict extends Sprite {
private var client:String; /**
* A transport channel used to receive data.
*/
protected var recv:LocalConnection;
private var socket:Socket; /**
private var readBuffer:ByteArray; * A transport channel used to send data.
*/
protected var send:LocalConnection;
private var remoteServer:String;
private var remotePort:Number;
public function Aphlict() { public function Aphlict() {
super(); super();
ExternalInterface.addCallback('connect', this.externalConnect); this.recv = new LocalConnection();
ExternalInterface.call( this.recv.client = this;
'JX.Stratcom.invoke',
'aphlict-component-ready', this.send = new LocalConnection();
null,
{});
} }
public function externalConnect(server:String, port:Number):void { protected function externalInvoke(type:String, object:Object = null):void {
this.externalInvoke('connect');
this.remoteServer = server;
this.remotePort = port;
this.connectToServer();
}
public function connectToServer():void {
var socket:Socket = new Socket();
socket.addEventListener(Event.CONNECT, didConnectSocket);
socket.addEventListener(Event.CLOSE, didCloseSocket);
socket.addEventListener(ProgressEvent.SOCKET_DATA, didReceiveSocket);
socket.addEventListener(IOErrorEvent.IO_ERROR, didIOErrorSocket);
socket.addEventListener(
SecurityErrorEvent.SECURITY_ERROR,
didSecurityErrorSocket);
socket.connect(this.remoteServer, this.remotePort);
this.readBuffer = new ByteArray();
this.socket = socket;
}
private function didConnectSocket(event:Event):void {
this.externalInvoke('connected');
}
private function didCloseSocket(event:Event):void {
this.externalInvoke('close');
}
private function didIOErrorSocket(event:IOErrorEvent):void {
this.externalInvoke('error', event.text);
}
private function didSecurityErrorSocket(event:SecurityErrorEvent):void {
this.externalInvoke('error', event.text);
}
private function didReceiveSocket(event:Event):void {
var b:ByteArray = this.readBuffer;
this.socket.readBytes(b, b.length);
do {
b = this.readBuffer;
b.position = 0;
if (b.length <= 8) {
break;
}
var msg_len:Number = parseInt(b.readUTFBytes(8), 10);
if (b.length >= msg_len + 8) {
var bytes:String = b.readUTFBytes(msg_len);
var data:Object = vegas.strings.JSON.deserialize(bytes);
var t:ByteArray = new ByteArray();
t.writeBytes(b, msg_len + 8);
this.readBuffer = t;
this.receiveMessage(data);
} else {
break;
}
} while (true);
}
public function receiveMessage(msg:Object):void {
this.externalInvoke('receive', msg);
}
public function externalInvoke(type:String, object:Object = null):void {
ExternalInterface.call('JX.Aphlict.didReceiveEvent', type, object); ExternalInterface.call('JX.Aphlict.didReceiveEvent', type, object);
} }
public function log(message:String):void { protected function log(message:String):void {
ExternalInterface.call('console.log', message); this.externalInvoke('log', message);
} }
} }

View file

@ -0,0 +1,129 @@
package {
import flash.events.TimerEvent;
import flash.external.ExternalInterface;
import flash.utils.Timer;
public class AphlictClient extends Aphlict {
/**
* The connection name for this client. This will be used for the
* @{class:LocalConnection} object.
*/
private var client:String;
/**
* The expiry timestamp for the @{class:AphlictMaster}. If this time is
* elapsed then the master will be assumed to be dead and another
* @{class:AphlictClient} will create a master.
*/
private var expiry:Number = 0;
/**
* The interval at which to ping the @{class:AphlictMaster}.
*/
public static const INTERVAL:Number = 3000;
private var master:AphlictMaster;
private var timer:Timer;
private var remoteServer:String;
private var remotePort:Number;
public function AphlictClient() {
super();
ExternalInterface.addCallback('connect', this.externalConnect);
ExternalInterface.call(
'JX.Stratcom.invoke',
'aphlict-component-ready',
null,
{});
}
public function externalConnect(server:String, port:Number):void {
this.externalInvoke('connect');
this.remoteServer = server;
this.remotePort = port;
this.client = AphlictClient.generateClientId();
this.recv.connect(this.client);
this.timer = new Timer(AphlictClient.INTERVAL);
this.timer.addEventListener(TimerEvent.TIMER, this.keepalive);
this.connectToMaster();
}
/**
* Generate a unique identifier that will be used to communicate with the
* @{class:AphlictMaster}.
*/
private static function generateClientId():String {
return 'aphlict_client_' + Math.round(Math.random() * 100000);
}
/**
* Create a new connection to the @{class:AphlictMaster}.
*
* If there is no current @{class:AphlictMaster} instance, then a new master
* will be created.
*/
private function connectToMaster():void {
this.timer.stop();
// Try to become the master.
try {
this.log('Attempting to become the master...');
this.master = new AphlictMaster(this.remoteServer, this.remotePort);
this.log('I am the master.');
} catch (x:Error) {
// Couldn't become the master
this.log('Cannot become the master... probably one already exists');
}
this.send.send('aphlict_master', 'register', this.client);
this.expiry = new Date().getTime() + (5 * AphlictClient.INTERVAL);
this.log('Registered client ' + this.client);
this.timer.start();
}
/**
* Send a keepalive signal to the @{class:AphlictMaster}.
*
* If the connection to the master has expired (because the master has not
* sent a heartbeat signal), then a new connection to master will be
* created.
*/
private function keepalive(event:TimerEvent):void {
if (new Date().getTime() > this.expiry) {
this.connectToMaster();
}
this.send.send('aphlict_master', 'ping', this.client);
}
/**
* This function is used to receive the heartbeat signal from the
* @{class:AphlictMaster}.
*/
public function pong():void {
this.expiry = new Date().getTime() + (2 * AphlictClient.INTERVAL);
}
/**
* Receive a message from the Aphlict Server, via the
* @{class:AphlictMaster}.
*/
public function receiveMessage(msg:Object):void {
this.log('Received message.');
this.externalInvoke('receive', msg);
}
}
}

View file

@ -0,0 +1,166 @@
package {
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.events.TimerEvent;
import flash.net.Socket;
import flash.utils.ByteArray;
import flash.utils.Dictionary;
import flash.utils.Timer;
import vegas.strings.JSON;
public class AphlictMaster extends Aphlict {
/**
* The pool of connected clients.
*/
private var clients:Dictionary;
/**
* A timer used to trigger periodic events.
*/
private var timer:Timer;
/**
* The interval after which clients will be considered dead and removed
* from the pool.
*/
public static const PURGE_INTERVAL:Number = 3 * AphlictClient.INTERVAL;
/**
* The hostname for the Aphlict Server.
*/
private var remoteServer:String;
/**
* The port number for the Aphlict Server.
*/
private var remotePort:Number;
private var socket:Socket;
private var readBuffer:ByteArray;
public function AphlictMaster(server:String, port:Number) {
super();
this.remoteServer = server;
this.remotePort = port;
// Connect to the Aphlict Server.
this.recv.connect('aphlict_master');
this.connectToServer();
this.clients = new Dictionary();
// Start a timer and regularly purge dead clients.
this.timer = new Timer(AphlictMaster.PURGE_INTERVAL);
this.timer.addEventListener(TimerEvent.TIMER, this.purgeClients);
this.timer.start();
}
/**
* Register a @{class:AphlictClient}.
*/
public function register(client:String):void {
if (!this.clients[client]) {
this.log('Registering client: ' + client);
this.clients[client] = new Date().getTime();
}
}
/**
* Purge stale client connections from the client pool.
*/
private function purgeClients(event:TimerEvent):void {
for (var client:String in this.clients) {
var checkin:Number = this.clients[client];
if (new Date().getTime() - checkin > AphlictMaster.PURGE_INTERVAL) {
this.log('Purging client: ' + client);
delete this.clients[client];
}
}
}
/**
* Clients will regularly "ping" the master to let us know that they are
* still alive. We will "pong" them back to let the client know that the
* master is still alive.
*/
public function ping(client:String):void {
this.clients[client] = new Date().getTime();
this.send.send(client, 'pong');
}
private function connectToServer():void {
var socket:Socket = new Socket();
socket.addEventListener(Event.CONNECT, didConnectSocket);
socket.addEventListener(Event.CLOSE, didCloseSocket);
socket.addEventListener(ProgressEvent.SOCKET_DATA, didReceiveSocket);
socket.addEventListener(IOErrorEvent.IO_ERROR, didIOErrorSocket);
socket.addEventListener(
SecurityErrorEvent.SECURITY_ERROR,
didSecurityErrorSocket);
socket.connect(this.remoteServer, this.remotePort);
this.readBuffer = new ByteArray();
this.socket = socket;
}
private function didConnectSocket(event:Event):void {
this.externalInvoke('connected');
}
private function didCloseSocket(event:Event):void {
this.externalInvoke('close');
}
private function didIOErrorSocket(event:IOErrorEvent):void {
this.externalInvoke('error', event.text);
}
private function didSecurityErrorSocket(event:SecurityErrorEvent):void {
this.externalInvoke('error', event.text);
}
private function didReceiveSocket(event:Event):void {
var b:ByteArray = this.readBuffer;
this.socket.readBytes(b, b.length);
do {
b = this.readBuffer;
b.position = 0;
if (b.length <= 8) {
break;
}
var msg_len:Number = parseInt(b.readUTFBytes(8), 10);
if (b.length >= msg_len + 8) {
var bytes:String = b.readUTFBytes(msg_len);
var data:Object = vegas.strings.JSON.deserialize(bytes);
var t:ByteArray = new ByteArray();
t.writeBytes(b, msg_len + 8);
this.readBuffer = t;
// Send the message to all clients.
for (var client:String in this.clients) {
this.log('Sending message to client: ' + client);
this.send.send(client, 'receiveMessage', data);
}
} else {
break;
}
} while (true);
}
}
}

View file

@ -1,25 +0,0 @@
/**
* @provides phabricator-jump-nav
*/
.phabricator-jump-nav-form {
text-align: center;
padding: 0px;
margin: 0;
}
input.phabricator-jump-nav[type='text'] {
font-size: 16px;
width: 100%;
}
.phabricator-jump-nav-caption {
margin-top: 4px;
font-size: 11px;
color: {$greytext};
text-align: left;
}
.phabricator-jump-nav-container form {
padding: 12px 16px;
}

View file

@ -671,3 +671,54 @@
border: none; border: none;
border-bottom: 1px solid {$thinblueborder}; border-bottom: 1px solid {$thinblueborder};
} }
/* - Launcher List ---------------------------------------------------------- */
.launcher-header {
margin: 8px 16px -4px;
clear: both;
color: {$darkbluetext};
}
.launcher-header:nth-of-type(1) {
margin-top: 24px;
}
.phui-object-item-launcher-list {
overflow: hidden;
}
.device-desktop .phui-object-item-launcher-list .phui-object-item {
width: 32.333%;
float: left;
margin-right: 1%;
box-sizing: border-box;
}
.phui-object-item-image-icon {
background: none;
}
.phui-object-item-image-icon {
width: 30px;
height: 30px;
margin: 4px 4px 4px 4px;
position: absolute;
}
.phui-object-item-image-icon .phui-icon-view {
position: absolute;
width: 28px;
height: 28px;
left: 6px;
top: 6px;
}
.phui-object-item-with-image-icon .phui-object-item-frame {
min-height: 48px;
}
.phui-object-item-with-image-icon .phui-object-item-content-box {
margin-left: 44px;
}

Binary file not shown.