mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-23 07:12:41 +01:00
0acdf256fc
Summary: Ref T7757. Oddities include: - not working in column view, since the generic anchor technology conflicts once you navigate to a page with a transaction timeline view - not working if you are linking to a message not included in initial load Remaining work is addressing these oddities. - make column view timestamp link to full conpherence correctly? - make back end load from hyperlinked transaction forward? or do it more like application transactions and have the client keep requesting stuff until it gets it? Open to suggestions! :D Test Plan: played around in conpherence full and stuff looked okay. noted no changes as intended in column view. Reviewers: epriestley, chad Reviewed By: epriestley Subscribers: Korvin, epriestley Maniphest Tasks: T7757 Differential Revision: https://secure.phabricator.com/D12402
363 lines
11 KiB
JavaScript
363 lines
11 KiB
JavaScript
/**
|
|
* @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 item = new JX.PHUIXActionView()
|
|
.setIcon(widget_data.icon || 'none')
|
|
.setName(widget_data.name)
|
|
.setHandler(
|
|
JX.bind(null, function(widget, e) {
|
|
toggleWidget({widget: widget});
|
|
e.prevent();
|
|
menu.close();
|
|
}, widget));
|
|
|
|
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');
|
|
// we end up re-directing to conpherence home
|
|
new JX.Workflow(href, data)
|
|
.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
|
|
);
|
|
|
|
});
|