1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-28 16:30:59 +01:00

Merge branch 'master' into phutil_tag

(Final sync.)
This commit is contained in:
epriestley 2013-02-05 10:23:16 -08:00
commit 8f1311bbc1
41 changed files with 589 additions and 201 deletions

View file

@ -801,7 +801,8 @@ return array(
// Show stack traces when unhandled exceptions occur, force reloading of
// static resources (skipping the cache), show an error callout if a page
// generated PHP errors, warnings, or notices, force disk reads when
// reloading. This option should not be enabled in production.
// reloading, and generally make development easier. This option should not
// be enabled in production.
'phabricator.developer-mode' => false,
// When users write comments which have URIs, they'll be automatically linked

View file

@ -0,0 +1,33 @@
<?php
echo "Migrating Differential unsubscribed users to edges...\n";
$table = new DifferentialRevision();
$table->openTransaction();
// We couldn't use new LiskMigrationIterator($table) because the $unsubscribed
// property gets deleted.
$revs = queryfx_all(
$table->establishConnection('w'),
'SELECT id, phid, unsubscribed FROM differential_revision');
foreach ($revs as $rev) {
echo ".";
$unsubscribed = json_decode($rev['unsubscribed']);
if (!$unsubscribed) {
continue;
}
$editor = new PhabricatorEdgeEditor();
$editor->setSuppressEvents(true);
foreach ($unsubscribed as $user_phid => $_) {
$editor->addEdge(
$rev['phid'],
PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER,
$user_phid);
}
$editor->save();
}
$table->saveTransaction();
echo "Done.\n";

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_differential.differential_revision
DROP unsubscribed;

View file

@ -1226,6 +1226,7 @@ phutil_register_library_map(array(
'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php',
'PhabricatorSettingsPanelAccount' => 'applications/settings/panel/PhabricatorSettingsPanelAccount.php',
'PhabricatorSettingsPanelConduit' => 'applications/settings/panel/PhabricatorSettingsPanelConduit.php',
'PhabricatorSettingsPanelDiffPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDiffPreferences.php',
'PhabricatorSettingsPanelDisplayPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDisplayPreferences.php',
'PhabricatorSettingsPanelEmailAddresses' => 'applications/settings/panel/PhabricatorSettingsPanelEmailAddresses.php',
'PhabricatorSettingsPanelEmailPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelEmailPreferences.php',
@ -2625,6 +2626,7 @@ phutil_register_library_map(array(
'PhabricatorSettingsMainController' => 'PhabricatorController',
'PhabricatorSettingsPanelAccount' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelConduit' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelDiffPreferences' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelDisplayPreferences' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelEmailAddresses' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelEmailPreferences' => 'PhabricatorSettingsPanel',

View file

@ -65,6 +65,20 @@ final class PhabricatorSetupCheckDatabase extends PhabricatorSetupCheck {
return;
}
if (PhabricatorEnv::getEnvConfig('phabricator.developer-mode')) {
$mode_string = queryfx_one($conn_raw, "SELECT @@sql_mode");
$modes = explode(',', $mode_string['@@sql_mode']);
if (!in_array('STRICT_ALL_TABLES', $modes)) {
$message = pht(
"The global sql_mode is not set to 'STRICT_ALL_TABLES'. It is ".
"recommended that you set this mode while developing Phabricator.");
$this->newIssue('mysql.mode')
->setName(pht('MySQL STRICT_ALL_TABLES mode not set.'))
->setMessage($message);
}
}
$namespace = PhabricatorEnv::getEnvConfig('storage.default-namespace');
$databases = queryfx_all($conn_raw, 'SHOW DATABASES');

View file

@ -77,15 +77,17 @@ final class ConpherenceListController extends
'class' => 'conpherence-header-pane',
'id' => 'conpherence-header-pane',
),
''),
''
),
phutil_tag(
'div',
array(
'class' => 'conpherence-widget-pane',
'id' => 'conpherence-widget-pane'
),
''),
phutil_tag(
''
),
javelin_tag(
'div',
array(
'class' => 'conpherence-message-pane',
@ -98,15 +100,19 @@ final class ConpherenceListController extends
'class' => 'conpherence-messages',
'id' => 'conpherence-messages'
),
''),
''
),
phutil_tag(
'div',
array(
'id' => 'conpherence-form'
),
''),
)),
));
''
)
)
)
)
);
}

View file

@ -95,8 +95,7 @@ final class ConpherenceNewController extends ConpherenceController {
phutil_tag(
'p',
array(),
pht('Message sent successfully.'))
);
pht('Message sent successfully.')));
$response = id(new AphrontDialogResponse())
->setDialog($dialog);
} else {

View file

@ -71,7 +71,7 @@ final class ConpherenceViewController extends
$edit_href = $this->getApplicationURI('update/'.$conpherence->getID().'/');
$header =
javelin_render_tag(
javelin_tag(
'a',
array(
'class' => 'edit',
@ -80,7 +80,7 @@ final class ConpherenceViewController extends
),
''
).
phutil_render_tag(
phutil_tag(
'div',
array(
'class' => 'header-image',
@ -88,19 +88,19 @@ final class ConpherenceViewController extends
),
''
).
phutil_render_tag(
phutil_tag(
'div',
array(
'class' => 'title',
),
phutil_escape_html($display_data['title'])
$display_data['title']
).
phutil_render_tag(
phutil_tag(
'div',
array(
'class' => 'subtitle',
),
phutil_escape_html($display_data['subtitle'])
$display_data['subtitle']
);
return array('header' => $header);
@ -152,6 +152,7 @@ final class ConpherenceViewController extends
private function renderWidgetPaneContent() {
require_celerity_resource('conpherence-widget-pane-css');
require_celerity_resource('sprite-conpher-css');
Javelin::initBehavior(
'conpherence-widget-pane',
array(
@ -165,7 +166,7 @@ final class ConpherenceViewController extends
$conpherence = $this->getConpherence();
$widgets = phutil_render_tag(
$widgets = phutil_tag(
'div',
array(
'class' => 'widgets-header'
@ -175,31 +176,44 @@ final class ConpherenceViewController extends
'a',
array(
'sigil' => 'conpherence-change-widget',
'meta' => array('widget' => 'widgets-files')
'meta' => array(
'widget' => 'widgets-files',
'toggleClass' => 'conpher_files_on'
),
'id' => 'widgets-files-toggle',
'class' => 'sprite-conpher conpher_files_off first-icon'
),
pht('Files')
''
),
' | ',
javelin_tag(
'a',
array(
'sigil' => 'conpherence-change-widget',
'meta' => array('widget' => 'widgets-tasks')
'meta' => array(
'widget' => 'widgets-tasks',
'toggleClass' => 'conpher_list_on'
),
'id' => 'widgets-tasks-toggle',
'class' => 'sprite-conpher conpher_list_off conpher_list_on',
),
pht('Tasks')
''
),
' | ',
javelin_tag(
'a',
array(
'sigil' => 'conpherence-change-widget',
'meta' => array('widget' => 'widgets-calendar')
'meta' => array(
'widget' => 'widgets-calendar',
'toggleClass' => 'conpher_calendar_on'
),
'id' => 'widgets-calendar-toggle',
'class' => 'sprite-conpher conpher_calendar_off',
),
pht('Calendar')
),
''
)
)
).
phutil_render_tag(
phutil_tag(
'div',
array(
'class' => 'widgets-body',
@ -208,7 +222,7 @@ final class ConpherenceViewController extends
),
$this->renderFilesWidgetPaneContent()
).
phutil_render_tag(
phutil_tag(
'div',
array(
'class' => 'widgets-body',
@ -216,7 +230,7 @@ final class ConpherenceViewController extends
),
$this->renderTaskWidgetPaneContent()
).
phutil_render_tag(
phutil_tag(
'div',
array(
'class' => 'widgets-body',
@ -253,7 +267,7 @@ final class ConpherenceViewController extends
->setNoDataString(pht('No files attached to conpherence.'))
->setHeaders(array('', pht('Name')))
->setColumnClasses(array('', 'wide'));
return $header->render() . $table->render();
return new PhutilSafeHTML($header->render() . $table->render());
}
private function renderTaskWidgetPaneContent() {
@ -279,7 +293,8 @@ final class ConpherenceViewController extends
array(
'href' => '/T'.$task->getID()
),
$task->getTitle()),
$task->getTitle()
)
);
}
$table = id(new AphrontTableView($data))
@ -288,13 +303,110 @@ final class ConpherenceViewController extends
->setColumnClasses(array('', 'wide'));
$content[] = $table->render();
}
return implode('', $content);
return new PhutilSafeHTML(implode('', $content));
}
private function renderCalendarWidgetPaneContent() {
$header = id(new PhabricatorHeaderView())
->setHeader(pht('Calendar'));
return $header->render() . 'TODO';
$user = $this->getRequest()->getUser();
$conpherence = $this->getConpherence();
$widget_data = $conpherence->getWidgetData();
$statuses = $widget_data['statuses'];
$handles = $conpherence->getHandles();
$content = array();
$timestamps = $this->getCalendarWidgetWeekTimestamps();
$one_day = 24 * 60 * 60;
foreach ($timestamps as $time => $day) {
// build a header for the new day
$content[] = id(new PhabricatorHeaderView())
->setHeader($day->format('l'))
->render();
$day->setTime(0, 0, 0);
$epoch_start = $day->format('U');
$day->modify('+1 day');
$epoch_end = $day->format('U');
// keep looking through statuses where we last left off
foreach ($statuses as $status) {
if ($status->getDateFrom() >= $epoch_end) {
// This list is sorted, so we can stop looking.
break;
}
if ($status->getDateFrom() < $epoch_end &&
$status->getDateTo() > $epoch_start) {
$timespan = $status->getDateTo() - $status->getDateFrom();
if ($timespan > $one_day) {
$time_str = 'm/d';
} else {
$time_str = 'h:i A';
}
$epoch_range = phabricator_format_local_time(
$status->getDateFrom(),
$user,
$time_str
) . ' - ' . phabricator_format_local_time(
$status->getDateTo(),
$user,
$time_str
);
$content[] = phutil_tag(
'div',
array(
'class' => 'user-status '.$status->getTextStatus(),
),
array(
phutil_tag(
'div',
array(
'class' => 'epoch-range'
),
$epoch_range
),
phutil_tag(
'div',
array(
'class' => 'icon',
),
''
),
phutil_tag(
'div',
array(
'class' => 'description'
),
$status->getTerseSummary($user)
),
phutil_tag(
'div',
array(
'class' => 'participant'
),
$handles[$status->getUserPHID()]->getName()
)
)
);
}
}
}
return new PhutilSafeHTML(implode('', $content));
}
private function getCalendarWidgetWeekTimestamps() {
$user = $this->getRequest()->getUser();
$timezone = new DateTimeZone($user->getTimezoneIdentifier());
$timestamps = array();
for ($day = 0; $day < 7; $day++) {
$timestamps[] = new DateTime(
sprintf('today +%d days', $day),
$timezone
);
}
return $timestamps;
}
}

View file

@ -141,17 +141,22 @@ final class ConpherenceThreadQuery
$tasks = mgroup($tasks, 'getOwnerPHID');
// statuses of everyone currently in the conpherence
// until the beginning of the next work week.
// NOTE: this is a bit boring on the weekends.
// for a rolling one week window
$start_of_week = phabricator_format_local_time(
strtotime('today'),
$this->getViewer(),
'U'
);
$end_of_week = phabricator_format_local_time(
strtotime('Monday midnight'),
strtotime('midnight +1 week'),
$this->getViewer(),
'U'
);
$statuses = id(new PhabricatorUserStatus())
->loadAllWhere(
'userPHID in (%Ls) AND dateTo <= %d',
'userPHID in (%Ls) AND dateTo >= %d AND dateFrom <= %d',
$participant_phids,
$start_of_week,
$end_of_week
);
$statuses = mgroup($statuses, 'getUserPHID');
@ -168,9 +173,12 @@ final class ConpherenceThreadQuery
foreach ($conpherences as $phid => $conpherence) {
$participant_phids = array_keys($conpherence->getParticipants());
$statuses = array_select_keys($statuses, $participant_phids);
$statuses = array_mergev($statuses);
$statuses = msort($statuses, 'getDateFrom');
$widget_data = array(
'tasks' => array_select_keys($tasks, $participant_phids),
'statuses' => array_select_keys($statuses, $participant_phids),
'statuses' => $statuses,
'files' => array_select_keys($files, $conpherence->getFilePHIDs()),
);
$conpherence->attachWidgetData($widget_data);

View file

@ -85,12 +85,12 @@ final class ConpherenceTransactionView extends AphrontView {
}
$transaction_view
->appendChild(phutil_render_tag(
->appendChild(phutil_tag(
'div',
array(
'class' => $content_class
),
$content)
new PhutilSafeHTML($content))
);
return $transaction_view->render();

View file

@ -408,29 +408,42 @@ final class DifferentialRevisionViewController extends DifferentialController {
->setAnchorName('top')
->setNavigationMarker(true);
$nav = id(new DifferentialChangesetFileTreeSideNavBuilder())
->setAnchorName('top')
->setTitle('D'.$revision->getID())
->setBaseURI(new PhutilURI('/D'.$revision->getID()))
->build($changesets);
$nav->appendChild(
array(
$reviewer_warning,
$top_anchor,
$revision_detail,
$page_pane,
));
$content = array(
$reviewer_warning,
$top_anchor,
$revision_detail,
$page_pane,
);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName($object_id)
->setHref('/'.$object_id));
$nav->setCrumbs($crumbs);
$prefs = $user->loadPreferences();
$pref_filetree = PhabricatorUserPreferences::PREFERENCE_DIFF_FILETREE;
if ($prefs->getPreference($pref_filetree)) {
$collapsed = $prefs->getPreference(
PhabricatorUserPreferences::PREFERENCE_NAV_COLLAPSED,
false);
$nav = id(new DifferentialChangesetFileTreeSideNavBuilder())
->setAnchorName('top')
->setTitle('D'.$revision->getID())
->setBaseURI(new PhutilURI('/D'.$revision->getID()))
->setCollapsed((bool)$collapsed)
->build($changesets);
$nav->appendChild($content);
$nav->setCrumbs($crumbs);
$content = $nav;
} else {
array_unshift($content, $crumbs);
}
return $this->buildApplicationPage(
$nav,
$content,
array(
'title' => $object_id.' '.$revision->getTitle(),
));

View file

@ -238,7 +238,7 @@ final class DifferentialRevisionEditor extends PhabricatorEditor {
$diff);
$adapter->setExplicitCCs($new['ccs']);
$adapter->setExplicitReviewers($new['rev']);
$adapter->setForbiddenCCs($revision->getUnsubscribedPHIDs());
$adapter->setForbiddenCCs($revision->loadUnsubscribedPHIDs());
$xscript = HeraldEngine::loadAndApplyRules($adapter);
$xscript_uri = '/herald/transcript/'.$xscript->getID().'/';
@ -500,12 +500,10 @@ final class DifferentialRevisionEditor extends PhabricatorEditor {
self::addCC($revision, $phid, $reason);
$unsubscribed = $revision->getUnsubscribed();
if (isset($unsubscribed[$phid])) {
unset($unsubscribed[$phid]);
$revision->setUnsubscribed($unsubscribed);
$revision->save();
}
$type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER;
id(new PhabricatorEdgeEditor())
->removeEdge($revision->getPHID(), $type, $phid)
->save();
}
public static function removeCCAndUpdateRevision(
@ -515,12 +513,10 @@ final class DifferentialRevisionEditor extends PhabricatorEditor {
self::removeCC($revision, $phid, $reason);
$unsubscribed = $revision->getUnsubscribed();
if (empty($unsubscribed[$phid])) {
$unsubscribed[$phid] = true;
$revision->setUnsubscribed($unsubscribed);
$revision->save();
}
$type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER;
id(new PhabricatorEdgeEditor())
->addEdge($revision->getPHID(), $type, $phid)
->save();
}
public static function addCC(

View file

@ -17,7 +17,6 @@ final class DifferentialRevision extends DifferentialDAO {
protected $lineCount;
protected $attached = array();
protected $unsubscribed = array();
protected $mailKey;
protected $branchName;
@ -264,8 +263,10 @@ final class DifferentialRevision extends DifferentialDAO {
return idx($this->relationships, $relation, array());
}
public function getUnsubscribedPHIDs() {
return array_keys($this->getUnsubscribed());
public function loadUnsubscribedPHIDs() {
return PhabricatorEdgeQuery::loadDestinationPHIDs(
$this->phid,
PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER);
}
public function getPrimaryReviewer() {

View file

@ -5,6 +5,7 @@ final class DifferentialChangesetFileTreeSideNavBuilder {
private $title;
private $baseURI;
private $anchorName;
private $collapsed = false;
public function setAnchorName($anchor_name) {
$this->anchorName = $anchor_name;
@ -30,12 +31,18 @@ final class DifferentialChangesetFileTreeSideNavBuilder {
return $this->title;
}
public function setCollapsed($collapsed) {
$this->collapsed = $collapsed;
return $this;
}
public function build(array $changesets) {
assert_instances_of($changesets, 'DifferentialChangeset');
$nav = new AphrontSideNavFilterView();
$nav->setBaseURI($this->getBaseURI());
$nav->setFlexible(true);
$nav->setCollapsed($this->collapsed);
$anchor = $this->getAnchorName();
@ -123,6 +130,8 @@ final class DifferentialChangesetFileTreeSideNavBuilder {
),
$filetree);
Javelin::initBehavior('phabricator-file-tree', array());
$nav->addLabel(pht('Changed Files'));
$nav->addCustomBlock($filetree);
$nav->setActive(true);

View file

@ -127,14 +127,9 @@ final class DifferentialChangesetListView extends AphrontView {
$ref,
$changeset);
$prefs = $this->user->loadPreferences();
$pref_symbols = $prefs->getPreference(
PhabricatorUserPreferences::PREFERENCE_DIFFUSION_SYMBOLS);
$detail->setChangeset($changeset);
$detail->addButton($view_options);
if ($pref_symbols != 'disabled') {
$detail->setSymbolIndex(idx($this->symbolIndexes, $key));
}
$detail->setSymbolIndex(idx($this->symbolIndexes, $key));
$detail->setVsChangesetID(idx($this->vsMap, $changeset->getID()));
$detail->setEditable(true);

View file

@ -251,10 +251,7 @@ final class DiffusionBrowseFileController extends DiffusionController {
$lang = last(explode('.', $drequest->getPath()));
$prefs = $this->getRequest()->getUser()->loadPreferences();
$pref_symbols = $prefs->getPreference(
PhabricatorUserPreferences::PREFERENCE_DIFFUSION_SYMBOLS);
if (isset($langs[$lang]) && $pref_symbols != 'disabled') {
if (isset($langs[$lang])) {
Javelin::initBehavior(
'repository-crossreference',
array(

View file

@ -327,13 +327,20 @@ final class DiffusionCommitController extends DiffusionController {
'commit' => true,
));
if ($changesets) {
$prefs = $user->loadPreferences();
$pref_filetree = PhabricatorUserPreferences::PREFERENCE_DIFF_FILETREE;
$pref_collapse = PhabricatorUserPreferences::PREFERENCE_NAV_COLLAPSED;
$show_filetree = $prefs->getPreference($pref_filetree);
$collapsed = $prefs->getPreference($pref_collapse);
if ($changesets && $show_filetree) {
$nav = id(new DifferentialChangesetFileTreeSideNavBuilder())
->setAnchorName('top')
->setTitle($short_name)
->setBaseURI(new PhutilURI('/'.$commit_id))
->build($changesets)
->setCrumbs($crumbs)
->setCollapsed((bool)$collapsed)
->appendChild($content);
$content = $nav;
} else {

View file

@ -79,7 +79,7 @@ abstract class PhabricatorDirectoryController extends PhabricatorController {
$is_hide = ($tile_display == PhabricatorApplication::TILE_HIDE);
if ($is_hide) {
$show_item_id = celerity_generate_unique_node_id();
$show_tiles_id = celerity_generate_unique_node_id();
$hide_item_id = celerity_generate_unique_node_id();
$show_item = id(new PhabricatorMenuItemView())
->setName(pht('Show More Applications'))
@ -90,18 +90,12 @@ abstract class PhabricatorDirectoryController extends PhabricatorController {
$hide_item = id(new PhabricatorMenuItemView())
->setName(pht('Show Fewer Applications'))
->setHref('#')
->setStyle('display: none')
->setID($hide_item_id)
->addSigil('home-hide-applications');
$nav->addMenuItem($show_item);
$nav->addCustomBlock(
hsprintf(
'<div id="%s" style="display: none;">',
$show_tiles_id));
Javelin::initBehavior('phabricator-home-reveal-tiles', array(
'tilesID' => $show_tiles_id,
'showID' => $show_item_id,
));
$tile_ids = array($hide_item_id);
}
foreach ($tile_group as $group => $application_list) {
@ -124,22 +118,39 @@ abstract class PhabricatorDirectoryController extends PhabricatorController {
while (count($tiles) % 3) {
$tiles[] = id(new PhabricatorApplicationLaunchView());
}
$nav->addLabel($groups[$group]);
$label = id(new PhabricatorMenuItemView())
->setType(PhabricatorMenuItemView::TYPE_LABEL)
->setName($groups[$group]);
if ($is_hide) {
$label->setStyle('display: none');
$label_id = celerity_generate_unique_node_id();
$label->setID($label_id);
$tile_ids[] = $label_id;
}
$nav->addMenuItem($label);
}
$group_id = celerity_generate_unique_node_id();
$tile_ids[] = $group_id;
$nav->addCustomBlock(
phutil_tag(
'div',
array(
'class' => 'application-tile-group',
'id' => $group_id,
'style' => ($is_hide ? 'display: none' : null),
),
mpull($tiles, 'render')));
}
$is_hide = ($tile_display == PhabricatorApplication::TILE_HIDE);
if ($is_hide) {
Javelin::initBehavior('phabricator-home-reveal-tiles', array(
'tileIDs' => $tile_ids,
'showID' => $show_item_id,
));
$nav->addMenuItem($hide_item);
$nav->addCustomBlock(hsprintf('</div>'));
}
}

View file

@ -271,7 +271,7 @@ final class PhabricatorFile extends PhabricatorFileDAO
}
public static function newFromFileDownload($uri, $name) {
public static function newFromFileDownload($uri, array $params) {
$uri = new PhutilURI($uri);
$protocol = $uri->getProtocol();
@ -286,12 +286,11 @@ final class PhabricatorFile extends PhabricatorFileDAO
$timeout = 5;
$file_data = HTTPSFuture::loadContent($uri, $timeout);
if ($file_data === false) {
return null;
}
list($file_data) = id(new HTTPSFuture($uri))
->setTimeout($timeout)
->resolvex();
return self::newFromFileData($file_data, array('name' => $name));
return self::newFromFileData($file_data, $params);
}
public static function normalizeFileName($file_name) {

View file

@ -19,21 +19,6 @@ final class PhabricatorFileImageMacro extends PhabricatorFileDAO
PhabricatorPHIDConstants::PHID_TYPE_MCRO);
}
static public function newFromImageURI($uri, $file_name, $image_macro_name) {
$file = PhabricatorFile::newFromFileDownload($uri, $file_name);
if (!$file) {
return null;
}
$image_macro = new PhabricatorFileImageMacro();
$image_macro->setName($image_macro_name);
$image_macro->setFilePHID($file->getPHID());
$image_macro->save();
return $image_macro;
}
public function isAutomaticallySubscribed($phid) {
return false;
}

View file

@ -330,8 +330,8 @@ final class ManiphestTaskListController extends ManiphestController {
$group = $query->getParameter('group');
$order = $query->getParameter('order');
$is_draggable =
($group == 'priority') ||
($group == 'none' && $order == 'priority');
($order == 'priority') &&
($group == 'none' || $group == 'priority');
$lists = new AphrontNullView();
$lists->appendChild('<div class="maniphest-group-container">');

View file

@ -122,7 +122,8 @@ final class PhameBlogEditController
->setName('description')
->setValue($blog->getDescription())
->setID('blog-description')
->setUser($user))
->setUser($user)
->setDisableMacros(true))
->appendChild(
id(new AphrontFormPolicyControl())
->setUser($user)

View file

@ -133,6 +133,7 @@ final class PhamePostEditController
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)
->setID('post-body')
->setUser($user)
->setDisableMacros(true)
)
->appendChild(
id(new AphrontFormSelectControl())

View file

@ -0,0 +1,72 @@
<?php
final class PhabricatorSettingsPanelDiffPreferences
extends PhabricatorSettingsPanel {
public function getPanelKey() {
return 'diff';
}
public function getPanelName() {
return pht('Diff Preferences');
}
public function getPanelGroup() {
return pht('Application Settings');
}
public function processRequest(AphrontRequest $request) {
$user = $request->getUser();
$preferences = $user->loadPreferences();
$pref_filetree = PhabricatorUserPreferences::PREFERENCE_DIFF_FILETREE;
if ($request->isFormPost()) {
$preferences->setPreference(
$pref_filetree,
$request->getInt($pref_filetree));
$preferences->save();
return id(new AphrontRedirectResponse())
->setURI($this->getPanelURI('?saved=true'));
}
$form = id(new AphrontFormView())
->setUser($user)
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Show Filetree'))
->setName($pref_filetree)
->setValue($preferences->getPreference($pref_filetree))
->setOptions(
array(
0 => pht('Disable Filetree'),
1 => pht('Enable Filetree'),
))
->setCaption(
pht("When looking at a revision or commit, show affected files ".
"in a sidebar.")))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Save Preferences')));
$panel = new AphrontPanelView();
$panel->setHeader(pht('Diff Preferences'));
$panel->appendChild($form);
$panel->setNoBackground();
$error_view = null;
if ($request->getBool('saved')) {
$error_view = id(new AphrontErrorView())
->setTitle(pht('Preferences Saved'))
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
->setErrors(array(pht('Your preferences have been saved.')));
}
return array(
$error_view,
$panel,
);
}
}

View file

@ -24,8 +24,6 @@ final class PhabricatorSettingsPanelDisplayPreferences
$pref_editor = PhabricatorUserPreferences::PREFERENCE_EDITOR;
$pref_multiedit = PhabricatorUserPreferences::PREFERENCE_MULTIEDIT;
$pref_titles = PhabricatorUserPreferences::PREFERENCE_TITLES;
$pref_symbols =
PhabricatorUserPreferences::PREFERENCE_DIFFUSION_SYMBOLS;
$pref_monospaced_textareas =
PhabricatorUserPreferences::PREFERENCE_MONOSPACED_TEXTAREAS;
@ -40,9 +38,6 @@ final class PhabricatorSettingsPanelDisplayPreferences
$preferences->setPreference(
$pref_multiedit,
$request->getStr($pref_multiedit));
$preferences->setPreference(
$pref_symbols,
$request->getStr($pref_symbols));
$preferences->setPreference($pref_monospaced, $monospaced);
$preferences->setPreference(
$pref_monospaced_textareas,
@ -74,7 +69,6 @@ EXAMPLE;
$font_default = PhabricatorEnv::getEnvConfig('style.monospace');
$font_default = phutil_escape_html($font_default);
$pref_symbols_value = $preferences->getPreference($pref_symbols);
$pref_monospaced_textareas_value = $preferences
->getPreference($pref_monospaced_textareas);
if (!$pref_monospaced_textareas_value) {
@ -132,15 +126,6 @@ EXAMPLE;
'<pre class="PhabricatorMonospaced">'.
phutil_escape_html($example_string).
'</pre>'))
->appendChild(
id(new AphrontFormRadioButtonControl())
->setLabel('Symbol Links')
->setName($pref_symbols)
->setValue($pref_symbols_value ? $pref_symbols_value : 'enabled')
->addButton('enabled', 'Enabled (default)',
'Use this setting to disable linking symbol names in Differential '.
'and Diffusion to their definitions. This is enabled by default.')
->addButton('disabled', 'Disabled', null))
->appendChild(
id(new AphrontFormRadioButtonControl())
->setLabel('Monospaced Textareas')

View file

@ -46,42 +46,57 @@ final class PhabricatorSettingsPanelProfile
$user->setTranslation($request->getStr('translation'));
$default_image = $request->getExists('default_image');
$gravatar_email = $request->getStr('gravatar');
if ($default_image) {
$profile->setProfileImagePHID(null);
$user->setProfileImagePHID(null);
} else if (!empty($_FILES['image'])) {
$err = idx($_FILES['image'], 'error');
if ($err != UPLOAD_ERR_NO_FILE) {
} else if (!empty($gravatar_email) || $request->getFileExists('image')) {
$file = null;
if (!empty($gravatar_email)) {
// These steps recommended by:
// https://en.gravatar.com/site/implement/hash/
$trimmed = trim($gravatar_email);
$lower_cased = strtolower($trimmed);
$hash = md5($lower_cased);
$url = 'http://www.gravatar.com/avatar/'.($hash).'?s=200';
$file = PhabricatorFile::newFromFileDownload(
$url,
array(
'name' => 'gravatar',
'authorPHID' => $user->getPHID(),
));
} else if ($request->getFileExists('image')) {
$file = PhabricatorFile::newFromPHPUpload(
$_FILES['image'],
array(
'authorPHID' => $user->getPHID(),
));
$okay = $file->isTransformableImage();
if ($okay) {
$xformer = new PhabricatorImageTransformer();
}
// Generate the large picture for the profile page.
$large_xformed = $xformer->executeProfileTransform(
$file,
$width = 280,
$min_height = 140,
$max_height = 420);
$profile->setProfileImagePHID($large_xformed->getPHID());
$okay = $file->isTransformableImage();
if ($okay) {
$xformer = new PhabricatorImageTransformer();
// Generate the small picture for comments, etc.
$small_xformed = $xformer->executeProfileTransform(
$file,
$width = 50,
$min_height = 50,
$max_height = 50);
$user->setProfileImagePHID($small_xformed->getPHID());
} else {
$e_image = 'Not Supported';
$errors[] =
'This server only supports these image formats: '.
implode(', ', $supported_formats).'.';
}
// Generate the large picture for the profile page.
$large_xformed = $xformer->executeProfileTransform(
$file,
$width = 280,
$min_height = 140,
$max_height = 420);
$profile->setProfileImagePHID($large_xformed->getPHID());
// Generate the small picture for comments, etc.
$small_xformed = $xformer->executeProfileTransform(
$file,
$width = 50,
$min_height = 50,
$max_height = 50);
$user->setProfileImagePHID($small_xformed->getPHID());
} else {
$e_image = 'Not Supported';
$errors[] =
'This server only supports these image formats: '.
implode(', ', $supported_formats).'.';
}
}
@ -190,6 +205,12 @@ final class PhabricatorSettingsPanelProfile
->setName('image')
->setError($e_image)
->setCaption('Supported formats: '.implode(', ', $supported_formats)))
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Import Gravatar')
->setName('gravatar')
->setError($e_image)
->setCaption('Enter gravatar email address'))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Save')

View file

@ -18,11 +18,13 @@ final class PhabricatorUserPreferences extends PhabricatorUserDAO {
const PREFERENCE_SEARCH_SHORTCUT = 'search-shortcut';
const PREFERENCE_DIFFUSION_VIEW = 'diffusion-view';
const PREFERENCE_DIFFUSION_SYMBOLS = 'diffusion-symbols';
const PREFERENCE_NAV_COLLAPSED = 'nav-collapsed';
const PREFERENCE_NAV_WIDTH = 'nav-width';
const PREFERENCE_APP_TILES = 'app-tiles';
const PREFERENCE_DIFF_FILETREE = 'diff-filetree';
protected $userPHID;
protected $preferences = array();

View file

@ -153,25 +153,20 @@ abstract class PhabricatorApplicationTransactionEditor
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
break;
case PhabricatorTransactions::TYPE_VIEW_POLICY:
$object->setViewPolicy($xaction->getNewValue());
break;
case PhabricatorTransactions::TYPE_EDIT_POLICY:
$object->setEditPolicy($xaction->getNewValue());
break;
default:
return $this->applyCustomInternalTransaction($object, $xaction);
}
return $this->applyCustomInternalTransaction($object, $xaction);
}
private function applyExternalEffects(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
break;
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
$subeditor = id(new PhabricatorSubscriptionsEditor())
->setObject($object)
@ -179,9 +174,8 @@ abstract class PhabricatorApplicationTransactionEditor
->subscribeExplicit($xaction->getNewValue())
->save();
break;
default:
return $this->applyCustomExternalTransaction($object, $xaction);
}
return $this->applyCustomExternalTransaction($object, $xaction);
}
protected function applyCustomInternalTransaction(

View file

@ -34,7 +34,7 @@ final class PhabricatorRemarkupRuleImageMacro
if ($file) {
$src_uri = $file->getBestURI();
$file_data = $file->getMetadata();
$height = idx($file_data,PhabricatorFile::METADATA_IMAGE_HEIGHT);
$height = idx($file_data, PhabricatorFile::METADATA_IMAGE_HEIGHT);
$width = idx($file_data, PhabricatorFile::METADATA_IMAGE_WIDTH);
if ($height && $width) {
$style = sprintf(

View file

@ -1097,6 +1097,14 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
'type' => 'sql',
'name' => $this->getPatchPath('20130127.altheraldtranscript.sql'),
),
'20130201.revisionunsubscribed.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130201.revisionunsubscribed.php'),
),
'20130201.revisionunsubscribed.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130201.revisionunsubscribed.sql'),
),
);
}

View file

@ -15,7 +15,6 @@ final class AphrontFormImageControl extends AphrontFormControl {
array(
'type' => 'file',
'name' => $this->getName(),
'class' => 'image',
)).
'<div style="clear: both;">'.
phutil_tag(

View file

@ -1,7 +1,11 @@
<?php
final class PhabricatorRemarkupControl extends AphrontFormTextAreaControl {
private $disableMacro = false;
public function setDisableMacros($disable) {
$this->disableMacro = $disable;
return $this;
}
protected function renderInput() {
$id = $this->getID();
if (!$id) {
@ -48,20 +52,22 @@ final class PhabricatorRemarkupControl extends AphrontFormTextAreaControl {
),
'table' => array(
'tip' => pht('Table'),
),
array(
)
);
if (!$this->disableMacro and function_exists('imagettftext')) {
$actions[] = array(
'spacer' => true,
),
'meme' => array(
);
$actions['meme'] = array(
'tip' => pht('Meme'),
),
'help' => array(
);
}
$actions['help'] = array(
'tip' => pht('Help'),
'align' => 'right',
'href' => PhabricatorEnv::getDoclink(
'article/Remarkup_Reference.html'),
),
);
);
$buttons = array();
foreach ($actions as $action => $spec) {
@ -74,7 +80,6 @@ final class PhabricatorRemarkupControl extends AphrontFormTextAreaControl {
'');
continue;
}
$classes = array();
$classes[] = 'remarkup-assist-button';
if (idx($spec, 'align') == 'right') {

View file

@ -21,6 +21,7 @@ final class AphrontSideNavFilterView extends AphrontView {
private $baseURI;
private $selectedFilter = false;
private $flexible;
private $collapsed = false;
private $active;
private $menu;
private $crumbs;
@ -70,6 +71,11 @@ final class AphrontSideNavFilterView extends AphrontView {
return $this;
}
public function setCollapsed($collapsed) {
$this->collapsed = $collapsed;
return $this;
}
public function getMenuView() {
return $this->menu;
}
@ -196,7 +202,6 @@ final class AphrontSideNavFilterView extends AphrontView {
$main_id = celerity_generate_unique_node_id();
if ($this->flexible) {
$nav_classes[] = 'has-drag-nav';
$drag_id = celerity_generate_unique_node_id();
$flex_bar = phutil_tag(
'div',
@ -213,7 +218,10 @@ final class AphrontSideNavFilterView extends AphrontView {
if ($this->menu->getItems()) {
$local_id = celerity_generate_unique_node_id();
$background_id = celerity_generate_unique_node_id();
$nav_classes[] = 'has-local-nav';
if (!$this->collapsed) {
$nav_classes[] = 'has-local-nav';
}
$menu_background = phutil_tag(
'div',
@ -243,7 +251,9 @@ final class AphrontSideNavFilterView extends AphrontView {
}
if ($this->flexible) {
$nav_classes[] = 'has-drag-nav';
if (!$this->collapsed) {
$nav_classes[] = 'has-drag-nav';
}
Javelin::initBehavior(
'phabricator-nav',
@ -253,6 +263,7 @@ final class AphrontSideNavFilterView extends AphrontView {
'dragID' => $drag_id,
'contentID' => $content_id,
'backgroundID' => $background_id,
'collapsed' => $this->collapsed,
));
if ($this->active) {

View file

@ -187,10 +187,6 @@ table.aphront-form-control-checkbox-layout th {
max-width: 400px;
}
.aphront-form-control-image .image {
width: 164px;
}
.aphront-form-control-image span {
margin: 0px 4px 0px 2px;
}

View file

@ -12,9 +12,88 @@
border-color: #CCC;
border-style: solid;
background: url('/rsrc/image/texture/dust_background.jpg');
overflow-y: auto;
}
.conpherence-widget-pane .aphront-form-input {
margin: 0;
width: 100%;
}
.conpherence-widget-pane .widgets-header {
height: 40px;
width: 127px;
margin: 0px auto 0px auto;
}
.conpherence-widget-pane .widgets-header .sprite-conpher {
display: block;
width: 29px;
height: 33px;
margin: 4px 0px 0px 20px;
float: left;
clear: none;
}
.conpherence-widget-pane .widgets-header .first-icon {
margin-left: 0px;
}
.conpherence-widget-pane .widgets-body {
position: fixed;
overflow-y: auto;
top: 165px;
bottom: 0px;
width: 320px;
}
/* calendar widget */
.conpherence-widget-pane #widgets-calendar {
}
.conpherence-widget-pane #widgets-calendar .user-status {
height: 60px;
}
.conpherence-widget-pane #widgets-calendar .user-status .icon {
border-radius: 10px;
position: relative;
top: 24px;
left: 12px;
height: 16px;
width: 16px;
box-shadow: 0px 0px 1px #000;
}
.conpherence-widget-pane #widgets-calendar .sporadic .icon {
background-color: rgb(222, 226, 232);
}
.conpherence-widget-pane #widgets-calendar .away .icon {
background-color: rgb(102, 204, 255);
}
.conpherence-widget-pane #widgets-calendar .user-status .epoch-range {
float: right;
font-style: italic;
position: relative;
top: 24px;
right: 8px;
font-size: 11px;
}
.conpherence-widget-pane #widgets-calendar .user-status .description {
position: relative;
left: 40px;
top: 0px;
width: 260px;
}
.conpherence-widget-pane #widgets-calendar .user-status .participant {
position: relative;
left: 40px;
top: 0px;
font-style: italic;
font-size: 11px;
width: 260px;
}

View file

@ -4,7 +4,7 @@
*/
.sprite-conpher {
background-image: url(/rsrc/image/sprite-conpher.png);
background-image: url(/rsrc/image/sprite-conph.png);
background-repeat: no-repeat;
}
@ -12,7 +12,7 @@
only screen and (min-device-pixel-ratio: 1.5),
only screen and (-webkit-min-device-pixel-ratio: 1.5) {
.sprite-conpher {
background-image: url(/rsrc/image/sprite-conpher-X2.png);
background-image: url(/rsrc/image/sprite-conph-X2.png);
background-size: 132px 132px;
}
}

View file

@ -16,8 +16,15 @@ JX.behavior('conpherence-widget-pane', function(config) {
for (var widget in config.widgetRegistery) {
if (widget == data.widget) {
JX.$(widget).style.display = 'block';
JX.DOM.alterClass(e.getTarget(), data.toggleClass, true);
} else {
JX.$(widget).style.display = 'none';
var cur_toggle = JX.$(widget + '-toggle');
JX.DOM.alterClass(
cur_toggle,
JX.Stratcom.getData(cur_toggle).toggleClass,
false
);
}
}
}

View file

@ -0,0 +1,16 @@
/**
* @provides javelin-behavior-phabricator-file-tree
* @requires javelin-behavior
* phabricator-keyboard-shortcut
* javelin-stratcom
*/
JX.behavior('phabricator-file-tree', function(config) {
new JX.KeyboardShortcut('f', 'Toggle file tree.')
.setHandler(function(manager) {
JX.Stratcom.invoke('differential-filetree-toggle');
})
.register();
});

View file

@ -13,7 +13,9 @@ JX.behavior('phabricator-home-reveal-tiles', function(config) {
function(e) {
e.kill();
JX.DOM.show(JX.$(config.tilesID));
for (var ii = 0; ii < config.tileIDs.length; ii++) {
JX.DOM.show(JX.$(config.tileIDs[ii]));
}
JX.DOM.hide(JX.$(config.showID));
});
@ -23,7 +25,9 @@ JX.behavior('phabricator-home-reveal-tiles', function(config) {
function(e) {
e.kill();
JX.DOM.hide(JX.$(config.tilesID));
for (var ii = 0; ii < config.tileIDs.length; ii++) {
JX.DOM.hide(JX.$(config.tileIDs[ii]));
}
JX.DOM.show(JX.$(config.showID));
});
});

View file

@ -109,12 +109,15 @@ JX.behavior('phabricator-nav', function(config) {
content.style.marginLeft = '';
}
var collapsed = false;
var collapsed = config.collapsed;
JX.Stratcom.listen('differential-filetree-toggle', null, function(e) {
collapsed = !collapsed;
JX.DOM.alterClass(main, 'has-local-nav', !collapsed);
JX.DOM.alterClass(main, 'has-drag-nav', !collapsed);
resetdrag();
new JX.Request('/settings/adjust/', JX.Bag)
.setData({ key : 'nav-collapsed', value : (collapsed ? 1 : 0) })
.send();
});

View file

@ -264,12 +264,6 @@ JX.behavior('differential-keyboard-navigation', function(config) {
})
.register();
new JX.KeyboardShortcut('f', 'Toggle file tree.')
.setHandler(function(manager) {
JX.Stratcom.invoke('differential-filetree-toggle');
})
.register();
if (config.haunt) {
new JX.KeyboardShortcut('z', 'Cycle comment panel haunting modes.')
.setHandler(haunt)