1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-27 01:02:42 +01:00

Conpherence - make pontificate be all ajaxy

Summary: serving up for some feedback -- does anything fancy need to happen when new messages load (say highlight em and fade the highlight out) or just scrolling down okay? in JS I have a TODO about how come it doesn't work; that code works okay in my console if I print out various debugging values and enter them in manually.

Test Plan: pontificate with myself; note new message and message entry updates properly. pontificate as different user then as myself; note two messages load and message entry updates properly. pontificate as a user who isn't the last to reply; note new message and message entry updates properly

Reviewers: epriestley, chad

Reviewed By: epriestley

CC: aran, Korvin

Maniphest Tasks: T2522

Differential Revision: https://secure.phabricator.com/D5214
This commit is contained in:
Bob Trahan 2013-03-05 15:45:36 -08:00
parent c23a9c9fde
commit 243b99f39e
8 changed files with 327 additions and 114 deletions

View file

@ -1162,6 +1162,21 @@ celerity_register_resource_map(array(
),
'disk' => '/rsrc/js/application/conpherence/behavior-menu.js',
),
'javelin-behavior-conpherence-pontificate' =>
array(
'uri' => '/res/7fb8cf6e/rsrc/js/application/conpherence/behavior-pontificate.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-workflow',
3 => 'javelin-util',
4 => 'javelin-stratcom',
5 => 'javelin-uri',
),
'disk' => '/rsrc/js/application/conpherence/behavior-pontificate.js',
),
'javelin-behavior-conpherence-widget-pane' =>
array(
'uri' => '/res/4fb51b46/rsrc/js/application/conpherence/behavior-widget-pane.js',

View file

@ -216,6 +216,7 @@ phutil_register_library_map(array(
'ConpherenceParticipantQuery' => 'applications/conpherence/query/ConpherenceParticipantQuery.php',
'ConpherenceParticipationStatus' => 'applications/conpherence/constants/ConpherenceParticipationStatus.php',
'ConpherencePeopleMenuEventListener' => 'applications/conpherence/events/ConpherencePeopleMenuEventListener.php',
'ConpherencePontificateControl' => 'applications/conpherence/view/ConpherencePontificateControl.php',
'ConpherenceReplyHandler' => 'applications/conpherence/mail/ConpherenceReplyHandler.php',
'ConpherenceThread' => 'applications/conpherence/storage/ConpherenceThread.php',
'ConpherenceThreadQuery' => 'applications/conpherence/query/ConpherenceThreadQuery.php',
@ -1759,6 +1760,7 @@ phutil_register_library_map(array(
'ConpherenceParticipantQuery' => 'PhabricatorOffsetPagedQuery',
'ConpherenceParticipationStatus' => 'ConpherenceConstants',
'ConpherencePeopleMenuEventListener' => 'PhutilEventListener',
'ConpherencePontificateControl' => 'AphrontFormControl',
'ConpherenceReplyHandler' => 'PhabricatorMailReplyHandler',
'ConpherenceThread' =>
array(

View file

@ -93,7 +93,7 @@ abstract class ConpherenceController extends PhabricatorController {
return $this;
}
public function buildSideNavView($filter = null) {
public function buildSideNavView($filter = null, $for_application = false) {
require_celerity_resource('conpherence-menu-css');
$unread_conpherences = $this->getUnreadConpherences();
$read_conpherences = $this->getReadConpherences();
@ -109,9 +109,17 @@ abstract class ConpherenceController extends PhabricatorController {
pht('New Conversation'),
$this->getApplicationURI('new/'));
$nav->addLabel(pht('Unread'));
$nav = $this->addConpherencesToNav($unread_conpherences, $nav);
$nav = $this->addConpherencesToNav(
$unread_conpherences,
$nav,
false,
$for_application);
$nav->addLabel(pht('Read'));
$nav = $this->addConpherencesToNav($read_conpherences, $nav, true);
$nav = $this->addConpherencesToNav(
$read_conpherences,
$nav,
true,
$for_application);
$nav->selectFilter($filter);
return $nav;
}
@ -119,37 +127,20 @@ abstract class ConpherenceController extends PhabricatorController {
private function addConpherencesToNav(
array $conpherences,
AphrontSideNavFilterView $nav,
$read = false) {
$read = false,
$for_application = false) {
$user = $this->getRequest()->getUser();
$id_suffix = $for_application ? '-menu-item' : '-nav-item';
foreach ($conpherences as $conpherence) {
$uri = $this->getApplicationURI('view/'.$conpherence->getID().'/');
$data = $conpherence->getDisplayData(
$user,
null);
$title = $data['title'];
$subtitle = $data['subtitle'];
$unread_count = $data['unread_count'];
$epoch = $data['epoch'];
$image = $data['image'];
$snippet = $data['snippet'];
$item = id(new ConpherenceMenuItemView())
->setUser($user)
->setTitle($title)
->setSubtitle($subtitle)
->setHref($uri)
->setEpoch($epoch)
->setImageURI($image)
->setMessageText($snippet)
->setUnreadCount($unread_count)
->setID($conpherence->getPHID())
->addSigil('conpherence-menu-click')
->setMetadata(array('id' => $conpherence->getID()));
$selected = false;
if ($this->getSelectedConpherencePHID() == $conpherence->getPHID()) {
$item->addClass('conpherence-selected');
$item->addClass('hide-unread-count');
$selected = true;
}
$item = $this->buildConpherenceMenuItem(
$conpherence,
$id_suffix,
$selected);
$nav->addCustomBlock($item->render());
}
@ -170,7 +161,9 @@ abstract class ConpherenceController extends PhabricatorController {
}
public function buildApplicationMenu() {
return $this->buildSideNavView()->getMenu();
return $this->buildSideNavView(
$filter = null,
$for_application = true)->getMenu();
}
public function buildApplicationCrumbs() {
@ -189,6 +182,130 @@ abstract class ConpherenceController extends PhabricatorController {
return $crumbs;
}
protected function buildConpherenceMenuItem(
$conpherence,
$id_suffix,
$selected) {
$user = $this->getRequest()->getUser();
$uri = $this->getApplicationURI('view/'.$conpherence->getID().'/');
$data = $conpherence->getDisplayData(
$user,
null);
$title = $data['title'];
$subtitle = $data['subtitle'];
$unread_count = $data['unread_count'];
$epoch = $data['epoch'];
$image = $data['image'];
$snippet = $data['snippet'];
$item = id(new ConpherenceMenuItemView())
->setUser($user)
->setTitle($title)
->setSubtitle($subtitle)
->setHref($uri)
->setEpoch($epoch)
->setImageURI($image)
->setMessageText($snippet)
->setUnreadCount($unread_count)
->setID($conpherence->getPHID().$id_suffix)
->addSigil('conpherence-menu-click')
->setMetadata(array('id' => $conpherence->getID()));
if ($selected) {
$item
->addClass('conpherence-selected')
->addClass('hide-unread-count');
}
return $item;
}
protected function buildHeaderPaneContent(ConpherenceThread $conpherence) {
$user = $this->getRequest()->getUser();
$display_data = $conpherence->getDisplayData(
$user,
ConpherenceImageData::SIZE_HEAD);
$edit_href = $this->getApplicationURI('update/'.$conpherence->getID().'/');
$class_mod = $display_data['image_class'];
$header =
phutil_tag(
'div',
array(
'class' => 'upload-photo'
),
pht('Drop photo here to change this Conpherence photo.')).
javelin_tag(
'a',
array(
'class' => 'edit',
'href' => $edit_href,
'sigil' => 'workflow edit-action',
),
'').
phutil_tag(
'div',
array(
'class' => $class_mod.'header-image',
'style' => 'background-image: url('.$display_data['image'].');'
),
'').
phutil_tag(
'div',
array(
'class' => $class_mod.'title',
),
$display_data['title']).
phutil_tag(
'div',
array(
'class' => $class_mod.'subtitle',
),
$display_data['subtitle']);
return $header;
}
protected function renderConpherenceTransactions(
ConpherenceThread $conpherence) {
$user = $this->getRequest()->getUser();
$transactions = $conpherence->getTransactions();
$handles = $conpherence->getHandles();
$rendered_transactions = array();
$engine = id(new PhabricatorMarkupEngine())
->setViewer($user);
foreach ($transactions as $key => $transaction) {
if ($transaction->shouldHide()) {
unset($transactions[$key]);
continue;
}
if ($transaction->getComment()) {
$engine->addObject(
$transaction->getComment(),
PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT);
}
}
$engine->process();
foreach ($transactions as $transaction) {
$rendered_transactions[] = id(new ConpherenceTransactionView())
->setUser($user)
->setConpherenceTransaction($transaction)
->setHandles($handles)
->setMarkupEngine($engine)
->render();
}
$latest_transaction_id = $transaction->getID();
$rendered_transactions = phutil_implode_html(' ', $rendered_transactions);
return array(
'transactions' => $rendered_transactions,
'latest_transaction_id' => $latest_transaction_id
);
}
protected function initJavelinBehaviors() {
Javelin::initBehavior('conpherence-menu',
@ -217,6 +334,12 @@ abstract class ConpherenceController extends PhabricatorController {
'upload_uri' => '/file/dropupload/',
'activated_class' => 'conpherence-header-upload-photo',
));
Javelin::initBehavior('conpherence-pontificate',
array(
'messages' => 'conpherence-messages',
'header' => 'conpherence-header-pane',
'menu_pane' => 'conpherence-menu',
'form_pane' => 'conpherence-form',
));
}
}

View file

@ -35,7 +35,7 @@ final class ConpherenceUpdateController extends
->executeOne();
$supported_formats = PhabricatorFile::getTransformableImageFormats();
$updated = false;
$latest_transaction_id = null;
$error_view = null;
$e_file = array();
$errors = array();
@ -54,6 +54,7 @@ final class ConpherenceUpdateController extends
switch ($action) {
case 'message':
$message = $request->getStr('text');
$latest_transaction_id = $request->getInt('latest_transaction_id');
$xactions = $editor->generateTransactionsFromText(
$conpherence,
$message);
@ -129,7 +130,16 @@ final class ConpherenceUpdateController extends
if ($xactions) {
try {
$xactions = $editor->applyTransactions($conpherence, $xactions);
$updated = true;
if ($latest_transaction_id) {
$content = $this->loadAndRenderNewTransactions(
$conpherence_id,
$latest_transaction_id);
return id(new AphrontAjaxResponse())
->setContent($content);
} else {
return id(new AphrontRedirectResponse())->setURI(
$this->getApplicationURI($conpherence_id.'/'));
}
} catch (PhabricatorApplicationTransactionNoEffectException $ex) {
return id(new PhabricatorApplicationTransactionNoEffectResponse())
->setCancelURI($this->getApplicationURI($conpherence_id.'/'))
@ -141,11 +151,6 @@ final class ConpherenceUpdateController extends
}
}
if ($updated) {
return id(new AphrontRedirectResponse())->setURI(
$this->getApplicationURI($conpherence_id.'/'));
}
if ($errors) {
$error_view = id(new AphrontErrorView())
->setTitle(pht('Errors editing conpherence.'))
@ -181,9 +186,7 @@ final class ConpherenceUpdateController extends
->appendChild(
id(new ConpherenceFormDragAndDropUploadControl())
->setLabel(pht('Change Image')));
} else {
$form
->appendChild(
id(new ConpherenceFormDragAndDropUploadControl())
@ -204,4 +207,44 @@ final class ConpherenceUpdateController extends
->addSubmitButton()
->addCancelButton($this->getApplicationURI($conpherence->getID().'/')));
}
private function loadAndRenderNewTransactions(
$conpherence_id,
$latest_transaction_id) {
$user = $this->getRequest()->getUser();
$conpherence = id(new ConpherenceThreadQuery())
->setViewer($user)
->setAfterID($latest_transaction_id)
->needHeaderPics(true)
->withIDs(array($conpherence_id))
->executeOne();
$data = $this->renderConpherenceTransactions($conpherence);
$rendered_transactions = $data['transactions'];
$new_latest_transaction_id = $data['latest_transaction_id'];
$selected = true;
$nav_item = $this->buildConpherenceMenuItem(
$conpherence,
'-nav-item',
$selected);
$menu_item = $this->buildConpherenceMenuItem(
$conpherence,
'-menu-item',
$selected);
$header = $this->buildHeaderPaneContent($conpherence);
$content = array(
'transactions' => $rendered_transactions,
'latest_transaction_id' => $new_latest_transaction_id,
'menu_item' => $menu_item->render(),
'nav_item' => $nav_item->render(),
'conpherence_phid' => $conpherence->getPHID(),
'header' => $header
);
return $content;
}
}

View file

@ -59,99 +59,40 @@ final class ConpherenceViewController extends
private function renderHeaderPaneContent() {
require_celerity_resource('conpherence-header-pane-css');
$user = $this->getRequest()->getUser();
$conpherence = $this->getConpherence();
$display_data = $conpherence->getDisplayData(
$user,
ConpherenceImageData::SIZE_HEAD);
$edit_href = $this->getApplicationURI('update/'.$conpherence->getID().'/');
$class_mod = $display_data['image_class'];
$header =
phutil_tag(
'div',
array(
'class' => 'upload-photo'
),
pht('Drop photo here to change this Conpherence photo.')).
javelin_tag(
'a',
array(
'class' => 'edit',
'href' => $edit_href,
'sigil' => 'workflow edit-action',
),
'').
phutil_tag(
'div',
array(
'class' => $class_mod.'header-image',
'style' => 'background-image: url('.$display_data['image'].');'
),
'').
phutil_tag(
'div',
array(
'class' => $class_mod.'title',
),
$display_data['title']).
phutil_tag(
'div',
array(
'class' => $class_mod.'subtitle',
),
$display_data['subtitle']);
$header = $this->buildHeaderPaneContent($conpherence);
return array('header' => $header);
}
private function renderMessagePaneContent() {
require_celerity_resource('conpherence-message-pane-css');
$user = $this->getRequest()->getUser();
$conpherence = $this->getConpherence();
$handles = $conpherence->getHandles();
$rendered_transactions = array();
$data = $this->renderConpherenceTransactions($conpherence);
$latest_transaction_id = $data['latest_transaction_id'];
$transactions = $data['transactions'];
$transactions = $conpherence->getTransactionsFrom(0, 100);
$engine = id(new PhabricatorMarkupEngine())
->setViewer($user);
foreach ($transactions as $transaction) {
if ($transaction->getComment()) {
$engine->addObject(
$transaction->getComment(),
PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT);
}
}
$engine->process();
foreach ($transactions as $transaction) {
if ($transaction->shouldHide()) {
continue;
}
$rendered_transactions[] = id(new ConpherenceTransactionView())
->setUser($user)
->setConpherenceTransaction($transaction)
->setHandles($handles)
->setMarkupEngine($engine)
->render();
}
$transactions = phutil_implode_html(' ', $rendered_transactions);
$update_uri = $this->getApplicationURI('update/'.$conpherence->getID().'/');
$form_id = celerity_generate_unique_node_id();
$form =
id(new AphrontFormView())
->setWorkflow(true)
->setAction($this->getApplicationURI('update/'.$conpherence->getID().'/'))
->setID($form_id)
->setAction($update_uri)
->setFlexible(true)
->setUser($user)
->addHiddenInput('action', 'message')
->addHiddenInput('latest_transaction_id', $latest_transaction_id)
->appendChild(
id(new PhabricatorRemarkupControl())
->setUser($user)
->setName('text'))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Pontificate')))->render();
id(new ConpherencePontificateControl())
->setFormID($form_id))
->render();
$scrollbutton = javelin_tag(
'a',

View file

@ -0,0 +1,29 @@
<?php
final class ConpherencePontificateControl extends AphrontFormControl {
private $formID;
public function setFormID($form_id) {
$this->formID = $form_id;
return $this;
}
public function getFormID() {
return $this->formID;
}
protected function getCustomControlClass() {
return 'aphront-form-control-submit';
}
protected function renderInput() {
return javelin_tag(
'button',
array (
'sigil' => 'conpherence-pontificate',
),
pht('Pontificate'));
}
}

View file

@ -8,7 +8,7 @@ JX.behavior('conpherence-init', function(config) {
// select the current message
var selectedConpherence = false;
if (config.selected_conpherence_id) {
var selected = JX.$(config.selected_conpherence_id);
var selected = JX.$(config.selected_conpherence_id + '-nav-item');
JX.Stratcom.invoke(
'conpherence-initial-selected',
null,

View file

@ -0,0 +1,60 @@
/**
* @provides javelin-behavior-conpherence-pontificate
* @requires javelin-behavior
* javelin-dom
* javelin-request
*/
JX.behavior('conpherence-pontificate', function(config) {
var root = JX.$(config.form_pane);
var onsubmit = function(e) {
e.kill();
var form = JX.DOM.find(root, 'form');
JX.Workflow.newFromForm(form)
.setHandler(JX.bind(this, function(r) {
// add the new transactions, probably just our post but who knows
var messages = JX.$(config.messages);
JX.DOM.appendContent(messages, JX.$H(r.transactions));
messages.scrollTop = messages.scrollHeight;
// update the menu entry as well
JX.DOM.replace(
JX.$(r.conpherence_phid + '-nav-item'),
JX.$H(r.nav_item)
);
JX.DOM.replace(
JX.$(r.conpherence_phid + '-menu-item'),
JX.$H(r.menu_item)
);
// update the header
JX.DOM.setContent(
JX.$(config.header),
JX.$H(r.header)
);
// clear the textarea
var textarea = JX.DOM.find(form, 'textarea');
textarea.value = '';
}))
.start();
};
JX.DOM.listen(
root,
['submit', 'didSyntheticSubmit'],
null,
onsubmit
);
JX.DOM.listen(
root,
['click'],
'conpherence-pontificate',
onsubmit
);
});