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

View file

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

View file

@ -83,8 +83,6 @@ return array(
'aphront-typeahead-control-css',
'aphront-list-filter-view-css',
'phabricator-jump-nav',
'phabricator-remarkup-css',
'syntax-highlighting-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) {
// 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:
// https://github.com/facebook/phabricator/pull/507
// https://github.com/phacility/phabricator/pull/507
continue;
}

View file

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

View file

@ -64,21 +64,21 @@ fi
if [ ! -e libphutil ]
then
git clone git://github.com/facebook/libphutil.git
git clone git://github.com/phacility/libphutil.git
else
(cd libphutil && git pull --rebase)
fi
if [ ! -e arcanist ]
then
git clone git://github.com/facebook/arcanist.git
git clone git://github.com/phacility/arcanist.git
else
(cd arcanist && git pull --rebase)
fi
if [ ! -e phabricator ]
then
git clone git://github.com/facebook/phabricator.git
git clone git://github.com/phacility/phabricator.git
else
(cd phabricator && git pull --rebase)
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 {
public function getShortDescription() {
return pht('Audit Code');
}
public function getBaseURI() {
return '/audit/';
}
@ -14,6 +10,10 @@ final class PhabricatorApplicationAudit extends PhabricatorApplication {
return 'audit';
}
public function getShortDescription() {
return pht('Browse and Audit Commits');
}
public function getHelpURI() {
return PhabricatorEnv::getDoclink('Audit User Guide');
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -26,10 +26,14 @@ final class PhabricatorDashboardViewController
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Dashboard %d', $dashboard->getID()));
$rendered_dashboard = id(new PhabricatorDashboardRenderingEngine())
->setViewer($viewer)
->setDashboard($dashboard)
->renderDashboard();
if ($dashboard->getPanelPHIDs()) {
$rendered_dashboard = id(new PhabricatorDashboardRenderingEngine())
->setViewer($viewer)
->setDashboard($dashboard)
->renderDashboard();
} else {
$rendered_dashboard = $this->buildEmptyView();
}
return $this->buildApplicationPage(
array(
@ -50,9 +54,24 @@ final class PhabricatorDashboardViewController
id(new PHUIListItemView())
->setIcon('fa-th')
->setName(pht('Manage Dashboard'))
->setHref($this->getApplicationURI()."manage/{$id}/"));
->setHref($this->getApplicationURI("manage/{$id}/")));
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() {
return array(
'/D(?P<id>[1-9]\d*)' => 'DifferentialRevisionViewController',

View file

@ -44,7 +44,7 @@ final class DifferentialTestPlanField
protected function getCoreFieldRequiredErrorString() {
return pht(
'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) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -16,10 +16,6 @@ final class PhabricatorHomeMainController
public function processRequest() {
$user = $this->getRequest()->getUser();
if ($this->filter == 'jump') {
return $this->buildJumpResponse();
}
$nav = $this->buildNav();
$dashboard = PhabricatorDashboardInstall::getDashboard(
@ -92,8 +88,6 @@ final class PhabricatorHomeMainController
$welcome_panel = null;
}
$jump_panel = $this->buildJumpPanel();
if ($has_differential) {
$revision_panel = $this->buildRevisionPanel();
} else {
@ -101,7 +95,6 @@ final class PhabricatorHomeMainController
}
$content = array(
$jump_panel,
$welcome_panel,
$unbreak_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() {
$unbreak_now = PhabricatorEnv::getEnvConfig(
'maniphest.priorities.unbreak-now');
@ -330,73 +302,6 @@ final class PhabricatorHomeMainController
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) {
$header = phutil_tag(
'a',

View file

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

View file

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

View file

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

View file

@ -1,10 +1,14 @@
<?php
final class PhabricatorApplicationDetailViewController
extends PhabricatorApplicationsController{
extends PhabricatorApplicationsController {
private $application;
public function shouldAllowPublic() {
return true;
}
public function willProcessRequest(array $data) {
$this->application = $data['application'];
}
@ -61,16 +65,37 @@ final class PhabricatorApplicationDetailViewController
$viewer = $this->getRequest()->getUser();
$properties = id(new PHUIPropertyListView())
->addProperty(pht('Description'), $application->getShortDescription());
$properties = id(new PHUIPropertyListView());
$properties->setActionList($actions);
$properties->addProperty(
pht('Description'),
$application->getShortDescription());
if ($application->getFlavorText()) {
$properties->addProperty(
null,
phutil_tag('em', array(), $application->getFlavorText()));
}
if ($application->isBeta()) {
$properties->addProperty(
pht('Release'),
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(
$viewer,
$application);
@ -94,6 +119,14 @@ final class PhabricatorApplicationDetailViewController
->setUser($user)
->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(
$user,
$selected,

View file

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

View file

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

View file

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

View file

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

View file

@ -25,6 +25,9 @@ final class PhabricatorAppSearchEngine
$saved->setParameter(
'firstParty',
$this->readBoolFromRequest($request, 'firstParty'));
$saved->setParameter(
'launchable',
$this->readBoolFromRequest($request, 'launchable'));
return $saved;
}
@ -54,6 +57,11 @@ final class PhabricatorAppSearchEngine
$query->withFirstParty($first_party);
}
$launchable = $saved->getParameter('launchable');
if ($launchable !== null) {
$query->withLaunchable($launchable);
}
return $query;
}
@ -99,6 +107,17 @@ final class PhabricatorAppSearchEngine
'' => pht('Show All Applications'),
'true' => pht('Show First-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() {
$names = array(
'launcher' => pht('Launcher'),
'all' => pht('All Applications'),
);
@ -121,6 +141,10 @@ final class PhabricatorAppSearchEngine
$query->setQueryKey($query_key);
switch ($query_key) {
case 'launcher':
return $query
->setParameter('installed', true)
->setParameter('launchable', true);
case 'all':
return $query;
}
@ -129,33 +153,93 @@ final class PhabricatorAppSearchEngine
}
protected function renderResultList(
array $applications,
array $all_applications,
PhabricatorSavedQuery $query,
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');
foreach ($applications as $application) {
$item = id(new PHUIObjectItemView())
->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);
if ($query->getQueryKey() == 'launcher') {
$groups = mgroup($all_applications, 'getApplicationGroup');
} else {
$groups = array($all_applications);
}
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 $unlisted;
private $classes;
private $launchable;
private $phids;
const ORDER_APPLICATION = 'order:application';
@ -41,6 +42,11 @@ final class PhabricatorApplicationQuery
return $this;
}
public function withLaunchable($launchable) {
$this->launchable = $launchable;
return $this;
}
public function withClasses(array $classes) {
$this->classes = $classes;
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) {
case self::ORDER_NAME:
$apps = msort($apps, 'getName');

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -26,23 +26,18 @@ final class PassphraseCredentialEditController extends PassphraseController {
return new Aphront404Response();
}
$type = PassphraseCredentialType::getTypeByConstant(
$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));
}
$type = $this->getCredentialType($credential->getCredentialType());
$is_new = false;
} else {
$type_const = $request->getStr('type');
$type = PassphraseCredentialType::getTypeByConstant($type_const);
if (!$type) {
return new Aphront404Response();
$type = $this->getCredentialType($type_const);
if (!$type->isCreateable()) {
throw new Exception(
pht(
'Credential has noncreateable type "%s"!',
$credential->getCredentialType()));
}
$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;
}
public function getShortDescription() {
return pht('Share Text Snippets');
}
public function getRemarkupRules() {
return array(
new PhabricatorPasteRemarkupRule(),

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -305,8 +305,15 @@ final class PhabricatorProjectTransactionEditor
$slug_xaction = last($xactions);
$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');
foreach ($slugs_used_already as $project_phid => $used_slugs) {
$used_slug_strs = mpull($used_slugs, 'getSlug');

View file

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

View file

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

View file

@ -384,7 +384,7 @@ final class PhabricatorRepositoryPullEngine
// 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
// 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
// string. In a translated version, the string will be something else,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -39,7 +39,7 @@ requests, general questions, or random feedback this way, too.
= GitHub Issues =
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.
= IRC =

View file

@ -95,9 +95,9 @@ Now that you have all that stuff installed, grab Phabricator and its
dependencies:
$ cd somewhere/ # pick some install directory
somewhere/ $ git clone git://github.com/facebook/libphutil.git
somewhere/ $ git clone git://github.com/facebook/arcanist.git
somewhere/ $ git clone git://github.com/facebook/phabricator.git
somewhere/ $ git clone git://github.com/phacility/libphutil.git
somewhere/ $ git clone git://github.com/phacility/arcanist.git
somewhere/ $ git clone git://github.com/phacility/phabricator.git
= 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:
some_install_path/ $ git clone git://github.com/facebook/libphutil.git
some_install_path/ $ git clone git://github.com/facebook/arcanist.git
some_install_path/ $ git clone git://github.com/phacility/libphutil.git
some_install_path/ $ git clone git://github.com/phacility/arcanist.git
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.
Existing settings can be printed with `arc set-config --show`.
Existing settings can be printed with `arc get-config`.
== 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,
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
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/
$ cd somewhere/
somewhere/ $ git clone git://github.com/facebook/libphutil.git
somewhere/ $ git clone git://github.com/facebook/arcanist.git
somewhere/ $ git clone git://github.com/phacility/libphutil.git
somewhere/ $ git clone git://github.com/phacility/arcanist.git
Add `arc` to your path:

View file

@ -142,7 +142,6 @@ final class PHUIFeedStoryView extends AphrontView {
require_celerity_resource('phui-feed-story-css');
Javelin::initBehavior('phabricator-hovercards');
$oneline = !$this->hasChildren();
$body = null;
$foot = null;
@ -186,18 +185,6 @@ final class PHUIFeedStoryView extends AphrontView {
$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();
$icons = null;
foreach ($this->actions as $action) {
@ -223,10 +210,9 @@ final class PHUIFeedStoryView extends AphrontView {
'class' => 'phui-feed-story-head',
),
array(
(!$oneline ? $actor : null),
$actor,
nonempty($this->title, pht('Untitled Story')),
$icons,
$ol_foot
));
if (!empty($this->tokenBar)) {
@ -249,23 +235,16 @@ final class PHUIFeedStoryView extends AphrontView {
$body_content);
}
if ($oneline) {
$foot = null;
} else {
$foot = phutil_tag(
'div',
array(
'class' => 'phui-feed-story-foot',
),
array(
$icon,
$foot));
}
$foot = phutil_tag(
'div',
array(
'class' => 'phui-feed-story-foot',
),
array(
$icon,
$foot));
$classes = array('phui-feed-story');
if ($oneline) {
$classes[] = 'phui-feed-story-oneline';
}
return id(new PHUIBoxView())
->addClass(implode(' ', $classes))
@ -282,6 +261,15 @@ final class PHUIFeedStoryView extends AphrontView {
case PhabricatorMacroPHIDTypeMacro::TYPECONST:
$this->setAppIcon("macro-dark");
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 $state;
private $fontIcon;
private $imageIcon;
const AGE_FRESH = 'fresh';
const AGE_STALE = 'stale';
@ -115,6 +116,15 @@ final class PHUIObjectItemView extends AphrontTagView {
return $this->imageURI;
}
public function setImageIcon($image_icon) {
$this->imageIcon = $image_icon;
return $this;
}
public function getImageIcon() {
return $this->imageIcon;
}
public function setState($state) {
$this->state = $state;
switch ($state) {
@ -288,6 +298,10 @@ final class PHUIObjectItemView extends AphrontTagView {
$item_classes[] = 'phui-object-item-with-image';
}
if ($this->getImageIcon()) {
$item_classes[] = 'phui-object-item-with-image-icon';
}
if ($this->fontIcon) {
$item_classes[] = 'phui-object-item-with-ficon';
}
@ -520,6 +534,22 @@ final class PHUIObjectItemView extends AphrontTagView {
'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;

View file

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

View file

@ -1,117 +1,38 @@
package {
import flash.net.*;
import flash.utils.*;
import flash.media.*;
import flash.display.*;
import flash.events.*;
import flash.display.Sprite;
import flash.external.ExternalInterface;
import flash.net.LocalConnection;
import vegas.strings.JSON;
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() {
super();
ExternalInterface.addCallback('connect', this.externalConnect);
ExternalInterface.call(
'JX.Stratcom.invoke',
'aphlict-component-ready',
null,
{});
this.recv = new LocalConnection();
this.recv.client = this;
this.send = new LocalConnection();
}
public function externalConnect(server:String, port:Number):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 {
protected function externalInvoke(type:String, object:Object = null):void {
ExternalInterface.call('JX.Aphlict.didReceiveEvent', type, object);
}
public function log(message:String):void {
ExternalInterface.call('console.log', message);
protected function log(message:String):void {
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-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.