[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/view/phui/ -> PHUITimelineEventView.php (source)

   1  <?php
   2  
   3  final class PHUITimelineEventView extends AphrontView {
   4  
   5    const DELIMITER = " \xC2\xB7 ";
   6  
   7    private $userHandle;
   8    private $title;
   9    private $icon;
  10    private $color;
  11    private $classes = array();
  12    private $contentSource;
  13    private $dateCreated;
  14    private $anchor;
  15    private $isEditable;
  16    private $isEdited;
  17    private $isRemovable;
  18    private $transactionPHID;
  19    private $isPreview;
  20    private $eventGroup = array();
  21    private $hideByDefault;
  22    private $token;
  23    private $tokenRemoved;
  24    private $quoteTargetID;
  25    private $quoteRef;
  26    private $reallyMajorEvent;
  27  
  28    public function setQuoteRef($quote_ref) {
  29      $this->quoteRef = $quote_ref;
  30      return $this;
  31    }
  32  
  33    public function getQuoteRef() {
  34      return $this->quoteRef;
  35    }
  36  
  37    public function setQuoteTargetID($quote_target_id) {
  38      $this->quoteTargetID = $quote_target_id;
  39      return $this;
  40    }
  41  
  42    public function getQuoteTargetID() {
  43      return $this->quoteTargetID;
  44    }
  45  
  46    public function setHideByDefault($hide_by_default) {
  47      $this->hideByDefault = $hide_by_default;
  48      return $this;
  49    }
  50  
  51    public function getHideByDefault() {
  52      return $this->hideByDefault;
  53    }
  54  
  55    public function setTransactionPHID($transaction_phid) {
  56      $this->transactionPHID = $transaction_phid;
  57      return $this;
  58    }
  59  
  60    public function getTransactionPHID() {
  61      return $this->transactionPHID;
  62    }
  63  
  64    public function setIsEdited($is_edited) {
  65      $this->isEdited = $is_edited;
  66      return $this;
  67    }
  68  
  69    public function getIsEdited() {
  70      return $this->isEdited;
  71    }
  72  
  73    public function setIsPreview($is_preview) {
  74      $this->isPreview = $is_preview;
  75      return $this;
  76    }
  77  
  78    public function getIsPreview() {
  79      return $this->isPreview;
  80    }
  81  
  82    public function setIsEditable($is_editable) {
  83      $this->isEditable = $is_editable;
  84      return $this;
  85    }
  86  
  87    public function getIsEditable() {
  88      return $this->isEditable;
  89    }
  90  
  91    public function setIsRemovable($is_removable) {
  92      $this->isRemovable = $is_removable;
  93      return $this;
  94    }
  95  
  96    public function getIsRemovable() {
  97      return $this->isRemovable;
  98    }
  99  
 100    public function setDateCreated($date_created) {
 101      $this->dateCreated = $date_created;
 102      return $this;
 103    }
 104  
 105    public function getDateCreated() {
 106      return $this->dateCreated;
 107    }
 108  
 109    public function setContentSource(PhabricatorContentSource $content_source) {
 110      $this->contentSource = $content_source;
 111      return $this;
 112    }
 113  
 114    public function getContentSource() {
 115      return $this->contentSource;
 116    }
 117  
 118    public function setUserHandle(PhabricatorObjectHandle $handle) {
 119      $this->userHandle = $handle;
 120      return $this;
 121    }
 122  
 123    public function setAnchor($anchor) {
 124      $this->anchor = $anchor;
 125      return $this;
 126    }
 127  
 128    public function getAnchor() {
 129      return $this->anchor;
 130    }
 131  
 132    public function setTitle($title) {
 133      $this->title = $title;
 134      return $this;
 135    }
 136  
 137    public function addClass($class) {
 138      $this->classes[] = $class;
 139      return $this;
 140    }
 141  
 142    public function setIcon($icon) {
 143      $this->icon = $icon;
 144      return $this;
 145    }
 146  
 147    public function setColor($color) {
 148      $this->color = $color;
 149      return $this;
 150    }
 151  
 152    public function setReallyMajorEvent($me) {
 153      $this->reallyMajorEvent = $me;
 154      return $this;
 155    }
 156  
 157    public function setToken($token, $removed = false) {
 158      $this->token = $token;
 159      $this->tokenRemoved = $removed;
 160      return $this;
 161    }
 162  
 163    public function getEventGroup() {
 164      return array_merge(array($this), $this->eventGroup);
 165    }
 166  
 167    public function addEventToGroup(PHUITimelineEventView $event) {
 168      $this->eventGroup[] = $event;
 169      return $this;
 170    }
 171  
 172    protected function shouldRenderEventTitle() {
 173      if ($this->title === null) {
 174        return false;
 175      }
 176  
 177      return true;
 178    }
 179  
 180    protected function renderEventTitle($force_icon, $has_menu, $extra) {
 181      $title = $this->title;
 182  
 183      $title_classes = array();
 184      $title_classes[] = 'phui-timeline-title';
 185  
 186      $icon = null;
 187      if ($this->icon || $force_icon) {
 188        $title_classes[] = 'phui-timeline-title-with-icon';
 189      }
 190  
 191      if ($has_menu) {
 192        $title_classes[] = 'phui-timeline-title-with-menu';
 193      }
 194  
 195      if ($this->icon) {
 196        $fill_classes = array();
 197        $fill_classes[] = 'phui-timeline-icon-fill';
 198        if ($this->color) {
 199          $fill_classes[] = 'phui-timeline-icon-fill-'.$this->color;
 200        }
 201  
 202        $icon = id(new PHUIIconView())
 203          ->setIconFont($this->icon.' white')
 204          ->addClass('phui-timeline-icon');
 205  
 206        $icon = phutil_tag(
 207          'span',
 208          array(
 209            'class' => implode(' ', $fill_classes),
 210          ),
 211          $icon);
 212      }
 213  
 214      $token = null;
 215      if ($this->token) {
 216        $token = id(new PHUIIconView())
 217          ->addClass('phui-timeline-token')
 218          ->setSpriteSheet(PHUIIconView::SPRITE_TOKENS)
 219          ->setSpriteIcon($this->token);
 220        if ($this->tokenRemoved) {
 221          $token->addClass('strikethrough');
 222        }
 223      }
 224  
 225      $title = phutil_tag(
 226        'div',
 227        array(
 228          'class' => implode(' ', $title_classes),
 229        ),
 230        array($icon, $token, $title, $extra));
 231  
 232      return $title;
 233    }
 234  
 235    public function render() {
 236  
 237      $events = $this->getEventGroup();
 238  
 239      // Move events with icons first.
 240      $icon_keys = array();
 241      foreach ($this->getEventGroup() as $key => $event) {
 242        if ($event->icon) {
 243          $icon_keys[] = $key;
 244        }
 245      }
 246      $events = array_select_keys($events, $icon_keys) + $events;
 247      $force_icon = (bool)$icon_keys;
 248  
 249      $menu = null;
 250      $items = array();
 251      $has_menu = false;
 252      if (!$this->getIsPreview()) {
 253        foreach ($this->getEventGroup() as $event) {
 254          $items[] = $event->getMenuItems($this->anchor);
 255          if ($event->hasChildren()) {
 256            $has_menu = true;
 257          }
 258        }
 259        $items = array_mergev($items);
 260      }
 261  
 262      if ($items || $has_menu) {
 263        $icon = id(new PHUIIconView())
 264          ->setIconFont('fa-caret-down');
 265        $aural = javelin_tag(
 266          'span',
 267          array(
 268            'aural' => true,
 269          ),
 270          pht('Comment Actions'));
 271  
 272        if ($items) {
 273          $sigil = 'phui-timeline-menu';
 274          Javelin::initBehavior('phui-timeline-dropdown-menu');
 275        } else {
 276          $sigil = null;
 277        }
 278  
 279        $action_list = id(new PhabricatorActionListView())
 280          ->setUser($this->getUser());
 281        foreach ($items as $item) {
 282          $action_list->addAction($item);
 283        }
 284  
 285        $menu = javelin_tag(
 286          $items ? 'a' : 'span',
 287          array(
 288            'href' => '#',
 289            'class' => 'phui-timeline-menu',
 290            'sigil' => $sigil,
 291            'aria-haspopup' => 'true',
 292            'aria-expanded' => 'false',
 293            'meta' => array(
 294              'items' => hsprintf('%s', $action_list),
 295            ),
 296          ),
 297          array(
 298            $aural,
 299            $icon,
 300          ));
 301  
 302        $has_menu = true;
 303      }
 304  
 305      // Render "extra" information (timestamp, etc).
 306      $extra = $this->renderExtra($events);
 307  
 308      $group_titles = array();
 309      $group_items = array();
 310      $group_children = array();
 311      foreach ($events as $event) {
 312        if ($event->shouldRenderEventTitle()) {
 313          $group_titles[] = $event->renderEventTitle(
 314            $force_icon,
 315            $has_menu,
 316            $extra);
 317  
 318          // Don't render this information more than once.
 319          $extra = null;
 320        }
 321  
 322        if ($event->hasChildren()) {
 323          $group_children[] = $event->renderChildren();
 324        }
 325      }
 326  
 327      $image_uri = $this->userHandle->getImageURI();
 328  
 329      $wedge = phutil_tag(
 330        'div',
 331        array(
 332          'class' => 'phui-timeline-wedge phui-timeline-border',
 333          'style' => (nonempty($image_uri)) ? '' : 'display: none;',
 334        ),
 335        '');
 336  
 337      $image = phutil_tag(
 338        'div',
 339        array(
 340          'style' => 'background-image: url('.$image_uri.')',
 341          'class' => 'phui-timeline-image',
 342        ),
 343        '');
 344  
 345      $content_classes = array();
 346      $content_classes[] = 'phui-timeline-content';
 347  
 348      $classes = array();
 349      $classes[] = 'phui-timeline-event-view';
 350      if ($group_children) {
 351        $classes[] = 'phui-timeline-major-event';
 352        $content = phutil_tag(
 353          'div',
 354          array(
 355            'class' => 'phui-timeline-inner-content',
 356          ),
 357          array(
 358            $group_titles,
 359            $menu,
 360            phutil_tag(
 361              'div',
 362              array(
 363                'class' => 'phui-timeline-core-content',
 364              ),
 365              $group_children),
 366          ));
 367      } else {
 368        $classes[] = 'phui-timeline-minor-event';
 369        $content = $group_titles;
 370      }
 371  
 372      $content = phutil_tag(
 373        'div',
 374        array(
 375          'class' => 'phui-timeline-group phui-timeline-border',
 376        ),
 377        $content);
 378  
 379      $content = phutil_tag(
 380        'div',
 381        array(
 382          'class' => implode(' ', $content_classes),
 383        ),
 384        array($image, $wedge, $content));
 385  
 386      $outer_classes = $this->classes;
 387      $outer_classes[] = 'phui-timeline-shell';
 388      $color = null;
 389      foreach ($this->getEventGroup() as $event) {
 390        if ($event->color) {
 391          $color = $event->color;
 392          break;
 393        }
 394      }
 395  
 396      if ($color) {
 397        $outer_classes[] = 'phui-timeline-'.$color;
 398      }
 399  
 400      $sigil = null;
 401      $meta = null;
 402      if ($this->getTransactionPHID()) {
 403        $sigil = 'transaction';
 404        $meta = array(
 405          'phid' => $this->getTransactionPHID(),
 406          'anchor' => $this->anchor,
 407        );
 408      }
 409  
 410      $major_event = null;
 411      if ($this->reallyMajorEvent) {
 412        $major_event = phutil_tag(
 413          'div',
 414          array(
 415            'class' => 'phui-timeline-event-view '.
 416                       'phui-timeline-spacer '.
 417                       'phui-timeline-spacer-bold',
 418          '',));
 419      }
 420  
 421      return array(
 422        javelin_tag(
 423          'div',
 424          array(
 425            'class' => implode(' ', $outer_classes),
 426            'id' => $this->anchor ? 'anchor-'.$this->anchor : null,
 427            'sigil' => $sigil,
 428            'meta' => $meta,
 429          ),
 430          phutil_tag(
 431            'div',
 432            array(
 433              'class' => implode(' ', $classes),
 434            ),
 435            $content)),
 436        $major_event,);
 437    }
 438  
 439    private function renderExtra(array $events) {
 440      $extra = array();
 441  
 442      if ($this->getIsPreview()) {
 443        $extra[] = pht('PREVIEW');
 444      } else {
 445        foreach ($events as $event) {
 446          if ($event->getIsEdited()) {
 447            $extra[] = pht('Edited');
 448            break;
 449          }
 450        }
 451  
 452        $source = $this->getContentSource();
 453        if ($source) {
 454          $extra[] = id(new PhabricatorContentSourceView())
 455            ->setContentSource($source)
 456            ->setUser($this->getUser())
 457            ->render();
 458        }
 459  
 460        $date_created = null;
 461        foreach ($events as $event) {
 462          if ($event->getDateCreated()) {
 463            if ($date_created === null) {
 464              $date_created = $event->getDateCreated();
 465            } else {
 466              $date_created = min($event->getDateCreated(), $date_created);
 467            }
 468          }
 469        }
 470  
 471        if ($date_created) {
 472          $date = phabricator_datetime(
 473            $date_created,
 474            $this->getUser());
 475          if ($this->anchor) {
 476            Javelin::initBehavior('phabricator-watch-anchor');
 477  
 478            $anchor = id(new PhabricatorAnchorView())
 479              ->setAnchorName($this->anchor)
 480              ->render();
 481  
 482            $date = array(
 483              $anchor,
 484              phutil_tag(
 485                'a',
 486                array(
 487                  'href' => '#'.$this->anchor,
 488                ),
 489                $date),
 490            );
 491          }
 492          $extra[] = $date;
 493        }
 494      }
 495  
 496      $extra = javelin_tag(
 497        'span',
 498        array(
 499          'class' => 'phui-timeline-extra',
 500        ),
 501        phutil_implode_html(
 502          javelin_tag(
 503            'span',
 504            array(
 505              'aural' => false,
 506            ),
 507            self::DELIMITER),
 508          $extra));
 509  
 510      return $extra;
 511    }
 512  
 513    private function getMenuItems($anchor) {
 514      $xaction_phid = $this->getTransactionPHID();
 515  
 516      $items = array();
 517  
 518      if ($this->getIsEditable()) {
 519        $items[] = id(new PhabricatorActionView())
 520          ->setIcon('fa-pencil')
 521          ->setHref('/transactions/edit/'.$xaction_phid.'/')
 522          ->setName(pht('Edit Comment'))
 523          ->addSigil('transaction-edit')
 524          ->setMetadata(
 525            array(
 526              'anchor' => $anchor,
 527            ));
 528      }
 529  
 530      if ($this->getQuoteTargetID()) {
 531        $ref = null;
 532        if ($this->getQuoteRef()) {
 533          $ref = $this->getQuoteRef();
 534          if ($anchor) {
 535            $ref = $ref.'#'.$anchor;
 536          }
 537        }
 538  
 539        $items[] = id(new PhabricatorActionView())
 540          ->setIcon('fa-quote-left')
 541          ->setHref('#')
 542          ->setName(pht('Quote'))
 543          ->addSigil('transaction-quote')
 544          ->setMetadata(
 545            array(
 546              'targetID' => $this->getQuoteTargetID(),
 547              'uri' => '/transactions/quote/'.$xaction_phid.'/',
 548              'ref' => $ref,
 549            ));
 550  
 551        // if there is something to quote then there is something to view raw
 552        $items[] = id(new PhabricatorActionView())
 553          ->setIcon('fa-cutlery')
 554          ->setHref('/transactions/raw/'.$xaction_phid.'/')
 555          ->setName(pht('View Raw'))
 556          ->addSigil('transaction-raw')
 557          ->setMetadata(
 558            array(
 559              'anchor' => $anchor,
 560            ));
 561  
 562        $content_source = $this->getContentSource();
 563        $source_email = PhabricatorContentSource::SOURCE_EMAIL;
 564        if ($content_source->getSource() == $source_email) {
 565          $source_id = $content_source->getParam('id');
 566          if ($source_id) {
 567            $items[] = id(new PhabricatorActionView())
 568              ->setIcon('fa-envelope-o')
 569              ->setHref('/transactions/raw/'.$xaction_phid.'/?email')
 570              ->setName(pht('View Email Body'))
 571              ->addSigil('transaction-raw')
 572              ->setMetadata(
 573                array(
 574                  'anchor' => $anchor,
 575                ));
 576          }
 577        }
 578      }
 579  
 580      if ($this->getIsRemovable()) {
 581        $items[] = id(new PhabricatorActionView())
 582          ->setIcon('fa-times')
 583          ->setHref('/transactions/remove/'.$xaction_phid.'/')
 584          ->setName(pht('Remove Comment'))
 585          ->addSigil('transaction-remove')
 586          ->setMetadata(
 587            array(
 588              'anchor' => $anchor,
 589            ));
 590  
 591      }
 592  
 593      if ($this->getIsEdited()) {
 594        $items[] = id(new PhabricatorActionView())
 595          ->setIcon('fa-list')
 596          ->setHref('/transactions/history/'.$xaction_phid.'/')
 597          ->setName(pht('View Edit History'))
 598          ->setWorkflow(true);
 599      }
 600  
 601      return $items;
 602    }
 603  
 604  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1