Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/calendar/controller/PhabricatorCalendarController.php b/src/applications/calendar/controller/PhabricatorCalendarController.php
index 08af8971ea..2e088ecf49 100644
--- a/src/applications/calendar/controller/PhabricatorCalendarController.php
+++ b/src/applications/calendar/controller/PhabricatorCalendarController.php
@@ -1,17 +1,29 @@
<?php
abstract class PhabricatorCalendarController extends PhabricatorController {
protected function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
+ $actions = id(new PhabricatorActionListView())
+ ->setUser($this->getViewer())
+ ->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Create Private Event'))
+ ->setHref('/calendar/event/create/?mode=private'))
+ ->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Create Public Event'))
+ ->setHref('/calendar/event/create/?mode=public'));
+
$crumbs->addAction(
id(new PHUIListItemView())
->setName(pht('Create Event'))
->setHref($this->getApplicationURI().'event/create/')
- ->setIcon('fa-plus-square'));
+ ->setIcon('fa-plus-square')
+ ->setDropdownMenu($actions));
return $crumbs;
}
}
diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php b/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php
index cc19f7273f..109aa692bd 100644
--- a/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php
+++ b/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php
@@ -1,421 +1,424 @@
<?php
final class PhabricatorCalendarEventEditController
extends PhabricatorCalendarController {
private $id;
public function willProcessRequest(array $data) {
$this->id = idx($data, 'id');
}
public function isCreate() {
return !$this->id;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$user_phid = $viewer->getPHID();
$error_name = true;
$error_start_date = true;
$error_end_date = true;
$validation_exception = null;
$all_day_id = celerity_generate_unique_node_id();
$start_date_id = celerity_generate_unique_node_id();
$end_date_id = null;
$next_workflow = $request->getStr('next');
$uri_query = $request->getStr('query');
if ($this->isCreate()) {
- $event = PhabricatorCalendarEvent::initializeNewCalendarEvent($viewer);
+ $mode = $request->getStr('mode');
+ $event = PhabricatorCalendarEvent::initializeNewCalendarEvent(
+ $viewer,
+ $mode);
$create_start_year = $request->getInt('year');
$create_start_month = $request->getInt('month');
$create_start_day = $request->getInt('day');
$create_start_time = $request->getStr('time');
if ($create_start_year) {
$start = AphrontFormDateControlValue::newFromParts(
$viewer,
$create_start_year,
$create_start_month,
$create_start_day,
$create_start_time);
if (!$start->isValid()) {
return new Aphront400Response();
}
$start_value = AphrontFormDateControlValue::newFromEpoch(
$viewer,
$start->getEpoch());
$end = clone $start_value->getDateTime();
$end->modify('+1 hour');
$end_value = AphrontFormDateControlValue::newFromEpoch(
$viewer,
$end->format('U'));
} else {
list($start_value, $end_value) = $this->getDefaultTimeValues($viewer);
}
$submit_label = pht('Create');
$page_title = pht('Create Event');
$redirect = 'created';
$subscribers = array();
$invitees = array($user_phid);
$cancel_uri = $this->getApplicationURI();
$end_date_id = celerity_generate_unique_node_id();
} else {
$event = id(new PhabricatorCalendarEventQuery())
->setViewer($viewer)
->withIDs(array($this->id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$event) {
return new Aphront404Response();
}
$end_value = AphrontFormDateControlValue::newFromEpoch(
$viewer,
$event->getDateTo());
$start_value = AphrontFormDateControlValue::newFromEpoch(
$viewer,
$event->getDateFrom());
$submit_label = pht('Update');
$page_title = pht('Update Event');
$subscribers = PhabricatorSubscribersQuery::loadSubscribersForPHID(
$event->getPHID());
$invitees = array();
foreach ($event->getInvitees() as $invitee) {
if ($invitee->isUninvited()) {
continue;
} else {
$invitees[] = $invitee->getInviteePHID();
}
}
$cancel_uri = '/'.$event->getMonogram();
}
$name = $event->getName();
$description = $event->getDescription();
$is_all_day = $event->getIsAllDay();
$icon = $event->getIcon();
$current_policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($event)
->execute();
if ($request->isFormPost()) {
$xactions = array();
$name = $request->getStr('name');
$start_value = AphrontFormDateControlValue::newFromRequest(
$request,
'start');
$end_value = AphrontFormDateControlValue::newFromRequest(
$request,
'end');
$description = $request->getStr('description');
$subscribers = $request->getArr('subscribers');
$edit_policy = $request->getStr('editPolicy');
$view_policy = $request->getStr('viewPolicy');
$is_all_day = $request->getStr('isAllDay');
$icon = $request->getStr('icon');
$invitees = $request->getArr('invitees');
$new_invitees = $this->getNewInviteeList($invitees, $event);
$status_attending = PhabricatorCalendarEventInvitee::STATUS_ATTENDING;
if ($this->isCreate()) {
$status = idx($new_invitees, $viewer->getPHID());
if ($status) {
$new_invitees[$viewer->getPHID()] = $status_attending;
}
}
$xactions[] = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(
PhabricatorCalendarEventTransaction::TYPE_NAME)
->setNewValue($name);
$xactions[] = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(
PhabricatorCalendarEventTransaction::TYPE_ALL_DAY)
->setNewValue($is_all_day);
$xactions[] = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(
PhabricatorCalendarEventTransaction::TYPE_ICON)
->setNewValue($icon);
$xactions[] = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(
PhabricatorCalendarEventTransaction::TYPE_START_DATE)
->setNewValue($start_value);
$xactions[] = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(
PhabricatorCalendarEventTransaction::TYPE_END_DATE)
->setNewValue($end_value);
$xactions[] = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(
PhabricatorTransactions::TYPE_SUBSCRIBERS)
->setNewValue(array('=' => array_fuse($subscribers)));
$xactions[] = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(
PhabricatorCalendarEventTransaction::TYPE_INVITE)
->setNewValue($new_invitees);
$xactions[] = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(
PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION)
->setNewValue($description);
$xactions[] = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
->setNewValue($request->getStr('viewPolicy'));
$xactions[] = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
->setNewValue($request->getStr('editPolicy'));
$editor = id(new PhabricatorCalendarEventEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true);
try {
$xactions = $editor->applyTransactions($event, $xactions);
$response = id(new AphrontRedirectResponse());
switch ($next_workflow) {
case 'day':
if (!$uri_query) {
$uri_query = 'month';
}
$year = $start_value->getDateTime()->format('Y');
$month = $start_value->getDateTime()->format('m');
$day = $start_value->getDateTime()->format('d');
$response->setURI(
'/calendar/query/'.$uri_query.'/'.$year.'/'.$month.'/'.$day.'/');
break;
default:
$response->setURI('/E'.$event->getID());
break;
}
return $response;
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
$error_name = $ex->getShortMessage(
PhabricatorCalendarEventTransaction::TYPE_NAME);
$error_start_date = $ex->getShortMessage(
PhabricatorCalendarEventTransaction::TYPE_START_DATE);
$error_end_date = $ex->getShortMessage(
PhabricatorCalendarEventTransaction::TYPE_END_DATE);
$event->setViewPolicy($view_policy);
$event->setEditPolicy($edit_policy);
}
}
Javelin::initBehavior('event-all-day', array(
'allDayID' => $all_day_id,
'startDateID' => $start_date_id,
'endDateID' => $end_date_id,
));
$name = id(new AphrontFormTextControl())
->setLabel(pht('Name'))
->setName('name')
->setValue($name)
->setError($error_name);
$all_day_checkbox = id(new AphrontFormCheckboxControl())
->addCheckbox(
'isAllDay',
1,
pht('All Day Event'),
$is_all_day,
$all_day_id);
$start_control = id(new AphrontFormDateControl())
->setUser($viewer)
->setName('start')
->setLabel(pht('Start'))
->setError($error_start_date)
->setValue($start_value)
->setID($start_date_id)
->setIsTimeDisabled($is_all_day)
->setEndDateID($end_date_id);
$end_control = id(new AphrontFormDateControl())
->setUser($viewer)
->setName('end')
->setLabel(pht('End'))
->setError($error_end_date)
->setValue($end_value)
->setID($end_date_id)
->setIsTimeDisabled($is_all_day);
$description = id(new AphrontFormTextAreaControl())
->setLabel(pht('Description'))
->setName('description')
->setValue($description);
$view_policies = id(new AphrontFormPolicyControl())
->setUser($viewer)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicyObject($event)
->setPolicies($current_policies)
->setName('viewPolicy');
$edit_policies = id(new AphrontFormPolicyControl())
->setUser($viewer)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
->setPolicyObject($event)
->setPolicies($current_policies)
->setName('editPolicy');
$subscribers = id(new AphrontFormTokenizerControl())
->setLabel(pht('Subscribers'))
->setName('subscribers')
->setValue($subscribers)
->setUser($viewer)
->setDatasource(new PhabricatorMetaMTAMailableDatasource());
$invitees = id(new AphrontFormTokenizerControl())
->setLabel(pht('Invitees'))
->setName('invitees')
->setValue($invitees)
->setUser($viewer)
->setDatasource(new PhabricatorMetaMTAMailableDatasource());
if ($this->isCreate()) {
$icon_uri = $this->getApplicationURI('icon/');
} else {
$icon_uri = $this->getApplicationURI('icon/'.$event->getID().'/');
}
$icon_display = PhabricatorCalendarIcon::renderIconForChooser($icon);
$icon = id(new AphrontFormChooseButtonControl())
->setLabel(pht('Icon'))
->setName('icon')
->setDisplayValue($icon_display)
->setButtonText(pht('Choose Icon...'))
->setChooseURI($icon_uri)
->setValue($icon);
$form = id(new AphrontFormView())
->addHiddenInput('next', $next_workflow)
->addHiddenInput('query', $uri_query)
->setUser($viewer)
->appendChild($name)
->appendChild($all_day_checkbox)
->appendChild($start_control)
->appendChild($end_control)
->appendControl($view_policies)
->appendControl($edit_policies)
->appendControl($subscribers)
->appendControl($invitees)
->appendChild($description)
->appendChild($icon);
if ($request->isAjax()) {
return $this->newDialog()
->setTitle($page_title)
->setWidth(AphrontDialogView::WIDTH_FULL)
->appendForm($form)
->addCancelButton($cancel_uri)
->addSubmitButton($submit_label);
}
$submit = id(new AphrontFormSubmitControl())
->addCancelButton($cancel_uri)
->setValue($submit_label);
$form->appendChild($submit);
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($page_title)
->setForm($form);
$crumbs = $this->buildApplicationCrumbs();
if (!$this->isCreate()) {
$crumbs->addTextCrumb('E'.$event->getId(), '/E'.$event->getId());
}
$crumbs->addTextCrumb($page_title);
$object_box = id(new PHUIObjectBoxView())
->setHeaderText($page_title)
->setValidationException($validation_exception)
->appendChild($form);
return $this->buildApplicationPage(
array(
$crumbs,
$object_box,
),
array(
'title' => $page_title,
));
}
public function getNewInviteeList(array $phids, $event) {
$invitees = $event->getInvitees();
$invitees = mpull($invitees, null, 'getInviteePHID');
$invited_status = PhabricatorCalendarEventInvitee::STATUS_INVITED;
$uninvited_status = PhabricatorCalendarEventInvitee::STATUS_UNINVITED;
$phids = array_fuse($phids);
$new = array();
foreach ($phids as $phid) {
$old_status = $event->getUserInviteStatus($phid);
if ($old_status != $uninvited_status) {
continue;
}
$new[$phid] = $invited_status;
}
foreach ($invitees as $invitee) {
$deleted_invitee = !idx($phids, $invitee->getInviteePHID());
if ($deleted_invitee) {
$new[$invitee->getInviteePHID()] = $uninvited_status;
}
}
return $new;
}
private function getDefaultTimeValues($viewer) {
$start = new DateTime('@'.time());
$start->setTimeZone($viewer->getTimeZone());
$start->setTime($start->format('H'), 0, 0);
$start->modify('+1 hour');
$end = id(clone $start)->modify('+1 hour');
$start_value = AphrontFormDateControlValue::newFromEpoch(
$viewer,
$start->format('U'));
$end_value = AphrontFormDateControlValue::newFromEpoch(
$viewer,
$end->format('U'));
return array($start_value, $end_value);
}
}
diff --git a/src/applications/calendar/storage/PhabricatorCalendarEvent.php b/src/applications/calendar/storage/PhabricatorCalendarEvent.php
index 3055e5e4e6..cd829369d8 100644
--- a/src/applications/calendar/storage/PhabricatorCalendarEvent.php
+++ b/src/applications/calendar/storage/PhabricatorCalendarEvent.php
@@ -1,380 +1,388 @@
<?php
final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
implements PhabricatorPolicyInterface,
PhabricatorMarkupInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorSubscribableInterface,
PhabricatorTokenReceiverInterface,
PhabricatorDestructibleInterface,
PhabricatorMentionableInterface,
PhabricatorFlaggableInterface {
protected $name;
protected $userPHID;
protected $dateFrom;
protected $dateTo;
protected $description;
protected $isCancelled;
protected $isAllDay;
protected $icon;
protected $mailKey;
protected $viewPolicy;
protected $editPolicy;
const DEFAULT_ICON = 'fa-calendar';
private $invitees = self::ATTACHABLE;
private $appliedViewer;
- public static function initializeNewCalendarEvent(PhabricatorUser $actor) {
+ public static function initializeNewCalendarEvent(
+ PhabricatorUser $actor,
+ $mode) {
$app = id(new PhabricatorApplicationQuery())
->setViewer($actor)
->withClasses(array('PhabricatorCalendarApplication'))
->executeOne();
+ if ($mode == 'public') {
+ $view_policy = PhabricatorPolicies::getMostOpenPolicy();
+ } else {
+ $view_policy = $actor->getPHID();
+ }
+
return id(new PhabricatorCalendarEvent())
->setUserPHID($actor->getPHID())
->setIsCancelled(0)
->setIsAllDay(0)
->setIcon(self::DEFAULT_ICON)
- ->setViewPolicy($actor->getPHID())
+ ->setViewPolicy($view_policy)
->setEditPolicy($actor->getPHID())
->attachInvitees(array())
->applyViewerTimezone($actor);
}
public function applyViewerTimezone(PhabricatorUser $viewer) {
if ($this->appliedViewer) {
throw new Exception(pht('Viewer timezone is already applied!'));
}
$this->appliedViewer = $viewer;
if (!$this->getIsAllDay()) {
return $this;
}
$zone = $viewer->getTimeZone();
$this->setDateFrom(
$this->getDateEpochForTimeZone(
$this->getDateFrom(),
new DateTimeZone('Pacific/Kiritimati'),
'Y-m-d',
null,
$zone));
$this->setDateTo(
$this->getDateEpochForTimeZone(
$this->getDateTo(),
new DateTimeZone('Pacific/Midway'),
'Y-m-d 23:59:00',
'-1 day',
$zone));
return $this;
}
public function removeViewerTimezone(PhabricatorUser $viewer) {
if (!$this->appliedViewer) {
throw new Exception(pht('Viewer timezone is not applied!'));
}
if ($viewer->getPHID() != $this->appliedViewer->getPHID()) {
throw new Exception(pht('Removed viewer must match applied viewer!'));
}
$this->appliedViewer = null;
if (!$this->getIsAllDay()) {
return $this;
}
$zone = $viewer->getTimeZone();
$this->setDateFrom(
$this->getDateEpochForTimeZone(
$this->getDateFrom(),
$zone,
'Y-m-d',
null,
new DateTimeZone('Pacific/Kiritimati')));
$this->setDateTo(
$this->getDateEpochForTimeZone(
$this->getDateTo(),
$zone,
'Y-m-d',
'+1 day',
new DateTimeZone('Pacific/Midway')));
return $this;
}
private function getDateEpochForTimeZone(
$epoch,
$src_zone,
$format,
$adjust,
$dst_zone) {
$src = new DateTime('@'.$epoch);
$src->setTimeZone($src_zone);
if (strlen($adjust)) {
$adjust = ' '.$adjust;
}
$dst = new DateTime($src->format($format).$adjust, $dst_zone);
return $dst->format('U');
}
public function save() {
if ($this->appliedViewer) {
throw new Exception(
pht(
'Can not save event with viewer timezone still applied!'));
}
if (!$this->mailKey) {
$this->mailKey = Filesystem::readRandomCharacters(20);
}
return parent::save();
}
/**
* Get the event start epoch for evaluating invitee availability.
*
* When assessing availability, we pretend events start earlier than they
* really. This allows us to mark users away for the entire duration of a
* series of back-to-back meetings, even if they don't strictly overlap.
*
* @return int Event start date for availability caches.
*/
public function getDateFromForCache() {
return ($this->getDateFrom() - phutil_units('15 minutes in seconds'));
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
'name' => 'text',
'dateFrom' => 'epoch',
'dateTo' => 'epoch',
'description' => 'text',
'isCancelled' => 'bool',
'isAllDay' => 'bool',
'icon' => 'text32',
'mailKey' => 'bytes20',
),
self::CONFIG_KEY_SCHEMA => array(
'userPHID_dateFrom' => array(
'columns' => array('userPHID', 'dateTo'),
),
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorCalendarEventPHIDType::TYPECONST);
}
public function getMonogram() {
return 'E'.$this->getID();
}
public function getInvitees() {
return $this->assertAttached($this->invitees);
}
public function attachInvitees(array $invitees) {
$this->invitees = $invitees;
return $this;
}
public function getUserInviteStatus($phid) {
$invitees = $this->getInvitees();
$invitees = mpull($invitees, null, 'getInviteePHID');
$invited = idx($invitees, $phid);
if (!$invited) {
return PhabricatorCalendarEventInvitee::STATUS_UNINVITED;
}
$invited = $invited->getStatus();
return $invited;
}
public function getIsUserAttending($phid) {
$attending_status = PhabricatorCalendarEventInvitee::STATUS_ATTENDING;
$old_status = $this->getUserInviteStatus($phid);
$is_attending = ($old_status == $attending_status);
return $is_attending;
}
public function getIsUserInvited($phid) {
$uninvited_status = PhabricatorCalendarEventInvitee::STATUS_UNINVITED;
$declined_status = PhabricatorCalendarEventInvitee::STATUS_DECLINED;
$status = $this->getUserInviteStatus($phid);
if ($status == $uninvited_status || $status == $declined_status) {
return false;
}
return true;
}
/* -( Markup Interface )--------------------------------------------------- */
/**
* @task markup
*/
public function getMarkupFieldKey($field) {
$hash = PhabricatorHash::digest($this->getMarkupText($field));
$id = $this->getID();
return "calendar:T{$id}:{$field}:{$hash}";
}
/**
* @task markup
*/
public function getMarkupText($field) {
return $this->getDescription();
}
/**
* @task markup
*/
public function newMarkupEngine($field) {
return PhabricatorMarkupEngine::newCalendarMarkupEngine();
}
/**
* @task markup
*/
public function didMarkupText(
$field,
$output,
PhutilMarkupEngine $engine) {
return $output;
}
/**
* @task markup
*/
public function shouldUseMarkupCache($field) {
return (bool)$this->getID();
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getViewPolicy();
case PhabricatorPolicyCapability::CAN_EDIT:
return $this->getEditPolicy();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
// The owner of a task can always view and edit it.
$user_phid = $this->getUserPHID();
if ($user_phid) {
$viewer_phid = $viewer->getPHID();
if ($viewer_phid == $user_phid) {
return true;
}
}
if ($capability == PhabricatorPolicyCapability::CAN_VIEW) {
$status = $this->getUserInviteStatus($viewer->getPHID());
if ($status == PhabricatorCalendarEventInvitee::STATUS_INVITED ||
$status == PhabricatorCalendarEventInvitee::STATUS_ATTENDING ||
$status == PhabricatorCalendarEventInvitee::STATUS_DECLINED) {
return true;
}
}
return false;
}
public function describeAutomaticCapability($capability) {
return pht('The owner of an event can always view and edit it,
and invitees can always view it.');
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new PhabricatorCalendarEventEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new PhabricatorCalendarEventTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
/* -( PhabricatorSubscribableInterface )----------------------------------- */
public function isAutomaticallySubscribed($phid) {
return ($phid == $this->getUserPHID());
}
public function shouldShowSubscribersProperty() {
return true;
}
public function shouldAllowSubscription($phid) {
return true;
}
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
public function getUsersToNotifyOfTokenGiven() {
return array($this->getUserPHID());
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
$this->openTransaction();
$this->delete();
$this->saveTransaction();
}
}
diff --git a/src/view/phui/PHUICrumbsView.php b/src/view/phui/PHUICrumbsView.php
index 95d78a268c..11ec90fafe 100644
--- a/src/view/phui/PHUICrumbsView.php
+++ b/src/view/phui/PHUICrumbsView.php
@@ -1,123 +1,124 @@
<?php
final class PHUICrumbsView extends AphrontView {
private $crumbs = array();
private $actions = array();
private $border;
protected function canAppendChild() {
return false;
}
/**
* Convenience method for adding a simple crumb with just text, or text and
* a link.
*
* @param string Text of the crumb.
* @param string? Optional href for the crumb.
* @return this
*/
public function addTextCrumb($text, $href = null) {
return $this->addCrumb(
id(new PHUICrumbView())
->setName($text)
->setHref($href));
}
public function addCrumb(PHUICrumbView $crumb) {
$this->crumbs[] = $crumb;
return $this;
}
public function addAction(PHUIListItemView $action) {
$this->actions[] = $action;
return $this;
}
public function setBorder($border) {
$this->border = $border;
return $this;
}
public function render() {
require_celerity_resource('phui-crumbs-view-css');
$action_view = null;
if ($this->actions) {
$actions = array();
foreach ($this->actions as $action) {
$icon = null;
if ($action->getIcon()) {
$icon_name = $action->getIcon();
if ($action->getDisabled()) {
$icon_name .= ' lightgreytext';
}
$icon = id(new PHUIIconView())
->setIconFont($icon_name);
}
$name = phutil_tag(
'span',
array(
'class' => 'phui-crumbs-action-name',
),
$action->getName());
$action_sigils = $action->getSigils();
if ($action->getWorkflow()) {
$action_sigils[] = 'workflow';
}
$action_classes = $action->getClasses();
$action_classes[] = 'phui-crumbs-action';
if ($action->getDisabled()) {
$action_classes[] = 'phui-crumbs-action-disabled';
}
$actions[] = javelin_tag(
'a',
array(
'href' => $action->getHref(),
'class' => implode(' ', $action_classes),
'sigil' => implode(' ', $action_sigils),
'style' => $action->getStyle(),
+ 'meta' => $action->getMetadata(),
),
array(
$icon,
$name,
));
}
$action_view = phutil_tag(
'div',
array(
'class' => 'phui-crumbs-actions',
),
$actions);
}
if ($this->crumbs) {
last($this->crumbs)->setIsLastCrumb(true);
}
$classes = array();
$classes[] = 'phui-crumbs-view';
if ($this->border) {
$classes[] = 'phui-crumbs-border';
}
return phutil_tag(
'div',
array(
'class' => implode(' ', $classes),
),
array(
$action_view,
$this->crumbs,
));
}
}
diff --git a/src/view/phui/PHUIListItemView.php b/src/view/phui/PHUIListItemView.php
index 79eb6c0f44..e2e347306f 100644
--- a/src/view/phui/PHUIListItemView.php
+++ b/src/view/phui/PHUIListItemView.php
@@ -1,263 +1,275 @@
<?php
final class PHUIListItemView extends AphrontTagView {
const TYPE_LINK = 'type-link';
const TYPE_SPACER = 'type-spacer';
const TYPE_LABEL = 'type-label';
const TYPE_BUTTON = 'type-button';
const TYPE_CUSTOM = 'type-custom';
const TYPE_DIVIDER = 'type-divider';
const TYPE_ICON = 'type-icon';
const TYPE_ICON_NAV = 'type-icon-nav';
const STATUS_WARN = 'phui-list-item-warn';
const STATUS_FAIL = 'phui-list-item-fail';
private $name;
private $href;
private $type = self::TYPE_LINK;
private $isExternal;
private $key;
private $icon;
private $appIcon;
private $selected;
private $disabled;
private $renderNameAsTooltip;
private $statusColor;
private $order;
private $aural;
private $profileImage;
+ public function setDropdownMenu(PhabricatorActionListView $actions) {
+ Javelin::initBehavior('phui-dropdown-menu');
+
+ $this->addSigil('phui-dropdown-menu');
+ $this->setMetadata(
+ array(
+ 'items' => $actions,
+ ));
+
+ return $this;
+ }
+
public function setAural($aural) {
$this->aural = $aural;
return $this;
}
public function getAural() {
return $this->aural;
}
public function setOrder($order) {
$this->order = $order;
return $this;
}
public function getOrder() {
return $this->order;
}
public function setRenderNameAsTooltip($render_name_as_tooltip) {
$this->renderNameAsTooltip = $render_name_as_tooltip;
return $this;
}
public function getRenderNameAsTooltip() {
return $this->renderNameAsTooltip;
}
public function setSelected($selected) {
$this->selected = $selected;
return $this;
}
public function getSelected() {
return $this->selected;
}
public function setIcon($icon) {
$this->icon = $icon;
return $this;
}
public function setProfileImage($image) {
$this->profileImage = $image;
return $this;
}
public function getIcon() {
return $this->icon;
}
public function setKey($key) {
$this->key = (string)$key;
return $this;
}
public function getKey() {
return $this->key;
}
public function setType($type) {
$this->type = $type;
return $this;
}
public function getType() {
return $this->type;
}
public function setHref($href) {
$this->href = $href;
return $this;
}
public function getHref() {
return $this->href;
}
public function setName($name) {
$this->name = $name;
return $this;
}
public function getName() {
return $this->name;
}
public function setIsExternal($is_external) {
$this->isExternal = $is_external;
return $this;
}
public function getIsExternal() {
return $this->isExternal;
}
public function setStatusColor($color) {
$this->statusColor = $color;
return $this;
}
protected function getTagName() {
return 'li';
}
protected function getTagAttributes() {
$classes = array();
$classes[] = 'phui-list-item-view';
$classes[] = 'phui-list-item-'.$this->type;
if ($this->icon || $this->appIcon) {
$classes[] = 'phui-list-item-has-icon';
}
if ($this->selected) {
$classes[] = 'phui-list-item-selected';
}
if ($this->disabled) {
$classes[] = 'phui-list-item-disabled';
}
if ($this->statusColor) {
$classes[] = $this->statusColor;
}
return array(
'class' => $classes,
);
}
public function setDisabled($disabled) {
$this->disabled = $disabled;
return $this;
}
public function getDisabled() {
return $this->disabled;
}
protected function getTagContent() {
$name = null;
$icon = null;
$meta = null;
$sigil = null;
if ($this->name) {
if ($this->getRenderNameAsTooltip()) {
Javelin::initBehavior('phabricator-tooltips');
$sigil = 'has-tooltip';
$meta = array(
'tip' => $this->name,
'align' => 'E',
);
} else {
$external = null;
if ($this->isExternal) {
$external = " \xE2\x86\x97";
}
// If this element has an aural representation, make any name visual
// only. This is primarily dealing with the links in the main menu like
// "Profile" and "Logout". If we don't hide the name, the mobile
// version of these elements will have two redundant names.
$classes = array();
$classes[] = 'phui-list-item-name';
if ($this->aural !== null) {
$classes[] = 'visual-only';
}
$name = phutil_tag(
'span',
array(
'class' => implode(' ', $classes),
),
array(
$this->name,
$external,
));
}
}
$aural = null;
if ($this->aural !== null) {
$aural = javelin_tag(
'span',
array(
'aural' => true,
),
$this->aural);
}
if ($this->icon) {
$icon_name = $this->icon;
if ($this->getDisabled()) {
$icon_name .= ' grey';
}
$icon = id(new PHUIIconView())
->addClass('phui-list-item-icon')
->setIconFont($icon_name);
}
if ($this->profileImage) {
$icon = id(new PHUIIconView())
->setHeadSize(PHUIIconView::HEAD_SMALL)
->setImage($this->profileImage);
}
if ($this->appIcon) {
$icon = id(new PHUIIconView())
->addClass('phui-list-item-icon')
->setIconFont($this->appIcon);
}
return javelin_tag(
$this->href ? 'a' : 'div',
array(
'href' => $this->href,
'class' => $this->href ? 'phui-list-item-href' : null,
'meta' => $meta,
'sigil' => $sigil,
),
array(
$aural,
$icon,
$this->renderChildren(),
$name,
));
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Dec 2, 11:32 AM (21 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
431852
Default Alt Text
(34 KB)

Event Timeline