1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-17 20:32:41 +01:00

Rebuild Conpherence

Summary:
Minor rebuild / redesign of Conpherence. Most of this is new UX and tossing out things like widgets, device fallbacks. I expect some of the UI to get more polished after next pass, but most everything here is in place.

 - Removed "Widgets", now just a single Participants pane
 - Added "Topic"
 - New header
 - Settings, Edit are action icons
 - Removed a lot of JS
 - Simplified CSS as much as I could

Test Plan:
Desktop, Tablet, Mobile. Adding and removing people. Setting new topics, new rooms.

{F1828662}

{F1828669}

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin

Differential Revision: https://secure.phabricator.com/D16550
This commit is contained in:
Chad Little 2016-09-14 18:34:11 -07:00
parent 98a62c9e49
commit c1c5fbce21
31 changed files with 582 additions and 931 deletions

View file

@ -7,8 +7,8 @@
*/
return array(
'names' => array(
'conpherence.pkg.css' => 'fdc05791',
'core.pkg.css' => '1ca373de',
'conpherence.pkg.css' => '7bddd31a',
'core.pkg.css' => 'dc6d08e3',
'core.pkg.js' => '1d376fa9',
'darkconsole.pkg.js' => 'e7393ebb',
'differential.pkg.css' => '3fb7f532',
@ -19,7 +19,7 @@ return array(
'maniphest.pkg.js' => '949a7498',
'rsrc/css/aphront/aphront-bars.css' => '231ac33c',
'rsrc/css/aphront/dark-console.css' => 'f54bf286',
'rsrc/css/aphront/dialog-view.css' => '913c172e',
'rsrc/css/aphront/dialog-view.css' => '593d3f67',
'rsrc/css/aphront/lightbox-attachment.css' => '7acac05d',
'rsrc/css/aphront/list-filter-view.css' => '5d6f0526',
'rsrc/css/aphront/multi-column.css' => 'fd18389d',
@ -46,12 +46,13 @@ return array(
'rsrc/css/application/config/setup-issue.css' => 'f794cfc3',
'rsrc/css/application/config/unhandled-exception.css' => '4c96257a',
'rsrc/css/application/conpherence/durable-column.css' => '194ac487',
'rsrc/css/application/conpherence/header-pane.css' => 'bdba8a5b',
'rsrc/css/application/conpherence/menu.css' => '8344d122',
'rsrc/css/application/conpherence/message-pane.css' => 'ee0e27be',
'rsrc/css/application/conpherence/message-pane.css' => 'c075e8fe',
'rsrc/css/application/conpherence/notification.css' => '6cdcc253',
'rsrc/css/application/conpherence/transaction.css' => '2c71247c',
'rsrc/css/application/conpherence/update.css' => 'faf6be09',
'rsrc/css/application/conpherence/widget-pane.css' => 'a131d5b6',
'rsrc/css/application/conpherence/transaction.css' => '46253e19',
'rsrc/css/application/conpherence/update.css' => '53bc527a',
'rsrc/css/application/conpherence/widget-pane.css' => '827a21f1',
'rsrc/css/application/contentsource/content-source-view.css' => '4b8b05d4',
'rsrc/css/application/countdown/timer.css' => '16c52f5c',
'rsrc/css/application/daemon/bulk-job.css' => 'df9c1d4a',
@ -108,7 +109,7 @@ return array(
'rsrc/css/core/core.css' => 'd0801452',
'rsrc/css/core/remarkup.css' => 'cd912f2c',
'rsrc/css/core/syntax.css' => '769d3498',
'rsrc/css/core/z-index.css' => '2b01a823',
'rsrc/css/core/z-index.css' => 'a847e919',
'rsrc/css/diviner/diviner-shared.css' => 'aa3656aa',
'rsrc/css/font/font-aleo.css' => '8bdb2835',
'rsrc/css/font/font-awesome.css' => '2b7ebbcc',
@ -437,11 +438,11 @@ return array(
'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => '01774ab2',
'rsrc/js/application/conpherence/behavior-drag-and-drop-photo.js' => 'cf86d16a',
'rsrc/js/application/conpherence/behavior-durable-column.js' => 'd3506890',
'rsrc/js/application/conpherence/behavior-menu.js' => '1d45c74d',
'rsrc/js/application/conpherence/behavior-menu.js' => '7a2f5952',
'rsrc/js/application/conpherence/behavior-participants-pane.js' => '08872fb7',
'rsrc/js/application/conpherence/behavior-pontificate.js' => '21ba5861',
'rsrc/js/application/conpherence/behavior-quicksand-blacklist.js' => '7927a7d3',
'rsrc/js/application/conpherence/behavior-toggle-widget.js' => 'b151bbbc',
'rsrc/js/application/conpherence/behavior-widget-pane.js' => '65845387',
'rsrc/js/application/conpherence/behavior-toggle-widget.js' => '9bdbbab0',
'rsrc/js/application/countdown/timer.js' => 'e4cc26b3',
'rsrc/js/application/daemon/behavior-bulk-job-reload.js' => 'edf8a145',
'rsrc/js/application/dashboard/behavior-dashboard-async-panel.js' => '469c0d9e',
@ -601,7 +602,7 @@ return array(
'almanac-css' => 'dbb9b3af',
'aphront-bars' => '231ac33c',
'aphront-dark-console-css' => 'f54bf286',
'aphront-dialog-view-css' => '913c172e',
'aphront-dialog-view-css' => '593d3f67',
'aphront-list-filter-view-css' => '5d6f0526',
'aphront-multi-column-view-css' => 'fd18389d',
'aphront-panel-view-css' => '8427b78d',
@ -617,13 +618,14 @@ return array(
'config-options-css' => '0ede4c9b',
'config-page-css' => '8798e14f',
'conpherence-durable-column-view' => '194ac487',
'conpherence-header-pane-css' => 'bdba8a5b',
'conpherence-menu-css' => '8344d122',
'conpherence-message-pane-css' => 'ee0e27be',
'conpherence-message-pane-css' => 'c075e8fe',
'conpherence-notification-css' => '6cdcc253',
'conpherence-thread-manager' => '01774ab2',
'conpherence-transaction-css' => '2c71247c',
'conpherence-update-css' => 'faf6be09',
'conpherence-widget-pane-css' => 'a131d5b6',
'conpherence-transaction-css' => '46253e19',
'conpherence-update-css' => '53bc527a',
'conpherence-widget-pane-css' => '827a21f1',
'd3' => 'a11a5ff2',
'differential-changeset-view-css' => '9ef7d354',
'differential-core-view-css' => '5b7b8ff4',
@ -665,9 +667,9 @@ return array(
'javelin-behavior-comment-actions' => '0300eae6',
'javelin-behavior-config-reorder-fields' => 'b6993408',
'javelin-behavior-conpherence-drag-and-drop-photo' => 'cf86d16a',
'javelin-behavior-conpherence-menu' => '1d45c74d',
'javelin-behavior-conpherence-menu' => '7a2f5952',
'javelin-behavior-conpherence-participants-pane' => '08872fb7',
'javelin-behavior-conpherence-pontificate' => '21ba5861',
'javelin-behavior-conpherence-widget-pane' => '65845387',
'javelin-behavior-countdown-timer' => 'e4cc26b3',
'javelin-behavior-dark-console' => 'f411b6ae',
'javelin-behavior-dashboard-async-panel' => '469c0d9e',
@ -773,7 +775,7 @@ return array(
'javelin-behavior-test-payment-form' => 'fc91ab6c',
'javelin-behavior-time-typeahead' => '522431f7',
'javelin-behavior-toggle-class' => '92b9ec77',
'javelin-behavior-toggle-widget' => 'b151bbbc',
'javelin-behavior-toggle-widget' => '9bdbbab0',
'javelin-behavior-typeahead-browse' => '635de1ec',
'javelin-behavior-typeahead-search' => '93d0c9e3',
'javelin-behavior-view-placeholder' => '47830651',
@ -881,7 +883,7 @@ return array(
'phabricator-uiexample-reactor-select' => 'a155550f',
'phabricator-uiexample-reactor-sendclass' => '1def2711',
'phabricator-uiexample-reactor-sendproperties' => 'b1f0ccee',
'phabricator-zindex-css' => '2b01a823',
'phabricator-zindex-css' => 'a847e919',
'phame-css' => '8efb0729',
'pholio-css' => 'ca89d380',
'pholio-edit-css' => '07676f51',
@ -1057,6 +1059,15 @@ return array(
'javelin-stratcom',
'javelin-vector',
),
'08872fb7' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-workflow',
'javelin-util',
'phabricator-notification',
'conpherence-thread-manager',
),
'0a0b10e9' => array(
'javelin-behavior',
'javelin-stratcom',
@ -1135,20 +1146,6 @@ return array(
'javelin-request',
'javelin-uri',
),
'1d45c74d' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'javelin-stratcom',
'javelin-workflow',
'javelin-behavior-device',
'javelin-history',
'javelin-vector',
'javelin-scrollbar',
'phabricator-title',
'phabricator-shaped-request',
'conpherence-thread-manager',
),
'1def2711' => array(
'javelin-install',
'javelin-dom',
@ -1484,19 +1481,6 @@ return array(
'javelin-request',
'javelin-workflow',
),
65845387 => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-workflow',
'javelin-util',
'phabricator-notification',
'javelin-behavior-device',
'phuix-dropdown-menu',
'phuix-action-list-view',
'phuix-action-view',
'conpherence-thread-manager',
),
'680ea2c8' => array(
'javelin-install',
'javelin-dom',
@ -1587,6 +1571,20 @@ return array(
'javelin-behavior',
'javelin-quicksand',
),
'7a2f5952' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'javelin-stratcom',
'javelin-workflow',
'javelin-behavior-device',
'javelin-history',
'javelin-vector',
'javelin-scrollbar',
'phabricator-title',
'phabricator-shaped-request',
'conpherence-thread-manager',
),
'7a68dda3' => array(
'owners-path-editor',
'javelin-behavior',
@ -1755,6 +1753,13 @@ return array(
'phabricator-phtize',
'changeset-view-manager',
),
'9bdbbab0' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'javelin-workflow',
'javelin-stratcom',
),
'9ef7d354' => array(
'phui-inline-comment-view-css',
),
@ -1850,13 +1855,6 @@ return array(
'javelin-util',
'phabricator-shaped-request',
),
'b151bbbc' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'javelin-workflow',
'javelin-stratcom',
),
'b1f0ccee' => array(
'javelin-install',
'javelin-dom',
@ -2311,6 +2309,7 @@ return array(
'conpherence-transaction-css',
'conpherence-update-css',
'conpherence-widget-pane-css',
'conpherence-header-pane-css',
),
'core.pkg.css' => array(
'phabricator-core-css',

View file

@ -159,6 +159,7 @@ return array(
'conpherence-transaction-css',
'conpherence-update-css',
'conpherence-widget-pane-css',
'conpherence-header-pane-css',
),
'differential.pkg.css' => array(
'differential-core-view-css',

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_conpherence.conpherence_thread
ADD topic VARCHAR(255) NOT NULL COLLATE {$COLLATE_TEXT};

View file

@ -300,10 +300,11 @@ phutil_register_library_map(array(
'ConpherenceNewRoomController' => 'applications/conpherence/controller/ConpherenceNewRoomController.php',
'ConpherenceNotificationPanelController' => 'applications/conpherence/controller/ConpherenceNotificationPanelController.php',
'ConpherenceParticipant' => 'applications/conpherence/storage/ConpherenceParticipant.php',
'ConpherenceParticipantController' => 'applications/conpherence/controller/ConpherenceParticipantController.php',
'ConpherenceParticipantCountQuery' => 'applications/conpherence/query/ConpherenceParticipantCountQuery.php',
'ConpherenceParticipantQuery' => 'applications/conpherence/query/ConpherenceParticipantQuery.php',
'ConpherenceParticipantView' => 'applications/conpherence/view/ConpherenceParticipantView.php',
'ConpherenceParticipationStatus' => 'applications/conpherence/constants/ConpherenceParticipationStatus.php',
'ConpherencePeopleWidgetView' => 'applications/conpherence/view/ConpherencePeopleWidgetView.php',
'ConpherencePicCropControl' => 'applications/conpherence/view/ConpherencePicCropControl.php',
'ConpherenceQueryThreadConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceQueryThreadConduitAPIMethod.php',
'ConpherenceQueryTransactionConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceQueryTransactionConduitAPIMethod.php',
@ -329,9 +330,6 @@ phutil_register_library_map(array(
'ConpherenceUpdateController' => 'applications/conpherence/controller/ConpherenceUpdateController.php',
'ConpherenceUpdateThreadConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceUpdateThreadConduitAPIMethod.php',
'ConpherenceViewController' => 'applications/conpherence/controller/ConpherenceViewController.php',
'ConpherenceWidgetConfigConstants' => 'applications/conpherence/constants/ConpherenceWidgetConfigConstants.php',
'ConpherenceWidgetController' => 'applications/conpherence/controller/ConpherenceWidgetController.php',
'ConpherenceWidgetView' => 'applications/conpherence/view/ConpherenceWidgetView.php',
'DarkConsoleController' => 'applications/console/controller/DarkConsoleController.php',
'DarkConsoleCore' => 'applications/console/core/DarkConsoleCore.php',
'DarkConsoleDataController' => 'applications/console/controller/DarkConsoleDataController.php',
@ -4768,10 +4766,11 @@ phutil_register_library_map(array(
'ConpherenceNewRoomController' => 'ConpherenceController',
'ConpherenceNotificationPanelController' => 'ConpherenceController',
'ConpherenceParticipant' => 'ConpherenceDAO',
'ConpherenceParticipantController' => 'ConpherenceController',
'ConpherenceParticipantCountQuery' => 'PhabricatorOffsetPagedQuery',
'ConpherenceParticipantQuery' => 'PhabricatorOffsetPagedQuery',
'ConpherenceParticipantView' => 'AphrontView',
'ConpherenceParticipationStatus' => 'ConpherenceConstants',
'ConpherencePeopleWidgetView' => 'ConpherenceWidgetView',
'ConpherencePicCropControl' => 'AphrontFormControl',
'ConpherenceQueryThreadConduitAPIMethod' => 'ConpherenceConduitAPIMethod',
'ConpherenceQueryTransactionConduitAPIMethod' => 'ConpherenceConduitAPIMethod',
@ -4803,9 +4802,6 @@ phutil_register_library_map(array(
'ConpherenceUpdateController' => 'ConpherenceController',
'ConpherenceUpdateThreadConduitAPIMethod' => 'ConpherenceConduitAPIMethod',
'ConpherenceViewController' => 'ConpherenceController',
'ConpherenceWidgetConfigConstants' => 'ConpherenceConstants',
'ConpherenceWidgetController' => 'ConpherenceController',
'ConpherenceWidgetView' => 'AphrontView',
'DarkConsoleController' => 'PhabricatorController',
'DarkConsoleCore' => 'Phobject',
'DarkConsoleDataController' => 'PhabricatorController',

View file

@ -42,7 +42,7 @@ final class PhabricatorConpherenceApplication extends PhabricatorApplication {
'search/(?:query/(?P<queryKey>[^/]+)/)?'
=> 'ConpherenceRoomListController',
'panel/' => 'ConpherenceNotificationPanelController',
'widget/(?P<id>[1-9]\d*)/' => 'ConpherenceWidgetController',
'participant/(?P<id>[1-9]\d*)/' => 'ConpherenceParticipantController',
'update/(?P<id>[1-9]\d*)/' => 'ConpherenceUpdateController',
),
);

View file

@ -13,8 +13,9 @@ final class ConpherenceCreateThreadConduitAPIMethod
protected function defineParamTypes() {
return array(
'title' => 'optional string',
'message' => 'required string',
'title' => 'required string',
'topic' => 'optional string',
'message' => 'optional string',
'participantPHIDs' => 'required list<phids>',
);
}
@ -27,8 +28,8 @@ final class ConpherenceCreateThreadConduitAPIMethod
return array(
'ERR_EMPTY_PARTICIPANT_PHIDS' => pht(
'You must specify participant phids.'),
'ERR_EMPTY_MESSAGE' => pht(
'You must specify a message.'),
'ERR_EMPTY_TITLE' => pht(
'You must specify a title.'),
);
}
@ -36,19 +37,21 @@ final class ConpherenceCreateThreadConduitAPIMethod
$participant_phids = $request->getValue('participantPHIDs', array());
$message = $request->getValue('message');
$title = $request->getValue('title');
$topic = $request->getValue('topic');
list($errors, $conpherence) = ConpherenceEditor::createThread(
$request->getUser(),
$participant_phids,
$title,
$message,
$request->newContentSource());
$request->newContentSource(),
$topic);
if ($errors) {
foreach ($errors as $error_code) {
switch ($error_code) {
case ConpherenceEditor::ERROR_EMPTY_MESSAGE:
throw new ConduitException('ERR_EMPTY_MESSAGE');
case ConpherenceEditor::ERROR_EMPTY_TITLE:
throw new ConduitException('ERR_EMPTY_TITLE');
break;
case ConpherenceEditor::ERROR_EMPTY_PARTICIPANTS:
throw new ConduitException('ERR_EMPTY_PARTICIPANT_PHIDS');

View file

@ -1,42 +0,0 @@
<?php
final class ConpherenceWidgetConfigConstants extends ConpherenceConstants {
const UPDATE_URI = '/conpherence/update/';
public static function getWidgetPaneBehaviorConfig() {
return array(
'widgetBaseUpdateURI' => self::UPDATE_URI,
'widgetRegistry' => self::getWidgetRegistry(),
);
}
public static function getWidgetRegistry() {
return array(
'conpherence-message-pane' => array(
'name' => pht('Thread'),
'icon' => 'fa-comment',
'deviceOnly' => true,
'hasCreate' => false,
),
'widgets-people' => array(
'name' => pht('Participants'),
'icon' => 'fa-users',
'deviceOnly' => false,
'hasCreate' => true,
'createData' => array(
'refreshFromResponse' => true,
'action' => ConpherenceUpdateActions::ADD_PERSON,
'customHref' => null,
),
),
'widgets-settings' => array(
'name' => pht('Notifications'),
'icon' => 'fa-wrench',
'deviceOnly' => false,
'hasCreate' => false,
),
);
}
}

View file

@ -14,81 +14,78 @@ abstract class ConpherenceController extends PhabricatorController {
public function buildApplicationMenu() {
$nav = new PHUIListView();
$conpherence = $this->conpherence;
// Local Links
if ($conpherence) {
$nav->addMenuItem(
id(new PHUIListItemView())
->setName(pht('Edit Room'))
->setType(PHUIListItemView::TYPE_LINK)
->setHref(
$this->getApplicationURI('update/'.$conpherence->getID()).'/')
->setWorkflow(true));
$nav->addMenuItem(
id(new PHUIListItemView())
->setName(pht('Add Participants'))
->setType(PHUIListItemView::TYPE_LINK)
->setHref('#')
->addSigil('conpherence-widget-adder')
->setMetadata(array('widget' => 'widgets-people')));
}
// Global Links
$nav->newLabel(pht('Conpherence'));
$nav->newLink(
pht('New Room'),
$this->getApplicationURI('new/'));
$nav->addMenuItem(
id(new PHUIListItemView())
->setName(pht('Add Participants'))
->setType(PHUIListItemView::TYPE_LINK)
->setHref('#')
->addSigil('conpherence-widget-adder')
->setMetadata(array('widget' => 'widgets-people')));
$nav->newLink(
pht('Search Rooms'),
$this->getApplicationURI('search/'));
return $nav;
}
protected function buildApplicationCrumbs() {
return $this->buildConpherenceApplicationCrumbs();
}
protected function buildConpherenceApplicationCrumbs($is_rooms = false) {
$crumbs = parent::buildApplicationCrumbs();
$crumbs->setBorder(true);
if (!$is_rooms) {
$crumbs
->addAction(
id(new PHUIListItemView())
->setName(pht('Room'))
->setHref('#')
->setIcon('fa-bars')
->setStyle('display: none;')
->addClass('device-widgets-selector')
->addSigil('device-widgets-selector'));
}
return $crumbs;
}
protected function buildHeaderPaneContent(
ConpherenceThread $conpherence,
array $policy_objects) {
assert_instances_of($policy_objects, 'PhabricatorPolicy');
$viewer = $this->getViewer();
$crumbs = $this->buildApplicationCrumbs();
$header = null;
if ($conpherence->getID()) {
$data = $conpherence->getDisplayData($this->getViewer());
$crumbs->addCrumb(
id(new PHUICrumbView())
->setName($data['title'])
->setHref('/'.$conpherence->getMonogram()));
$can_edit = PhabricatorPolicyFilter::hasCapability(
$header = id(new PHUIHeaderView())
->setHeader($data['title'])
->setSubheader($data['topic'])
->addClass((!$data['topic']) ? 'conpherence-no-topic' : null);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$conpherence,
PhabricatorPolicyCapability::CAN_EDIT);
$crumbs
->addAction(
id(new PHUIListItemView())
->setName(pht('Edit Room'))
$header->addActionItem(
id(new PHUIIconCircleView())
->setHref(
$this->getApplicationURI('update/'.$conpherence->getID()).'/')
->setIcon('fa-pencil')
->setDisabled(!$can_edit)
->addClass('hide-on-device')
->setWorkflow(true));
$header->addActionItem(
id(new PHUIIconCircleView())
->setHref(
$this->getApplicationURI('update/'.$conpherence->getID()).'/'.
'?action='.ConpherenceUpdateActions::NOTIFICATIONS)
->setIcon('fa-gear')
->addClass('hide-on-device')
->setWorkflow(true));
$widget_key = PhabricatorConpherenceWidgetVisibleSetting::SETTINGKEY;
$widget_view = (bool)$viewer->getUserSetting($widget_key, false);
$divider = id(new PHUIListItemView())
->setType(PHUIListItemView::TYPE_DIVIDER)
->addClass('conpherence-header-desktop-item');
$crumbs->addAction($divider);
Javelin::initBehavior(
'toggle-widget',
array(
@ -96,24 +93,15 @@ abstract class ConpherenceController extends PhabricatorController {
'settingsURI' => '/settings/adjust/?key='.$widget_key,
));
$crumbs->addAction(
id(new PHUIListItemView())
->addSigil('conpherence-widget-toggle')
->setIcon('fa-columns')
->addClass('conpherence-header-desktop-item'));
$header->addActionItem(
id(new PHUIIconCircleView())
->addSigil('conpherence-widget-toggle')
->setIcon('fa-group')
->setHref('#')
->addClass('conpherence-participant-toggle'));
}
return hsprintf(
'%s',
array(
phutil_tag(
'div',
array(
'class' => 'header-loading-mask',
),
''),
$crumbs,
));
return $header;
}
}

View file

@ -26,6 +26,9 @@ final class ConpherenceNewRoomController extends ConpherenceController {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransaction::TYPE_TITLE)
->setNewValue($request->getStr('title'));
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransaction::TYPE_TOPIC)
->setNewValue($request->getStr('topic'));
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
->setNewValue($request->getStr('viewPolicy'));
@ -93,6 +96,11 @@ final class ConpherenceNewRoomController extends ConpherenceController {
->setLabel(pht('Name'))
->setName('title')
->setValue($request->getStr('title')))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Topic'))
->setName('topic')
->setValue($request->getStr('topic')))
->appendChild(
id(new AphrontFormTokenizerControl())
->setName('participants')

View file

@ -0,0 +1,73 @@
<?php
final class ConpherenceParticipantController extends ConpherenceController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$conpherence_id = $request->getURIData('id');
if (!$conpherence_id) {
return new Aphront404Response();
}
$conpherence = id(new ConpherenceThreadQuery())
->setViewer($viewer)
->withIDs(array($conpherence_id))
->needWidgetData(true)
->executeOne();
if (!$conpherence) {
return new Aphront404Response();
}
$this->setConpherence($conpherence);
$content = $this->renderParticipantPaneContent();
return id(new AphrontAjaxResponse())->setContent($content);
}
private function renderParticipantPaneContent() {
$conpherence = $this->getConpherence();
$widgets = array();
$new_icon = id(new PHUIIconView())
->setIcon('fa-plus-square')
->setHref($this->getUpdateURI())
->setMetadata(array('widget' => null))
->addSigil('conpherence-widget-adder');
$content = id(new ConpherenceParticipantView())
->setUser($this->getViewer())
->setConpherence($this->getConpherence())
->setUpdateURI($this->getUpdateURI());
$widgets[] = phutil_tag(
'div',
array(
'class' => 'widgets-header',
),
id(new PHUIHeaderView())
->setHeader(pht('Participants'))
->addActionItem($new_icon));
$widgets[] = javelin_tag(
'div',
array(
'class' => 'widgets-body',
'id' => 'widgets-people',
'sigil' => 'widgets-people',
),
$content);
// without this implosion we get "," between each element in our widgets
// array
return array('widgets' => phutil_implode_html('', $widgets));
}
private function getUpdateURI() {
$conpherence = $this->getConpherence();
return $this->getApplicationURI('update/'.$conpherence->getID().'/');
}
}

View file

@ -18,10 +18,6 @@ final class ConpherenceRoomListController extends ConpherenceController {
return $this->delegateToController($controller);
}
protected function buildApplicationCrumbs() {
return $this->buildConpherenceApplicationCrumbs($is_rooms = true);
}
public function buildApplicationMenu() {
return $this->buildRoomsSideNavView(true)->getMenu();
}

View file

@ -107,7 +107,7 @@ final class ConpherenceUpdateController
break;
case ConpherenceUpdateActions::REMOVE_PERSON:
if (!$request->isContinueRequest()) {
// do nothing; we'll display a confirmation dialogue instead
// do nothing; we'll display a confirmation dialog instead
break;
}
$person_phid = $request->getStr('remove_person');
@ -127,22 +127,16 @@ final class ConpherenceUpdateController
}
$participant->setSettings(array('notifications' => $notifications));
$participant->save();
return id(new AphrontRedirectResponse())
->setURI('/'.$conpherence->getMonogram());
$label = PhabricatorConpherenceNotificationsSetting::getSettingLabel(
$notifications);
$result = pht(
'Updated notification settings to "%s".',
$label);
return id(new AphrontAjaxResponse())
->setContent($result);
break;
case ConpherenceUpdateActions::METADATA:
$top = $request->getInt('image_y');
$left = $request->getInt('image_x');
$file_id = $request->getInt('file_id');
$title = $request->getStr('title');
$topic = $request->getStr('topic');
if ($file_id) {
$orig_file = id(new PhabricatorFileQuery())
->setViewer($user)
@ -190,9 +184,13 @@ final class ConpherenceUpdateController
->setNewValue($image_phid);
}
$title = $request->getStr('title');
$topic = $request->getStr('topic');
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransaction::TYPE_TITLE)
->setNewValue($title);
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransaction::TYPE_TOPIC)
->setNewValue($topic);
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
->setNewValue($request->getStr('viewPolicy'));
@ -269,29 +267,97 @@ final class ConpherenceUpdateController
}
switch ($action) {
case ConpherenceUpdateActions::NOTIFICATIONS:
$dialog = $this->renderPreferencesDialog($conpherence);
break;
case ConpherenceUpdateActions::ADD_PERSON:
$dialogue = $this->renderAddPersonDialogue($conpherence);
$dialog = $this->renderAddPersonDialog($conpherence);
break;
case ConpherenceUpdateActions::REMOVE_PERSON:
$dialogue = $this->renderRemovePersonDialogue($conpherence);
$dialog = $this->renderRemovePersonDialog($conpherence);
break;
case ConpherenceUpdateActions::METADATA:
default:
$dialogue = $this->renderMetadataDialogue($conpherence, $error_view);
$dialog = $this->renderMetadataDialog($conpherence, $error_view);
break;
}
return id(new AphrontDialogResponse())
->setDialog($dialogue
return
$dialog
->setUser($user)
->setWidth(AphrontDialogView::WIDTH_FORM)
->setSubmitURI($this->getApplicationURI('update/'.$conpherence_id.'/'))
->addSubmitButton()
->addCancelButton($this->getApplicationURI($conpherence->getID().'/')));
->addCancelButton($this->getApplicationURI($conpherence->getID().'/'));
}
private function renderAddPersonDialogue(
private function renderPreferencesDialog(
ConpherenceThread $conpherence) {
$request = $this->getRequest();
$user = $request->getUser();
$participant = $conpherence->getParticipantIfExists($user->getPHID());
if (!$participant) {
$can_join = PhabricatorPolicyFilter::hasCapability(
$user,
$conpherence,
PhabricatorPolicyCapability::CAN_JOIN);
if ($can_join) {
$text = pht(
'Notification settings are available after joining the room.');
} else if ($user->isLoggedIn()) {
$text = pht(
'Notification settings not applicable to rooms you can not join.');
} else {
$text = pht(
'Notification settings are available after logging in and joining '.
'the room.');
}
return id(new AphrontDialogView())
->setTitle(pht('Room Preferences'))
->appendParagraph($text);
}
$notification_key = PhabricatorConpherenceNotificationsSetting::SETTINGKEY;
$notification_default = $user->getUserSetting($notification_key);
$settings = $participant->getSettings();
$notifications = idx(
$settings,
'notifications',
$notification_default);
$form = id(new AphrontFormView())
->setUser($user)
->setFullWidth(true)
->appendControl(
id(new AphrontFormRadioButtonControl())
->addButton(
PhabricatorConpherenceNotificationsSetting::VALUE_CONPHERENCE_EMAIL,
PhabricatorConpherenceNotificationsSetting::getSettingLabel(
PhabricatorConpherenceNotificationsSetting::VALUE_CONPHERENCE_EMAIL),
'')
->addButton(
PhabricatorConpherenceNotificationsSetting::VALUE_CONPHERENCE_NOTIFY,
PhabricatorConpherenceNotificationsSetting::getSettingLabel(
PhabricatorConpherenceNotificationsSetting::VALUE_CONPHERENCE_NOTIFY),
'')
->setName('notifications')
->setValue($notifications));
return id(new AphrontDialogView())
->setTitle(pht('Room Preferences'))
->addHiddenInput('action', 'notifications')
->addHiddenInput(
'latest_transaction_id',
$request->getInt('latest_transaction_id'))
->appendForm($form);
}
private function renderAddPersonDialog(
ConpherenceThread $conpherence) {
$request = $this->getRequest();
@ -322,7 +388,7 @@ final class ConpherenceUpdateController
return $view;
}
private function renderRemovePersonDialogue(
private function renderRemovePersonDialog(
ConpherenceThread $conpherence) {
$request = $this->getRequest();
@ -405,7 +471,7 @@ final class ConpherenceUpdateController
return $dialog;
}
private function renderMetadataDialogue(
private function renderMetadataDialog(
ConpherenceThread $conpherence,
$error_view) {
@ -419,7 +485,12 @@ final class ConpherenceUpdateController
id(new AphrontFormTextControl())
->setLabel(pht('Title'))
->setName('title')
->setValue($conpherence->getTitle()));
->setValue($conpherence->getTitle()))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Topic'))
->setName('topic')
->setValue($conpherence->getTopic()));
$nopic = $this->getRequest()->getExists('nopic');
$image = $conpherence->getImage(ConpherenceImageData::SIZE_ORIG);
@ -548,11 +619,10 @@ final class ConpherenceUpdateController
$rendered_transactions = idx($data, 'transactions');
$new_latest_transaction_id = idx($data, 'latest_transaction_id');
$widget_uri = $this->getApplicationURI('update/'.$conpherence->getID().'/');
$update_uri = $this->getApplicationURI('update/'.$conpherence->getID().'/');
$nav_item = null;
$header = null;
$people_widget = null;
$file_widget = null;
if (!$minimal_display) {
switch ($action) {
case ConpherenceUpdateActions::METADATA:
@ -571,10 +641,10 @@ final class ConpherenceUpdateController
$nav_item = hsprintf('%s', $nav_item);
break;
case ConpherenceUpdateActions::ADD_PERSON:
$people_widget = id(new ConpherencePeopleWidgetView())
$people_widget = id(new ConpherenceParticipantView())
->setUser($user)
->setConpherence($conpherence)
->setUpdateURI($widget_uri);
->setUpdateURI($update_uri);
$people_widget = hsprintf('%s', $people_widget->render());
break;
case ConpherenceUpdateActions::REMOVE_PERSON:
@ -595,7 +665,6 @@ final class ConpherenceUpdateController
'nav_item' => $nav_item,
'conpherence_phid' => $conpherence->getPHID(),
'header' => $header,
'file_widget' => $file_widget,
'people_widget' => $people_widget,
'aphlictDropdownData' => array(
$dropdown_query->getNotificationData(),

View file

@ -1,181 +0,0 @@
<?php
final class ConpherenceWidgetController extends ConpherenceController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$request = $this->getRequest();
$user = $request->getUser();
$conpherence_id = $request->getURIData('id');
if (!$conpherence_id) {
return new Aphront404Response();
}
$conpherence = id(new ConpherenceThreadQuery())
->setViewer($user)
->withIDs(array($conpherence_id))
->needWidgetData(true)
->executeOne();
if (!$conpherence) {
return new Aphront404Response();
}
$this->setConpherence($conpherence);
switch ($request->getStr('widget')) {
case 'widgets-people':
$content = $this->renderPeopleWidgetPaneContent();
break;
case 'widgets-settings':
$content = $this->renderSettingsWidgetPaneContent();
break;
default:
$widgets = $this->renderWidgetPaneContent();
$content = $widgets;
break;
}
return id(new AphrontAjaxResponse())->setContent($content);
}
private function renderWidgetPaneContent() {
$conpherence = $this->getConpherence();
$widgets = array();
$new_icon = id(new PHUIIconView())
->setIcon('fa-plus')
->setHref($this->getWidgetURI())
->setMetadata(array('widget' => null))
->addSigil('conpherence-widget-adder');
$header = javelin_tag(
'a',
array(
'href' => '#',
'sigil' => 'widgets-selector',
),
pht('Participants'));
$widgets[] = phutil_tag(
'div',
array(
'class' => 'widgets-header',
),
id(new PHUIHeaderView())
->setHeader($header)
->addActionItem($new_icon));
$user = $this->getRequest()->getUser();
// now the widget bodies
$widgets[] = javelin_tag(
'div',
array(
'class' => 'widgets-body',
'id' => 'widgets-people',
'sigil' => 'widgets-people',
),
$this->renderPeopleWidgetPaneContent());
$widgets[] = phutil_tag(
'div',
array(
'class' => 'widgets-body',
'id' => 'widgets-settings',
'style' => 'display: none',
),
$this->renderSettingsWidgetPaneContent());
// without this implosion we get "," between each element in our widgets
// array
return array('widgets' => phutil_implode_html('', $widgets));
}
private function renderPeopleWidgetPaneContent() {
return id(new ConpherencePeopleWidgetView())
->setUser($this->getViewer())
->setConpherence($this->getConpherence())
->setUpdateURI($this->getWidgetURI());
}
private function renderSettingsWidgetPaneContent() {
$viewer = $this->getViewer();
$conpherence = $this->getConpherence();
$participant = $conpherence->getParticipantIfExists($viewer->getPHID());
if (!$participant) {
$can_join = PhabricatorPolicyFilter::hasCapability(
$viewer,
$conpherence,
PhabricatorPolicyCapability::CAN_JOIN);
if ($can_join) {
$text = pht(
'Notification settings are available after joining the room.');
} else if ($viewer->isLoggedIn()) {
$text = pht(
'Notification settings not applicable to rooms you can not join.');
} else {
$text = pht(
'Notification settings are available after logging in and joining '.
'the room.');
}
return phutil_tag(
'div',
array(
'class' => 'no-settings',
),
$text);
}
$notification_key = PhabricatorConpherenceNotificationsSetting::SETTINGKEY;
$notification_default = $viewer->getUserSetting($notification_key);
$settings = $participant->getSettings();
$notifications = idx(
$settings,
'notifications',
$notification_default);
$options = id(new AphrontFormRadioButtonControl())
->addButton(
PhabricatorConpherenceNotificationsSetting::VALUE_CONPHERENCE_EMAIL,
PhabricatorConpherenceNotificationsSetting::getSettingLabel(
PhabricatorConpherenceNotificationsSetting::VALUE_CONPHERENCE_EMAIL),
'')
->addButton(
PhabricatorConpherenceNotificationsSetting::VALUE_CONPHERENCE_NOTIFY,
PhabricatorConpherenceNotificationsSetting::getSettingLabel(
PhabricatorConpherenceNotificationsSetting::VALUE_CONPHERENCE_NOTIFY),
'')
->setName('notifications')
->setValue($notifications);
$layout = array(
$options,
phutil_tag(
'input',
array(
'type' => 'hidden',
'name' => 'action',
'value' => 'notifications',
)),
phutil_tag(
'button',
array(
'type' => 'submit',
'class' => 'notifications-update',
),
pht('Save')),
);
return phabricator_form(
$viewer,
array(
'method' => 'POST',
'action' => $this->getWidgetURI(),
'sigil' => 'notifications-update',
),
$layout);
}
private function getWidgetURI() {
$conpherence = $this->getConpherence();
return $this->getApplicationURI('update/'.$conpherence->getID().'/');
}
}

View file

@ -18,7 +18,8 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
array $participant_phids,
$title,
$message,
PhabricatorContentSource $source) {
PhabricatorContentSource $source,
$topic) {
$conpherence = ConpherenceThread::initializeNewRoom($creator);
$files = array();
@ -59,6 +60,11 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
->setTransactionType(ConpherenceTransaction::TYPE_TITLE)
->setNewValue($title);
}
if (strlen($topic)) {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransaction::TYPE_TOPIC)
->setNewValue($topic);
}
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
@ -118,6 +124,7 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = ConpherenceTransaction::TYPE_TITLE;
$types[] = ConpherenceTransaction::TYPE_TOPIC;
$types[] = ConpherenceTransaction::TYPE_PARTICIPANTS;
$types[] = ConpherenceTransaction::TYPE_FILES;
$types[] = ConpherenceTransaction::TYPE_PICTURE;
@ -136,6 +143,8 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
switch ($xaction->getTransactionType()) {
case ConpherenceTransaction::TYPE_TITLE:
return $object->getTitle();
case ConpherenceTransaction::TYPE_TOPIC:
return $object->getTopic();
case ConpherenceTransaction::TYPE_PICTURE:
return $object->getImagePHID(ConpherenceImageData::SIZE_ORIG);
case ConpherenceTransaction::TYPE_PICTURE_CROP:
@ -156,6 +165,7 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
switch ($xaction->getTransactionType()) {
case ConpherenceTransaction::TYPE_TITLE:
case ConpherenceTransaction::TYPE_TOPIC:
case ConpherenceTransaction::TYPE_PICTURE_CROP:
return $xaction->getNewValue();
case ConpherenceTransaction::TYPE_PICTURE:
@ -250,6 +260,9 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
case ConpherenceTransaction::TYPE_TITLE:
$object->setTitle($xaction->getNewValue());
break;
case ConpherenceTransaction::TYPE_TOPIC:
$object->setTopic($xaction->getNewValue());
break;
case ConpherenceTransaction::TYPE_PICTURE:
$object->setImagePHID(
$xaction->getNewValue(),
@ -484,6 +497,7 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
PhabricatorPolicyCapability::CAN_VIEW);
break;
case ConpherenceTransaction::TYPE_TITLE:
case ConpherenceTransaction::TYPE_TOPIC:
PhabricatorPolicyFilter::requireCapability(
$this->requireActor(),
$object,

View file

@ -8,6 +8,7 @@ final class ConpherenceThread extends ConpherenceDAO
PhabricatorDestructibleInterface {
protected $title;
protected $topic;
protected $imagePHIDs = array();
protected $messageCount;
protected $recentParticipantPHIDs = array();
@ -29,6 +30,7 @@ final class ConpherenceThread extends ConpherenceDAO
return id(new ConpherenceThread())
->setMessageCount(0)
->setTitle('')
->setTopic('')
->attachParticipants(array())
->attachFilePHIDs(array())
->attachImages(array())
@ -46,6 +48,7 @@ final class ConpherenceThread extends ConpherenceDAO
),
self::CONFIG_COLUMN_SCHEMA => array(
'title' => 'text255?',
'topic' => 'text255',
'messageCount' => 'uint64',
'mailKey' => 'text20',
'joinPolicy' => 'policy',
@ -342,9 +345,11 @@ final class ConpherenceThread extends ConpherenceDAO
$unread_count = $this->getMessageCount() - $user_seen_count;
$title = $this->getDisplayTitle($viewer);
$topic = $this->getTopic();
return array(
'title' => $title,
'topic' => $topic,
'subtitle' => $subtitle,
'unread_count' => $unread_count,
'epoch' => $this->getDateModified(),

View file

@ -4,6 +4,7 @@ final class ConpherenceTransaction extends PhabricatorApplicationTransaction {
const TYPE_FILES = 'files';
const TYPE_TITLE = 'title';
const TYPE_TOPIC = 'topic';
const TYPE_PARTICIPANTS = 'participants';
const TYPE_DATE_MARKER = 'date-marker';
const TYPE_PICTURE = 'picture';
@ -39,6 +40,7 @@ final class ConpherenceTransaction extends PhabricatorApplicationTransaction {
case self::TYPE_PARTICIPANTS:
return ($old === null);
case self::TYPE_TITLE:
case self::TYPE_TOPIC:
case self::TYPE_PICTURE:
case self::TYPE_DATE_MARKER:
return false;
@ -59,6 +61,7 @@ final class ConpherenceTransaction extends PhabricatorApplicationTransaction {
switch ($this->getTransactionType()) {
case self::TYPE_TITLE:
case self::TYPE_TOPIC:
case PhabricatorTransactions::TYPE_VIEW_POLICY:
case PhabricatorTransactions::TYPE_EDIT_POLICY:
case PhabricatorTransactions::TYPE_JOIN_POLICY:
@ -147,6 +150,20 @@ final class ConpherenceTransaction extends PhabricatorApplicationTransaction {
}
return $title;
break;
case self::TYPE_TOPIC:
if ($new) {
$title = pht(
'%s set the topic of this room to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else if ($old) {
$title = pht(
'%s deleted the room topic "%s"',
$this->renderHandleLink($author_phid),
$old);
}
return $title;
break;
case self::TYPE_PICTURE:
return pht(
'%s updated the room image.',

View file

@ -105,9 +105,7 @@ final class ConpherenceLayoutView extends AphrontView {
$classes[] = 'hide-widgets';
}
$this->initBehavior(
'conpherence-widget-pane',
ConpherenceWidgetConfigConstants::getWidgetPaneBehaviorConfig());
$this->initBehavior('conpherence-participants-pane');
return javelin_tag(
'div',

View file

@ -1,6 +1,25 @@
<?php
final class ConpherencePeopleWidgetView extends ConpherenceWidgetView {
final class ConpherenceParticipantView extends AphrontView {
private $conpherence;
private $updateURI;
public function setUpdateURI($update_uri) {
$this->updateURI = $update_uri;
return $this;
}
public function getUpdateURI() {
return $this->updateURI;
}
public function setConpherence(ConpherenceThread $conpherence) {
$this->conpherence = $conpherence;
return $this;
}
public function getConpherence() {
return $this->conpherence;
}
public function render() {
$conpherence = $this->getConpherence();
@ -14,6 +33,7 @@ final class ConpherencePeopleWidgetView extends ConpherenceWidgetView {
natcasesort($handle_list);
$handles = mpull($handles, null, 'getName');
$handles = array_select_keys($handles, $handle_list);
$head_handles = mpull($head_handles, null, 'getName');
$handles = $head_handles + $handles;
@ -28,7 +48,8 @@ final class ConpherencePeopleWidgetView extends ConpherenceWidgetView {
if (($user_phid == $viewer->getPHID()) || $can_edit) {
$icon = id(new PHUIIconView())
->setIcon('fa-times lightbluetext');
->setIcon('fa-times')
->addClass('lightbluetext');
$remove_html = javelin_tag(
'a',
array(

View file

@ -231,6 +231,7 @@ final class ConpherenceTransactionView extends AphrontView {
$content = $transaction->getTitle();
break;
case ConpherenceTransaction::TYPE_TITLE:
case ConpherenceTransaction::TYPE_TOPIC:
case ConpherenceTransaction::TYPE_PICTURE:
case ConpherenceTransaction::TYPE_PICTURE_CROP:
case ConpherenceTransaction::TYPE_PARTICIPANTS:

View file

@ -1,24 +0,0 @@
<?php
abstract class ConpherenceWidgetView extends AphrontView {
private $conpherence;
private $updateURI;
public function setUpdateURI($update_uri) {
$this->updateURI = $update_uri;
return $this;
}
public function getUpdateURI() {
return $this->updateURI;
}
public function setConpherence(ConpherenceThread $conpherence) {
$this->conpherence = $conpherence;
return $this;
}
public function getConpherence() {
return $this->conpherence;
}
}

View file

@ -46,6 +46,10 @@
border: none;
}
.device-phone .aphront-dialog-body {
padding: 8px;
}
.aphront-dialog-tail {
border: none;
position: relative;

View file

@ -0,0 +1,68 @@
/**
* @provides conpherence-header-pane-css
*/
.conpherence-header-pane {
}
.conpherence-header-pane .phui-header-shell {
padding: 8px 16px 10px;
min-height: 38px;
}
.conpherence-header-pane .phui-header-header {
font-size: 16px;
font-family: 'Aleo', {$fontfamily};
color: #000;
}
.conpherence-header-pane .phui-header-subheader {
color: {$lightgreyborder};
padding: 0;
font-size: 12px;
margin: 0;
}
.conpherence-header-pane .phui-header-shell.conpherence-no-topic {
padding: 15px 16px 5px;
}
.conpherence-header-pane .phui-header-action-list .phui-header-action-item
.phui-icon-view {
height: 18px;
width: 24px;
font-size: 14px;
line-height: 23px;
display: block;
}
.device .hide-on-device {
display: none;
}
.device-phone .conpherence-header-pane .phui-header-col3 {
vertical-align: middle;
}
.conpherence-header-pane .conpherence-participant-toggle.phui-icon-circle {
text-decoration: none;
border-color: {$sky};
cursor: pointer;
}
.conpherence-header-pane .conpherence-participant-toggle.phui-icon-circle
.phui-icon-view {
color: {$sky};
}
.hide-widgets .conpherence-header-pane
.conpherence-participant-toggle.phui-icon-circle {
text-decoration: none;
border-color: {$lightblueborder};
cursor: pointer;
}
.hide-widgets .conpherence-header-pane
.conpherence-participant-toggle.phui-icon-circle .phui-icon-view {
color: {$lightblueborder};
}

View file

@ -9,7 +9,7 @@
position: fixed;
left: 240px;
right: 240px;
top: 76px;
top: 102px;
bottom: 0px;
min-width: 300px;
width: auto;
@ -32,11 +32,6 @@
margin: 16px 0px 16px 0px;
}
.conpherence-layout .phui-crumbs-view {
padding: 0 0 0 8px;
background: #f7f7f7;
}
.conpherence-show-more-messages {
display: block;
background: #e0e3ec;
@ -54,7 +49,7 @@
position: fixed;
left: 240px;
right: 240px;
top: 78px;
top: 103px;
bottom: 148px;
overflow-x: hidden;
overflow-y: auto;
@ -103,13 +98,17 @@
.conpherence-message-pane .phui-form-view {
border-width: 0;
height: 140px;
padding: 0 8px 8px;
padding: 0 20px 12px;
position: fixed;
bottom: 0;
left: 240px;
right: 241px;
}
.device .conpherence-message-pane .phui-form-view {
padding: 8px 8px;
}
.conpherence-message-pane .phui-form-view.login-to-participate {
height: 26px;
}
@ -123,6 +122,11 @@
margin-top: 6px;
}
.device .conpherence-message-pane .aphront-form-control-submit button,
.device .conpherence-message-pane .aphront-form-control-submit a.button {
margin-top: 13px;
}
/**
* When entering "Fullscreen Mode" in the remarkup control, we need to drop
* all of the "position: fixed" on parent elements or Chrome doesn't put the
@ -162,7 +166,7 @@
.conpherence-message-pane .conpherence-transaction-view {
padding: 2px 0px;
margin: 4px 12px;
margin: 4px 20px;
background-size: 100%;
min-height: auto;
}
@ -182,7 +186,9 @@
}
.device-phone .conpherence-message-pane .conpherence-transaction-image {
display: none;
height: 25px;
width: 25px;
background-size: 25px;
}
.conpherence-message-pane .conpherence-comment.anchor-target,
@ -206,12 +212,12 @@
}
.device-phone .conpherence-message-pane .conpherence-transaction-detail {
margin: 0;
margin-left: 32px;
}
.conpherence-message-pane .conpherence-transaction-view.date-marker {
padding: 0;
margin: 20px 12px 4px;
margin: 20px 20px 4px;
min-height: auto;
}
@ -234,7 +240,6 @@
.device .conpherence-message-pane .conpherence-transaction-view.date-marker
.date {
color: {$lightbluetext};
left: 4px;
}
@ -351,10 +356,3 @@
max-height: 200px;
}
.device .conpherence-header-desktop-item {
display: none;
}
.device .conpherence-header-pane .phui-crumb-action-divider {
display: none;
}

View file

@ -17,14 +17,14 @@
}
.conpherence-transaction-view.date-marker {
border-top: 1px solid {$thinblueborder};
border-top: 1px solid {$sh-violetborder};
}
.conpherence-transaction-view.date-marker .date {
position: relative;
top: -11px;
background-color: #fff;
color: #000;
color: {$sh-violettext};
font-weight: bold;
}

View file

@ -2,10 +2,6 @@
* @provides conpherence-update-css
*/
.phabricator-standard-page-body .aphront-dialog-view {
margin: 20px auto 0px auto;
}
.aphront-dialog-view .conpherence-dialogue-drag-photo {
border: 1px dashed #bfbfbf;
padding: 10px 0px 10px 10px;

View file

@ -2,11 +2,10 @@
* @provides conpherence-widget-pane-css
*/
.conpherence-widget-pane,
.loading .widgets-loading-mask {
.conpherence-widget-pane {
position: fixed;
right: 0px;
top: 79px;
top: 103px;
bottom: 0;
width: 240px;
border-width: 0 0 0 1px;
@ -15,20 +14,9 @@
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.device .conpherence-widget-pane,
.device .loading .widgets-loading-mask {
top: 44px;
width: 100%;
}
.conpherence-widget-pane .widgets-loading-mask {
opacity: .6;
background: #fff;
display: none;
}
.loading .widgets-loading-mask {
display: block;
.device .conpherence-widget-pane {
background-color: {$page.background};
}
.conpherence-widget-pane .aphront-form-input {
@ -48,84 +36,20 @@
font-size: {$biggerfontsize};
}
.device .conpherence-widget-pane .widgets-header {
display: none;
}
.conpherence-widget-pane .widgets-header .caret {
float: none;
height: 0px;
width: 0px;
margin: 10px 0 0 4px;
border-top-color: #000;
}
.conpherence-widget-pane .widgets-header .phui-icon-view.disabled {
color: {$lightgreytext};
}
.device-desktop .conpherence-layout .device-widgets-selector {
display: none;
}
.conpherence-widget-pane .widgets-body {
position: fixed;
overflow-y: auto;
bottom: 0;
top: 76px;
width: 100%;
}
#widgets-settings {
padding: 3px 6px;
}
.device-desktop .conpherence-widget-pane .widgets-body {
top: 115px;
top: 144px;
width: 240px;
}
.conpherence-widget-pane .widget-icon {
display: block;
height: 14px;
width: 14px;
}
.conpherence-widget-pane .phabricator-remarkup-embed-layout-link {
padding-bottom: 1px;
}
/* people widget */
.conpherence-widget-pane .people-widget-header .add-people-widget {
padding: 10px 0 5px 0;
overflow: hidden;
}
.conpherence-widget-pane .people-widget-header .add-people-widget
.aphront-form-control-tokenizer {
float: left;
width: 150px;
padding: 0px 0px 0px 10px
}
.device .conpherence-widget-pane .people-widget-header .add-people-widget
.aphront-form-control-tokenizer {
width: 70%;
}
.conpherence-widget-pane .people-widget-header .add-people-widget
.people-add-button {
float: right;
margin: 2px 8px 0px 0px;
padding: 3px 16px 4px 16px;
}
#widgets-people {
margin-top: 4px;
}
.conpherence-widget-pane .person-entry {
padding: 4px 8px;
padding: 4px 4px 4px 8px;
}
.conpherence-widget-pane .person-entry:hover {
@ -173,35 +97,17 @@
color: #000;
}
/* settings widget */
.conpherence-widget-pane .title-update,
.conpherence-widget-pane .notifications-update {
margin: 3px 0px 0px 4px;
}
.conpherence-widget-pane .no-settings {
width: 200px;
padding: 20px;
text-align: center;
color: {$greytext};
}
.device .conpherence-widget-pane .no-settings {
width: 60px;
margin: 0 auto 0 auto;
}
/****** Hide Widgets **********************************************************/
.device-desktop .hide-widgets .conpherence-widget-pane {
.hide-widgets .conpherence-widget-pane {
display: none;
}
.device-desktop .hide-widgets .conpherence-message-pane,
.device-desktop .hide-widgets .loading .messages-loading-mask,
.device-desktop .hide-widgets .loading .messages-loading-icon,
.device-desktop .hide-widgets .conpherence-no-threads,
.device-desktop .hide-widgets .conpherence-message-pane .conpherence-messages,
.device-desktop .hide-widgets .conpherence-message-pane .phui-form-view {
.hide-widgets .conpherence-message-pane,
.hide-widgets .loading .messages-loading-mask,
.hide-widgets .loading .messages-loading-icon,
.hide-widgets .conpherence-no-threads,
.hide-widgets .conpherence-message-pane .conpherence-messages,
.hide-widgets .conpherence-message-pane .phui-form-view {
right: 0;
}

View file

@ -150,6 +150,10 @@ div.jx-typeahead-results {
z-index: 21;
}
.conpherence-widget-pane {
z-index: 25;
}
.phuix-dropdown-menu {
z-index: 32;
}

View file

@ -241,7 +241,7 @@ JX.behavior('conpherence-menu', function(config) {
if (!data.widget) {
data.widget = getDefaultWidget();
}
var widget_uri = config.baseURI + 'widget/' + data.threadID + '/';
var widget_uri = config.baseURI + 'participant/' + data.threadID + '/';
new JX.Workflow(widget_uri, {})
.setHandler(JX.bind(null, onWidgetResponse, data.threadID, data.widget))
.start();

View file

@ -0,0 +1,112 @@
/**
* @requires javelin-behavior
* javelin-dom
* javelin-stratcom
* javelin-workflow
* javelin-util
* phabricator-notification
* conpherence-thread-manager
* @provides javelin-behavior-conpherence-participants-pane
*/
JX.behavior('conpherence-participants-pane', function() {
/**
* Generified adding new stuff to widgets technology!
*/
JX.Stratcom.listen(
['click'],
'conpherence-widget-adder',
function (e) {
e.kill();
var threadManager = JX.ConpherenceThreadManager.getInstance();
var href = threadManager._getUpdateURI();
var latest_transaction_id = threadManager.getLatestTransactionID();
var data = {
latest_transaction_id : latest_transaction_id,
action : 'add_person'
};
var workflow = new JX.Workflow(href, data)
.setHandler(function (r) {
var threadManager = JX.ConpherenceThreadManager.getInstance();
threadManager.setLatestTransactionID(r.latest_transaction_id);
var root = JX.DOM.find(document, 'div', 'conpherence-layout');
var messages = null;
try {
messages = JX.DOM.find(root, 'div', 'conpherence-messages');
} catch (ex) {
}
if (messages) {
JX.DOM.appendContent(messages, JX.$H(r.transactions));
JX.Stratcom.invoke('conpherence-redraw-thread', null, {});
}
try {
var people_root = JX.DOM.find(root, 'div', 'widgets-people');
// update the people widget
JX.DOM.setContent(
people_root,
JX.$H(r.people_widget));
} catch (ex) {
}
});
threadManager.syncWorkflow(workflow, 'submit');
}
);
JX.Stratcom.listen(
['touchstart', 'mousedown'],
'remove-person',
function (e) {
var threadManager = JX.ConpherenceThreadManager.getInstance();
var href = threadManager._getUpdateURI();
var data = e.getNodeData('remove-person');
// While the user is removing themselves, disable the notification
// update behavior. If we don't do this, the user can get an error
// when they remove themselves about permissions as the notification
// code tries to load what jist happened.
var loadedPhid = threadManager.getLoadedThreadPHID();
threadManager.setLoadedThreadPHID(null);
new JX.Workflow(href, data)
.setCloseHandler(function() {
threadManager.setLoadedThreadPHID(loadedPhid);
})
// we re-direct to conpherence home so the thread manager will
// fix itself there
.setHandler(function(r) {
JX.$U(r.href).go();
})
.start();
}
);
/* settings widget */
var onsubmitSettings = function (e) {
e.kill();
var form = e.getNode('tag:form');
var button = JX.DOM.find(form, 'button');
JX.Workflow.newFromForm(form)
.setHandler(JX.bind(this, function (r) {
new JX.Notification()
.setDuration(6000)
.setContent(r)
.show();
button.disabled = '';
JX.DOM.alterClass(button, 'disabled', false);
}))
.start();
};
JX.Stratcom.listen(
['submit', 'didSyntheticSubmit'],
'notifications-update',
onsubmitSettings
);
});

View file

@ -14,6 +14,7 @@ JX.behavior('toggle-widget', function(config) {
var node = JX.$('conpherence-main-layout');
config.show = !config.show;
JX.DOM.alterClass(node, 'hide-widgets', !config.show);
JX.Stratcom.invoke('resize');
new JX.Request(config.settingsURI)
.setData({value: (config.show ? 1 : 0)})

View file

@ -1,382 +0,0 @@
/**
* @requires javelin-behavior
* javelin-dom
* javelin-stratcom
* javelin-workflow
* javelin-util
* phabricator-notification
* javelin-behavior-device
* phuix-dropdown-menu
* phuix-action-list-view
* phuix-action-view
* conpherence-thread-manager
* @provides javelin-behavior-conpherence-widget-pane
*/
JX.behavior('conpherence-widget-pane', function(config) {
/**
* There can be race conditions around loading the messages or the widgets
* first. Keep track of what widgets we've loaded with this variable.
*/
var _loadedWidgetsID = null;
/**
* At any given time there can be only one selected widget. Keep track of
* which one it is by the user-facing name for ease of use with
* PhabricatorDropdownMenuItems.
*/
var _selectedWidgetName = null;
/**
* This is potentially built each time the user switches conpherence threads
* or when the result JX.Device.getDevice() changes from desktop to some
* other value.
*/
var buildDeviceWidgetSelector = function (data) {
var device_header = _getDeviceWidgetHeader();
if (!device_header) {
return;
}
JX.DOM.show(device_header);
var device_menu = new JX.PHUIXDropdownMenu(device_header);
data.deviceMenu = true;
_buildWidgetSelector(device_menu, data);
};
/**
* This is potentially built each time the user switches conpherence threads
* or when the result JX.Device.getDevice() changes from mobile or tablet to
* desktop.
*/
var buildDesktopWidgetSelector = function (data) {
var root = JX.DOM.find(document, 'div', 'conpherence-layout');
var widget_pane = JX.DOM.find(root, 'div', 'conpherence-widget-pane');
var widget_header = JX.DOM.find(widget_pane, 'a', 'widgets-selector');
var menu = new JX.PHUIXDropdownMenu(widget_header);
menu
.setAlign('left')
.setOffsetY(4);
data.deviceMenu = false;
_buildWidgetSelector(menu, data);
};
/**
* Workhorse that actually builds the widget selector. Note some fancy bits
* where we listen for the "open" event and enable / disable widgets as
* appropos.
*/
var _buildWidgetSelector = function (menu, data) {
_loadedWidgetsID = data.threadID;
var list = new JX.PHUIXActionListView();
var map = {};
var widgets = config.widgetRegistry;
for (var widget in widgets) {
var widget_data = widgets[widget];
if (widget_data.deviceOnly && data.deviceMenu === false) {
continue;
}
var handler;
var href;
handler = JX.bind(null, function(widget, e) {
toggleWidget({widget: widget});
e.prevent();
menu.close();
}, widget);
var item = new JX.PHUIXActionView()
.setIcon(widget_data.icon || 'none')
.setName(widget_data.name)
.setHref(href)
.setHandler(handler);
map[widget_data.name] = item;
list.addItem(item);
}
menu
.setWidth(200)
.setContent(list.getNode());
menu.listen('open', function() {
for (var k in map) {
map[k].setDisabled((k == _selectedWidgetName));
}
});
};
/**
* Since this is not always on the page, avoid having a repeat
* try / catch block and consolidate into this helper function.
*/
var _getDeviceWidgetHeader = function () {
var root = JX.DOM.find(document, 'div', 'conpherence-layout');
var device_header = null;
try {
device_header = JX.DOM.find(
root,
'a',
'device-widgets-selector');
} catch (ex) {
// is okay - no deviceWidgetHeader yet... but bail time
}
return device_header;
};
/**
* Responder to the 'conpherence-did-redraw-thread' event, this bad boy
* hides or shows the device widget selector as appropros.
*/
var _didRedrawThread = function (data) {
if (_loadedWidgetsID === null || _loadedWidgetsID != data.threadID) {
return;
}
var device = JX.Device.getDevice();
var device_selector = _getDeviceWidgetHeader();
if (device == 'desktop') {
JX.DOM.hide(device_selector);
} else {
JX.DOM.show(device_selector);
}
if (data.buildDeviceWidgetSelector) {
buildDeviceWidgetSelector(data);
}
toggleWidget(data);
};
JX.Stratcom.listen(
'conpherence-did-redraw-thread',
null,
function (e) {
_didRedrawThread(e.getData());
}
);
/**
* Toggling a widget involves showing / hiding the appropriate widget
* bodies as well as updating the selectors to have the label on the
* newly selected widget.
*/
var toggleWidget = function (data) {
var widgets = config.widgetRegistry;
var widget_data = widgets[data.widget];
var device = JX.Device.getDevice();
var is_desktop = device == 'desktop';
if (widget_data.deviceOnly && is_desktop) {
return;
}
_selectedWidgetName = widget_data.name;
var device_header = _getDeviceWidgetHeader();
if (device_header) {
// this is fragile but adding a sigil to this element is awkward
var device_header_spans = JX.DOM.scry(device_header, 'span');
var device_header_span = device_header_spans[1];
JX.DOM.setContent(
device_header_span,
widget_data.name);
}
// don't update the non-device selector with device only widget stuff
if (!widget_data.deviceOnly) {
var root = JX.DOM.find(document, 'div', 'conpherence-layout');
var widget_pane = JX.DOM.find(root, 'div', 'conpherence-widget-pane');
var widget_header = JX.DOM.find(widget_pane, 'a', 'widgets-selector');
var adder = JX.DOM.find(widget_pane, 'a', 'conpherence-widget-adder');
var threadManager = JX.ConpherenceThreadManager.getInstance();
var disabled = !threadManager.getCanEditLoadedThread();
JX.DOM.setContent(
widget_header,
widget_data.name);
JX.DOM.appendContent(
widget_header,
JX.$N('span', { className : 'caret' }));
if (widget_data.hasCreate) {
JX.DOM.show(adder);
JX.DOM.alterClass(
adder,
'disabled',
disabled);
} else {
JX.DOM.hide(adder);
}
}
for (var widget in config.widgetRegistry) {
widget_data = widgets[widget];
if (widget_data.deviceOnly && is_desktop) {
// some one off code for conpherence messages which are device-only
// as a widget, but shown always on the desktop
if (widget == 'conpherence-message-pane') {
JX.$(widget).style.display = 'block';
}
continue;
}
if (widget == data.widget) {
JX.$(widget).style.display = 'block';
// some one off code for conpherence messages - fancier refresh tech
if (widget == 'conpherence-message-pane') {
JX.Stratcom.invoke('conpherence-redraw-thread', null, {});
JX.Stratcom.invoke('conpherence-update-page-data', null, {});
}
} else {
JX.$(widget).style.display = 'none';
}
}
};
JX.Stratcom.listen(
'conpherence-update-widgets',
null,
function (e) {
var data = e.getData();
if (data.buildSelectors) {
buildDesktopWidgetSelector(data);
buildDeviceWidgetSelector(data);
}
if (data.toggleWidget) {
toggleWidget(data);
}
});
/**
* Generified adding new stuff to widgets technology!
*/
JX.Stratcom.listen(
['click'],
'conpherence-widget-adder',
function (e) {
e.kill();
var widgets = config.widgetRegistry;
// the widget key might be in node data, but otherwise use the
// selected widget
var event_data = e.getNodeData('conpherence-widget-adder');
var widget_key = _selectedWidgetName;
if (event_data.widget) {
widget_key = widgets[event_data.widget].name;
}
var widget_to_update = null;
var create_data = null;
for (var widget in widgets) {
if (widgets[widget].name == widget_key) {
create_data = widgets[widget].createData;
widget_to_update = widget;
break;
}
}
// this should be impossible, but hey
if (!widget_to_update) {
return;
}
var href = config.widgetBaseUpdateURI + _loadedWidgetsID + '/';
if (create_data.customHref) {
href = create_data.customHref;
}
var threadManager = JX.ConpherenceThreadManager.getInstance();
var latest_transaction_id = threadManager.getLatestTransactionID();
var data = {
latest_transaction_id : latest_transaction_id,
action : create_data.action
};
var workflow = new JX.Workflow(href, data)
.setHandler(function (r) {
var threadManager = JX.ConpherenceThreadManager.getInstance();
threadManager.setLatestTransactionID(r.latest_transaction_id);
var root = JX.DOM.find(document, 'div', 'conpherence-layout');
if (create_data.refreshFromResponse) {
var messages = null;
try {
messages = JX.DOM.find(root, 'div', 'conpherence-messages');
} catch (ex) {
}
if (messages) {
JX.DOM.appendContent(messages, JX.$H(r.transactions));
JX.Stratcom.invoke('conpherence-redraw-thread', null, {});
}
if (r.people_widget) {
try {
var people_root = JX.DOM.find(root, 'div', 'widgets-people');
// update the people widget
JX.DOM.setContent(
people_root,
JX.$H(r.people_widget));
} catch (ex) {
}
}
// otherwise let's redraw the widget somewhat lazily
} else {
JX.Stratcom.invoke(
'conpherence-reload-widget',
null,
{
threadID : _loadedWidgetsID,
widget : widget_to_update
});
}
});
threadManager.syncWorkflow(workflow, 'submit');
}
);
JX.Stratcom.listen(
['touchstart', 'mousedown'],
'remove-person',
function (e) {
var href = config.widgetBaseUpdateURI + _loadedWidgetsID + '/';
var data = e.getNodeData('remove-person');
// While the user is removing themselves, disable the notification
// update behavior. If we don't do this, the user can get an error
// when they remove themselves about permissions as the notification
// code tries to load what jist happened.
var threadManager = JX.ConpherenceThreadManager.getInstance();
var loadedPhid = threadManager.getLoadedThreadPHID();
threadManager.setLoadedThreadPHID(null);
new JX.Workflow(href, data)
.setCloseHandler(function() {
threadManager.setLoadedThreadPHID(loadedPhid);
})
// we re-direct to conpherence home so the thread manager will
// fix itself there
.setHandler(function(r) {
JX.$U(r.href).go();
})
.start();
}
);
/* settings widget */
var onsubmitSettings = function (e) {
e.kill();
var form = e.getNode('tag:form');
var button = JX.DOM.find(form, 'button');
JX.Workflow.newFromForm(form)
.setHandler(JX.bind(this, function (r) {
new JX.Notification()
.setDuration(6000)
.setContent(r)
.show();
button.disabled = '';
JX.DOM.alterClass(button, 'disabled', false);
}))
.start();
};
JX.Stratcom.listen(
['submit', 'didSyntheticSubmit'],
'notifications-update',
onsubmitSettings
);
});