mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-17 18:21:11 +01:00
Show Aphlict connection status in notification menu
Summary: Fixes T5373. Ref T5281. Several changes: - The `marshallExceptions` thing is useful if JS throws an exception when invoked from Flash, so set it. The resulting exceptions are a little odd (not escaped correctly, e.g.) but way better than nothing. - Put connection status in the notification menu. - When the connection fails, try to provide contextual help where we can. Test Plan: {F169493} Reviewers: chad, joshuaspence Reviewed By: joshuaspence Subscribers: epriestley Maniphest Tasks: T5281, T5373 Differential Revision: https://secure.phabricator.com/D9700
This commit is contained in:
parent
5dffd88737
commit
76cefde0b3
12 changed files with 217 additions and 40 deletions
|
@ -7,8 +7,8 @@
|
|||
return array(
|
||||
'names' =>
|
||||
array(
|
||||
'core.pkg.css' => '22e4fc33',
|
||||
'core.pkg.js' => 'f5ba2408',
|
||||
'core.pkg.css' => 'f9c94804',
|
||||
'core.pkg.js' => '8c184823',
|
||||
'darkconsole.pkg.js' => 'df001cab',
|
||||
'differential.pkg.css' => '4a93db37',
|
||||
'differential.pkg.js' => 'd1443567',
|
||||
|
@ -37,7 +37,7 @@ return array(
|
|||
'rsrc/css/aphront/typeahead.css' => 'a989b5b3',
|
||||
'rsrc/css/application/auth/auth.css' => '1e655982',
|
||||
'rsrc/css/application/base/main-menu-view.css' => 'aceca0e9',
|
||||
'rsrc/css/application/base/notification-menu.css' => 'cbff1b94',
|
||||
'rsrc/css/application/base/notification-menu.css' => '8ae4a008',
|
||||
'rsrc/css/application/base/phabricator-application-launch-view.css' => '8b7e271d',
|
||||
'rsrc/css/application/base/standard-page-view.css' => '517cdfb1',
|
||||
'rsrc/css/application/chatlog/chatlog.css' => '852140ff',
|
||||
|
@ -346,9 +346,10 @@ return array(
|
|||
'rsrc/image/texture/table_header.png' => '5c433037',
|
||||
'rsrc/image/texture/table_header_hover.png' => '038ec3b9',
|
||||
'rsrc/image/texture/table_header_tall.png' => 'd56b434f',
|
||||
'rsrc/js/application/aphlict/Aphlict.js' => 'da12704d',
|
||||
'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => '862ea0fe',
|
||||
'rsrc/js/application/aphlict/Aphlict.js' => '4a07e8e3',
|
||||
'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => 'f51afce0',
|
||||
'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'a826c925',
|
||||
'rsrc/js/application/aphlict/behavior-aphlict-status.js' => '58f7803f',
|
||||
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
|
||||
'rsrc/js/application/config/behavior-reorder-fields.js' => '14a827de',
|
||||
'rsrc/js/application/conpherence/behavior-menu.js' => 'f0a41b9f',
|
||||
|
@ -490,7 +491,7 @@ return array(
|
|||
'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8',
|
||||
'rsrc/js/phuix/PHUIXActionView.js' => '6e8cefa4',
|
||||
'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca',
|
||||
'rsrc/swf/aphlict.swf' => 'ef64606d',
|
||||
'rsrc/swf/aphlict.swf' => 'e5a24c72',
|
||||
),
|
||||
'symbols' =>
|
||||
array(
|
||||
|
@ -539,10 +540,11 @@ return array(
|
|||
'herald-rule-editor' => '6c9e6fb8',
|
||||
'herald-test-css' => '778b008e',
|
||||
'inline-comment-summary-css' => '8cfd34e8',
|
||||
'javelin-aphlict' => 'da12704d',
|
||||
'javelin-aphlict' => '4a07e8e3',
|
||||
'javelin-behavior' => '8a3ed18b',
|
||||
'javelin-behavior-aphlict-dropdown' => '862ea0fe',
|
||||
'javelin-behavior-aphlict-dropdown' => 'f51afce0',
|
||||
'javelin-behavior-aphlict-listen' => 'a826c925',
|
||||
'javelin-behavior-aphlict-status' => '58f7803f',
|
||||
'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884',
|
||||
'javelin-behavior-aphront-crop' => 'fa0f4fc2',
|
||||
'javelin-behavior-aphront-drag-and-drop-textarea' => '92eb531d',
|
||||
|
@ -725,7 +727,7 @@ return array(
|
|||
'phabricator-nav-view-css' => '9283c2df',
|
||||
'phabricator-notification' => '0c6946e7',
|
||||
'phabricator-notification-css' => 'ef2c9b34',
|
||||
'phabricator-notification-menu-css' => 'cbff1b94',
|
||||
'phabricator-notification-menu-css' => '8ae4a008',
|
||||
'phabricator-object-selector-css' => '029a133d',
|
||||
'phabricator-phtize' => 'd254d646',
|
||||
'phabricator-prefab' => '41ed7994',
|
||||
|
@ -1190,6 +1192,11 @@ return array(
|
|||
1 => 'javelin-dom',
|
||||
2 => 'javelin-reactor-dom',
|
||||
),
|
||||
'4a07e8e3' =>
|
||||
array(
|
||||
0 => 'javelin-install',
|
||||
1 => 'javelin-util',
|
||||
),
|
||||
'4d94d9c3' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
|
@ -1235,6 +1242,13 @@ return array(
|
|||
2 => 'javelin-vector',
|
||||
3 => 'javelin-dom',
|
||||
),
|
||||
'58f7803f' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-aphlict',
|
||||
2 => 'phabricator-phtize',
|
||||
3 => 'javelin-dom',
|
||||
),
|
||||
'59b251eb' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
|
@ -1477,16 +1491,6 @@ return array(
|
|||
3 => 'javelin-workflow',
|
||||
4 => 'javelin-stratcom',
|
||||
),
|
||||
'862ea0fe' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-request',
|
||||
2 => 'javelin-stratcom',
|
||||
3 => 'javelin-vector',
|
||||
4 => 'javelin-dom',
|
||||
5 => 'javelin-uri',
|
||||
6 => 'javelin-behavior-device',
|
||||
),
|
||||
'880fa5ac' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
|
@ -1921,11 +1925,6 @@ return array(
|
|||
1 => 'javelin-util',
|
||||
2 => 'javelin-stratcom',
|
||||
),
|
||||
'da12704d' =>
|
||||
array(
|
||||
0 => 'javelin-install',
|
||||
1 => 'javelin-util',
|
||||
),
|
||||
'dd7e8ef5' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
|
@ -2038,6 +2037,16 @@ return array(
|
|||
5 => 'phuix-action-view',
|
||||
6 => 'javelin-workflow',
|
||||
),
|
||||
'f51afce0' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-request',
|
||||
2 => 'javelin-stratcom',
|
||||
3 => 'javelin-vector',
|
||||
4 => 'javelin-dom',
|
||||
5 => 'javelin-uri',
|
||||
6 => 'javelin-behavior-device',
|
||||
),
|
||||
'f588412e' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
|
|
|
@ -1803,6 +1803,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorNotificationPanelController' => 'applications/notification/controller/PhabricatorNotificationPanelController.php',
|
||||
'PhabricatorNotificationQuery' => 'applications/notification/PhabricatorNotificationQuery.php',
|
||||
'PhabricatorNotificationStatusController' => 'applications/notification/controller/PhabricatorNotificationStatusController.php',
|
||||
'PhabricatorNotificationStatusView' => 'applications/notification/view/PhabricatorNotificationStatusView.php',
|
||||
'PhabricatorNotificationTestController' => 'applications/notification/controller/PhabricatorNotificationTestController.php',
|
||||
'PhabricatorOAuthClientAuthorization' => 'applications/oauthserver/storage/PhabricatorOAuthClientAuthorization.php',
|
||||
'PhabricatorOAuthClientAuthorizationQuery' => 'applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php',
|
||||
|
@ -4631,6 +4632,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorNotificationPanelController' => 'PhabricatorNotificationController',
|
||||
'PhabricatorNotificationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorNotificationStatusController' => 'PhabricatorNotificationController',
|
||||
'PhabricatorNotificationStatusView' => 'AphrontTagView',
|
||||
'PhabricatorNotificationTestController' => 'PhabricatorNotificationController',
|
||||
'PhabricatorOAuthClientAuthorization' =>
|
||||
array(
|
||||
|
|
|
@ -25,16 +25,31 @@ final class PhabricatorNotificationPanelController
|
|||
pht('You have no notifications.'));
|
||||
}
|
||||
|
||||
$notifications_link = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/notification/',
|
||||
),
|
||||
pht('Notifications'));
|
||||
|
||||
$connection_status = new PhabricatorNotificationStatusView();
|
||||
|
||||
$header = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'phabricator-notification-header',
|
||||
),
|
||||
array(
|
||||
$connection_status,
|
||||
$notifications_link,
|
||||
));
|
||||
|
||||
$content = hsprintf(
|
||||
'<div class="phabricator-notification-header">%s %s</div>'.
|
||||
'%s'.
|
||||
'<div class="phabricator-notification-view-all">%s</div>',
|
||||
phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/notification/',
|
||||
),
|
||||
pht('Notifications')),
|
||||
'%s'.
|
||||
'<div class="phabricator-notification-view-all">%s %s %s</div>',
|
||||
$header,
|
||||
$content,
|
||||
javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
|
@ -43,7 +58,7 @@ final class PhabricatorNotificationPanelController
|
|||
'class' => 'phabricator-notification-clear-all'
|
||||
),
|
||||
pht('Mark All Read')),
|
||||
$content,
|
||||
" \xC2\xB7 ",
|
||||
phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorNotificationStatusView extends AphrontTagView {
|
||||
|
||||
protected function getTagAttributes() {
|
||||
if (!$this->getID()) {
|
||||
$this->setID(celerity_generate_unique_node_id());
|
||||
}
|
||||
|
||||
Javelin::initBehavior(
|
||||
'aphlict-status',
|
||||
array(
|
||||
'nodeID' => $this->getID(),
|
||||
'pht' => array(
|
||||
'setup' => pht('Setting Up Client'),
|
||||
'start' => pht('Starting Client'),
|
||||
'ready' => pht('Ready to Connect'),
|
||||
'connecting' => pht('Connecting...'),
|
||||
'connected' => pht('Connected'),
|
||||
'error' => pht('Connection Error'),
|
||||
'client' => pht('Connected Locally'),
|
||||
|
||||
'error.flash.xdomain' => pht(
|
||||
'Unable to connect to Flash Policy Server. Check that the '.
|
||||
'notification server is running and port 843 is not firewalled.'),
|
||||
),
|
||||
));
|
||||
|
||||
return array(
|
||||
'class' => 'aphlict-connection-status',
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -42,10 +42,6 @@ package {
|
|||
this.externalInvoke('log', message);
|
||||
}
|
||||
|
||||
final protected function setStatus(status:String):void {
|
||||
this.externalInvoke('status', {type: status});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ package {
|
|||
UncaughtErrorEvent.UNCAUGHT_ERROR,
|
||||
this.uncaughtErrorHandler);
|
||||
|
||||
ExternalInterface.marshallExceptions = true;
|
||||
ExternalInterface.addCallback('connect', this.externalConnect);
|
||||
|
||||
this.setStatus('ready');
|
||||
|
@ -150,6 +151,10 @@ package {
|
|||
this.externalInvoke('receive', msg);
|
||||
}
|
||||
|
||||
public function setStatus(status:String, code:String = null):void {
|
||||
this.externalInvoke('status', {type: status, code: code});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,6 +48,9 @@ package {
|
|||
private var socket:Socket;
|
||||
private var readBuffer:ByteArray;
|
||||
|
||||
private var status:String;
|
||||
private var statusCode:String;
|
||||
|
||||
|
||||
public function AphlictMaster(server:String, port:Number) {
|
||||
super();
|
||||
|
@ -75,6 +78,8 @@ package {
|
|||
if (!this.clients[client]) {
|
||||
this.log('Registering client: ' + client);
|
||||
this.clients[client] = new Date().getTime();
|
||||
|
||||
this.send.send(client, 'setStatus', this.status, this.statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,6 +111,8 @@ package {
|
|||
}
|
||||
|
||||
private function connectToServer():void {
|
||||
this.setStatusOnClients('connecting');
|
||||
|
||||
var socket:Socket = new Socket();
|
||||
|
||||
socket.addEventListener(Event.CONNECT, didConnectSocket);
|
||||
|
@ -124,7 +131,7 @@ package {
|
|||
}
|
||||
|
||||
private function didConnectSocket(event:Event):void {
|
||||
this.externalInvoke('connected');
|
||||
this.setStatusOnClients('connected');
|
||||
|
||||
// Send subscriptions
|
||||
var phids = new Array();
|
||||
|
@ -146,7 +153,15 @@ package {
|
|||
}
|
||||
|
||||
private function didSecurityErrorSocket(event:SecurityErrorEvent):void {
|
||||
this.externalInvoke('error', event.text);
|
||||
var text = event.text;
|
||||
|
||||
// This is really gross but there doesn't seem to be anything else
|
||||
// on the object which gives us an error code.
|
||||
if (text.match(/^Error #2048/)) {
|
||||
this.setStatusOnClients('error', 'error.flash.xdomain');
|
||||
}
|
||||
|
||||
this.error(text);
|
||||
}
|
||||
|
||||
public function subscribe(client:String, phids:Array):void {
|
||||
|
@ -280,6 +295,18 @@ package {
|
|||
}
|
||||
}
|
||||
|
||||
private function setStatusOnClients(
|
||||
status:String,
|
||||
code:String = null):void {
|
||||
|
||||
this.status = status;
|
||||
this.statusCode = code;
|
||||
|
||||
for (var client:String in this.clients) {
|
||||
this.send.send(client, 'setStatus', status, code);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -97,3 +97,17 @@
|
|||
padding: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.phabricator-notification-menu .aphlict-connection-status {
|
||||
float: right;
|
||||
font-weight: normal;
|
||||
color: {$lightgreytext};
|
||||
}
|
||||
|
||||
.aphlict-connection-status .aphlict-connection-status-connected {
|
||||
color: {$green};
|
||||
}
|
||||
|
||||
.aphlict-connection-status .aphlict-connection-status-error {
|
||||
color: {$red};
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ JX.install('Aphlict', {
|
|||
construct: function(id, server, port, subscriptions) {
|
||||
if (__DEV__) {
|
||||
if (JX.Aphlict._instance) {
|
||||
JX.$E('Aphlict object is a singleton!');
|
||||
JX.$E('Aphlict object is a singleton.');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,17 +36,24 @@ JX.install('Aphlict', {
|
|||
this._server = server;
|
||||
this._port = port;
|
||||
this._subscriptions = subscriptions;
|
||||
this._setStatus('setup');
|
||||
|
||||
JX.Aphlict._instance = this;
|
||||
},
|
||||
|
||||
events: ['didChangeStatus'],
|
||||
|
||||
members: {
|
||||
_id: null,
|
||||
_server: null,
|
||||
_port: null,
|
||||
_subscriptions: null,
|
||||
_status: null,
|
||||
_statusCode: null,
|
||||
|
||||
start: function(node, uri) {
|
||||
this._setStatus('start');
|
||||
|
||||
// NOTE: This is grotesque, but seems to work everywhere.
|
||||
node.innerHTML =
|
||||
'<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000">' +
|
||||
|
@ -72,6 +79,20 @@ JX.install('Aphlict', {
|
|||
this._server,
|
||||
this._port,
|
||||
this._subscriptions);
|
||||
},
|
||||
|
||||
getStatus: function() {
|
||||
return this._status;
|
||||
},
|
||||
|
||||
getStatusCode: function() {
|
||||
return this._statusCode;
|
||||
},
|
||||
|
||||
_setStatus: function(status, code) {
|
||||
this._status = status;
|
||||
this._statusCode = code || null;
|
||||
this.invoke('didChangeStatus');
|
||||
}
|
||||
|
||||
},
|
||||
|
@ -98,6 +119,7 @@ JX.install('Aphlict', {
|
|||
}
|
||||
|
||||
if (type == 'status') {
|
||||
client._setStatus(message.type, message.code);
|
||||
switch (message.type) {
|
||||
case 'ready':
|
||||
client._didStartFlash();
|
||||
|
|
|
@ -73,6 +73,12 @@ JX.behavior('aphlict-dropdown', function(config, statics) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!e.getNode('notification')) {
|
||||
// User clicked somewhere in the dead area of the menu, like the header
|
||||
// or footer.
|
||||
return;
|
||||
}
|
||||
|
||||
// If the user clicked a notification (but missed a link) and it has a
|
||||
// primary URI, go there.
|
||||
var href = e.getNodeData('notification').href;
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* @provides javelin-behavior-aphlict-status
|
||||
* @requires javelin-behavior
|
||||
* javelin-aphlict
|
||||
* phabricator-phtize
|
||||
* javelin-dom
|
||||
* @javelin
|
||||
*/
|
||||
|
||||
JX.behavior('aphlict-status', function(config) {
|
||||
var pht = JX.phtize(config.pht);
|
||||
|
||||
function update() {
|
||||
var client = JX.Aphlict.getInstance();
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
var node;
|
||||
try {
|
||||
node = JX.$(config.nodeID);
|
||||
} catch (ignored) {
|
||||
return;
|
||||
}
|
||||
|
||||
var tip = null;
|
||||
var status = client.getStatus();
|
||||
|
||||
if (status == 'error') {
|
||||
tip = pht(client.getStatusCode());
|
||||
}
|
||||
|
||||
var status_node = JX.$N(
|
||||
'span',
|
||||
{
|
||||
className: 'aphlict-connection-status-' + status,
|
||||
sigil: tip ? 'has-tooltip' : null,
|
||||
meta: tip ? {tip: tip, align: 'S', size: 300} : {}
|
||||
},
|
||||
pht(status));
|
||||
|
||||
JX.DOM.setContent(node, status_node);
|
||||
}
|
||||
|
||||
JX.Aphlict.listen('didChangeStatus', update);
|
||||
update();
|
||||
});
|
Binary file not shown.
Loading…
Reference in a new issue