Current File : /var/www/e360ban/wp-content/plugins/wp-views/vendor/toolset/toolset-common/debug/main.js |
var Toolset = Toolset || {};
Toolset.Gui = Toolset.Gui || {};
/**
* Toolset Troubleshooting page controller.
*
* This object is also acting as the main viewmodel which holds the collection of the troubleshooting section viewmodels.
*
* @param $
* @constructor
* @since m2m
*/
Toolset.Gui.TroubleshootingPage = function($) {
var self = this;
// Parent constructor
Toolset.Gui.AbstractPage.call(self);
/**
* Augment self, turning it into the main viewmodel for the page.
*
* @returns {Toolset.Gui.TroubleshootingPage}
* @since m2m
*/
self.getMainViewModel = function() {
self.isActionInProgress = ko.observable(false);
var modelData = self.getModelData();
// Create viewmodels for individual troubleshooting sections.
// Model fields are descibed in the toolset_get_troubleshooting_sections filter inline doc.
var sectionVMs = _.map(modelData.sections, function(sectionModel) {
/**
* A single section viewmodel, which binds to the "postbox" elements.
*
* @type {sectionViewmodel}
*/
var sectionViewmodel = new function() {
var vm = this;
// Read-only properties
vm.title = sectionModel.title;
vm.description = sectionModel.description;
vm.buttonLabel = sectionModel.button_label;
vm.isDangerous = sectionModel.is_dangerous;
/** True if the user has clicked on the "I know what I'm doing" checkbox */
vm.userConfirmed = ko.observable(false);
/** Is the action in progress at the moment? */
vm.isInProgress = ko.observable(false);
/** True once the action has been completed. */
vm.isCompleted = ko.observable(false);
/**
* Determine whether the action can be started.
*/
vm.canProceed = ko.computed(function() {
return (
!self.isActionInProgress()
&& (!vm.isDangerous || vm.userConfirmed())
);
});
/**
* Compute the CSS selector for the Start button.
*/
vm.buttonClass = ko.pureComputed(function() {
if(vm.canProceed()) {
if(vm.isDangerous) {
return 'button button-primary toolset-red-button';
} else {
return 'button button-primary';
}
} else {
return 'button-secondary';
}
});
/** Textual output from the AJAX calls to be displayed to the user. */
vm.output = ko.observable('');
vm.isOutputEmpty = ko.computed(function() {
return (0 === vm.output().length);
});
/** Append a new line to the output. */
vm.appendToOutput = function(text) {
var currentContent = (vm.isOutputEmpty() ? '' : vm.output() + "\n");
vm.output(currentContent + text);
};
/** Initiate the action. */
vm.onClick = function() {
vm.output('');
vm.isCompleted(false);
var initialActionData = {
action: sectionModel.action_name,
wpnonce: sectionModel.nonce
};
self.doAction(vm, initialActionData, sectionModel);
};
};
return sectionViewmodel;
});
/**
* Perform the (possibly multi-step) action.
*
* Starts with an AJAX call as defined by the section VM. Depending on what the AJAX response is,
* further calls may be performed until the "continue" flag is no longer true.
*
* This is well-described by the toolset_get_troubleshooting_sections filter.
*
* @param vm Section ViewModel.
* @param {{action:string, wpnonce:string}} initialActionData Base for the "data" property for the AJAX call arguments.
* @param {{ajax_arguments:object}} initialArgumentSource Object holding the "argument source" whose properties will be appended to
* the "data" mentioned above.
* @since m2m
*/
self.doAction = function(vm, initialActionData, initialArgumentSource) {
// Indicate the activity
vm.isInProgress(true);
self.isActionInProgress(true);
// Prepare helper functions
var indicateActivityEnd = function() {
vm.isCompleted(true);
vm.isInProgress(false);
self.isActionInProgress(false);
};
// From the "argument source" and initialActionData, build a new actionData object.
var maybeAppendAjaxArguments = function(source) {
var actionData = _.extend(initialActionData);
if(_.has(source, 'ajax_arguments')) {
actionData = _.extendOwn(actionData, source['ajax_arguments']);
}
return actionData;
};
// Parse a message from the response or return a default one.
var getMessage = function(responseData, defaultValue) {
var message = (
_.has(responseData, 'message') && responseData.message.length > 0
? responseData.message
: defaultValue
);
return message;
};
// Callback on failed AJAX call. Print the error and finish.
var failCallback = function(response, responseData) {
var message = getMessage(responseData, 'An unknown error has happened.');
vm.appendToOutput(message);
indicateActivityEnd();
};
var actionData = maybeAppendAjaxArguments(initialArgumentSource);
// Process one step at a time until the AJAX call doesn't return the "continue" flag in the response.
//
// For explanation about how we're processing asynchronous AJAX calls in a loop but without risking
// a stack overflow, look here: http://metaduck.com/01-asynchronous-iteration-patterns.html
(function oneStep(actionData) {
// Perform the async call
$.post({
url: ajaxurl,
data: actionData,
success: function (originalResponse) {
var response = WPV_Toolset.Utils.Ajax.parseResponse(originalResponse);
// noinspection JSUnusedAssignment
self.debug('AJAX response', actionData, originalResponse);
if (response.success) {
// Inform the user
var responseData = response.data;
var message = getMessage(responseData, 'Action completed.');
vm.appendToOutput(message);
console.log(responseData);
// Does the response contain instructions about next step?
var shouldContinue = _.has(responseData, 'continue') && responseData.continue;
if(shouldContinue) {
// Build actionData for next step and execute it
var actionData = maybeAppendAjaxArguments(responseData);
// This will be called immediately after the stack unwinds,
// preventing a stack overflow even for very high number of steps.
setTimeout(_.partial(oneStep, actionData), 0);
} else {
// No next steps, we're successfully done here.
indicateActivityEnd();
}
} else {
failCallback(response, response.data || {});
}
},
error: function (ajaxContext) {
console.log('Error:', ajaxContext.responseText);
failCallback({success: false, data: {}}, {});
}
});
})(actionData);
};
self.sections = ko.observableArray(sectionVMs);
// Initialize the main viewmodel.
ko.applyBindings(self);
return self;
};
self.beforeInit = function() {
self.addKnockoutBindingHandlers();
};
/**
* Add custom Knockout bindings.
*/
self.addKnockoutBindingHandlers = function() {
// Update textarea's value and scroll it to the bottom.
var valueScroll = function(element, valueAccessor) {
var value = ko.unwrap(valueAccessor());
var textarea = $(element);
textarea.val(value);
textarea.scrollTop(textarea[0].scrollHeight);
};
ko.bindingHandlers.valueScroll = {
init: valueScroll,
update: valueScroll
};
};
self.afterInit = function() {
// Discourage the user from leaving the page while an action is in progress.
WPV_Toolset.Utils.setConfirmUnload(
function() {
return self.isActionInProgress();
},
null,
self.getString('confirmUnload')
);
}
};
// Make everything happen.
Toolset.Gui.troubleshootingPage = new Toolset.Gui.TroubleshootingPage(jQuery);
jQuery(Toolset.Gui.troubleshootingPage.init);