blob: f6bf91bed4fb718dbe43cf8c51a5fd6670f07d15 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
var mercury = require('mercury');
var methodNameToVarHashKey = require('./methodNameToVarHashKey');
var methodStart = require('./method-start.js');
var methodEnd = require('./method-end.js');
var methodForm = require('../method-form/index.js');
var namespaceService = require('../../../../services/namespace/service');
var log = require('../../../../lib/log')(
'components:browse:item-details:server:display-server-details'
);
module.exports = displayServerDetails;
// Holds name of the last requested name.
var lastRequestedName;
/*
* Loads all the information needed to render the server details page.
*/
function displayServerDetails(state, events, data) {
var itemObs = data.itemObs;
var name = itemObs().objectName;
// Return if we are already on that item.
if (isCurrentlySelected()) {
return;
}
lastRequestedName = name;
state.put('item', itemObs);
state.put('itemName', name);
state.put('error', null);
state.put('signature', null);
state.put('remoteBlessings', null);
state.put('objectAddresses', null);
state.put('showLoadingIndicator', false);
// Whether we have finished loading yet.
var isLoaded = false;
// How long to wait before showing loading if things have not loaded yet
var SHOW_LOADING_THRESHOLD = 250;
setTimeout(function maybeShowLoadingIndicator() {
if (isLoaded || !isCurrentlySelected()) {
return;
}
state.put('showLoadingIndicator', true);
}, SHOW_LOADING_THRESHOLD);
var allPromises = Promise.all([
loadRemoteBlessings(itemObs()),
loadObjectAddresses(itemObs()),
loadSignature(itemObs())
]);
return allPromises.then(function() {
// Indicate we finished loading
setIsLoaded();
}).catch(function(err) {
log.error('Error while getting server details for', name, err);
if (!isCurrentlySelected()) {
return;
}
events.toast({
text: 'Error while getting server details for:' + name,
type: 'error'
});
state.put('error', err);
setIsLoaded();
});
function loadRemoteBlessings(item) {
if (!item.hasServer) {
return;
}
return namespaceService.getRemoteBlessings(name).then(function(rbs) {
// Protect this call; this must be the selected item.
if (!isCurrentlySelected()) {
return;
}
state.put('remoteBlessings', rbs);
});
}
function loadObjectAddresses(item) {
if (!item.hasServer) {
return;
}
return namespaceService.getObjectAddresses(name).then(function(eps) {
// Protect this call; this must be the selected item.
if (!isCurrentlySelected()) {
return;
}
state.put('objectAddresses', eps);
});
}
function loadSignature(item) {
if (!item.hasServer) {
return;
}
return namespaceService.getSignature(name).then(function(signatureResult) {
// Protect this call; this must be the selected item.
if (!isCurrentlySelected()) {
return;
}
state.put('signature', signatureResult);
if (!signatureResult) {
return;
}
// Go through each signature method from each interface. Prepare the state
// needed for the form to be rendered and its events to function.
signatureResult.forEach(function(interface, i) {
var forms = mercury.varhash();
var formEvents = mercury.varhash();
interface.methods.forEach(function(methodData) {
var methodName = methodData.name;
var methodKey = methodNameToVarHashKey(methodName);
var form = methodForm();
forms.put(methodKey, form.state);
formEvents.put(methodKey, form.events);
// Hook up the new form's method start, end, and toast events.
form.events.methodStart(
methodStart.bind(null, state, methodName)
);
form.events.methodEnd(
methodEnd.bind(null, state, methodName, interface)
);
form.events.toast = events.toast;
// Finally, allow the form to gather the info it needs to display.
form.events.displayMethodForm({
itemName: name,
interface: interface,
methodName: methodName
});
});
// Save the method forms, events, open-status of each interface.
// Note: Some services have more interfaces than others. If a service
// has fewer than usual, it won't override/delete any extra interfaces.
// It isn't necessary because those old interfaces won't be rendered.
state.methodForms.put(i, forms);
events.methodForms[i] = formEvents;
// Note: We want the __Reserved interface to be closed by default.
// It has a common pool of methods that would be distracting in the UI.
state.methodFormsOpen.put(i, interface.name !== '__Reserved');
});
});
}
/*
* Indicates the current request has finished loading
*/
function setIsLoaded() {
isLoaded = true;
state.put('showLoadingIndicator', false);
}
/*
* Returns whether we are still the currently selected item or not
*/
function isCurrentlySelected() {
return (name === lastRequestedName);
}
}