/*
* Copyright 2025 Anyware Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This class handles the errors, warnings or info after content edition
*/
Ext.define(
"Ametys.cms.content.ContentErrorHelper",
{
singleton: true,
/**
* Callback function called after edit content server request is processed
* @param {HTMLElement} response The XML document.
* @param {HTMLElement} response The XML document.
* @param {Object} params The callback arguments (see #createContent documentation).
* @param {Object} additionalFns The additional functions to call for each kind of errors
* @param {Function} successFn The function to be call to handle success
* @param {Function} workflowValidationErrorFn The function to be call to handle workflow errors
* @param {Function} fieldResultErrorFn The function to be call to handle field errors
* @param {Function} fieldResultWarningFn The function to be call to handle field warning
* @param {Function} fieldResultInfoFn The function to be call to handle field informations
* @param {Function} messageFn The function to be call to handle messages (as duplicate content)
*/
handleContentEditError: function (response, contentId, params, additionalFns)
{
var success = Ext.dom.Query.selectValue ('> ActionResult > success', response) == "true";
// Handling workflow errors
if (Ext.isFunction (additionalFns.workflowValidationErrorFn))
{
var workflowErrors = Ext.dom.Query.select ('> ActionResult > workflowValidation > error', response);
if (!success && workflowErrors.length > 0)
{
var workflowMsgErrors = [];
var detailedMsg = '<ul>';
for (var i=0; i < workflowErrors.length; i++)
{
var errorMsg = Ext.dom.Query.selectValue("", workflowErrors[i]);
detailedMsg += '<li>' + errorMsg + '</li>';
workflowMsgErrors.push(errorMsg);
}
detailedMsg += '</ul>';
var msg = "{{i18n PLUGINS_CMS_SAVE_ACTION_FAILED_WORKFLOW_DESC}}";
additionalFns.workflowValidationErrorFn(contentId, msg, detailedMsg, workflowMsgErrors, params);
return;
}
}
// Handling field errors
if (Ext.isFunction (additionalFns.fieldResultErrorFn))
{
var errors = Ext.dom.Query.select ('> ActionResult > * > fieldResult > error', response);
if (!success && errors.length > 0)
{
var msg = "{{i18n PLUGINS_CMS_SAVE_ACTION_FAILED_DESC}}";
msg += errors.length == 1 ? "{{i18n PLUGINS_CMS_SAVE_ACTION_FAILED_DESC_SINGLE}}" : errors.length + "{{i18n PLUGINS_CMS_SAVE_ACTION_FAILED_DESC_MULTI}}";
var fieldsInError = {};
var detailedMsg = this._getFieldsDetailedMessageAndFillFieldMessages(errors, fieldsInError);
additionalFns.fieldResultErrorFn(contentId, msg, detailedMsg, fieldsInError, params);
return;
}
}
// Handling field warnings
if (Ext.isFunction (additionalFns.fieldResultWarningFn))
{
var allWarnings = Ext.dom.Query.select ('> ActionResult > * > fieldResult > warning', response)
if (!success && allWarnings.length > 0)
{
var fieldsWithWarning = {};
var warnings = this._filterBypassedWarnings(allWarnings, params.bypassedWarnings);
var hasWarning = warnings.length > 0;
var msg = hasWarning
? warnings.length == 1 ? "{{i18n PLUGINS_CMS_SAVE_ACTION_WARNING_DESC_SINGLE}}" : "{{i18n PLUGINS_CMS_SAVE_ACTION_WARNING_DESC_MULTI}}"
: null;
var detailedMsg = hasWarning ? this._getFieldsDetailedMessageAndFillFieldMessages(warnings, fieldsWithWarning) : null;
var question = hasWarning ? "{{i18n PLUGINS_CMS_SAVE_ACTION_WARNING_DESC_QUESTION}}" : null;
additionalFns.fieldResultWarningFn(contentId, msg, detailedMsg, question, fieldsWithWarning, params)
return;
}
}
// Handling field infos
if (Ext.isFunction (additionalFns.fieldResultInfoFn))
{
var infos = Ext.dom.Query.select ('> ActionResult > * > fieldResult > info', response);
if (success && infos.length > 0)
{
var msg = "{{i18n PLUGINS_CMS_SAVE_ACTION_FAILED_WORKFLOW_DESC}}TODO";
var msg = infos.length == 1 ? "{{i18n PLUGINS_CMS_SAVE_ACTION_INFO_DESC_SINGLE}}" : "{{i18n PLUGINS_CMS_SAVE_ACTION_INFO_DESC_MULTI}}";
var fieldsWithInfo = {};
var detailedMsg = this._getFieldsDetailedMessageAndFillFieldMessages(infos, fieldsWithInfo);
additionalFns.fieldResultInfoFn(contentId, msg, detailedMsg, fieldsWithInfo, params)
}
}
// Handling warning messages
if (Ext.isFunction (additionalFns.messageFn))
{
var messages = Ext.dom.Query.select ('> ActionResult > messages > messages', response);
if (success && messages.length > 0)
{
var globalLevel = "info";
var messagesTab = [];
for (var i=0; i < messages.length; i++)
{
var currentLevel = Ext.dom.Query.selectValue("type", messages[i]);
if (globalLevel == "info" && currentLevel == 'warning')
{
globalLevel = currentLevel;
}
var currentMessages = Ext.dom.Query.select ('message > message', messages[i]);
var currentMessage = '';
for (var j=0; j < currentMessages.length; j++)
{
currentMessage += Ext.dom.Query.selectValue("", currentMessages[j]);
}
messagesTab.push({
msg: currentMessage,
level: currentLevel
});
}
additionalFns.messageFn(contentId, messagesTab, globalLevel, params)
}
}
// Success
if (Ext.isFunction(additionalFns.successFn))
{
additionalFns.successFn(contentId, params)
}
},
/**
* @private
* Retrieves detailed message for given fields
* @param {HTMLElement[]} fields The XML containing fields and corresponding messages
* @param {Object} fieldMessages the object to fill with fields' messages
* @return {String} the detailed message
*/
_getFieldsDetailedMessageAndFillFieldMessages: function (fields, fieldMessages)
{
var detailedMessage = '<ul>';
for (var i=0; i < fields.length; i++)
{
var fieldData = fields[i].parentNode.parentNode;
var fieldId = fieldData.tagName;
var message = Ext.dom.Query.selectValue("", fields[i]);
if (fieldId == '_global')
{
detailedMessage += '<li>' + message + '</li>';
}
else
{
var fieldPath = Ext.dom.Query.selectValue ('> fieldPath', fieldData);
var messages = fieldMessages['content.input.' + (fieldPath || fieldId)] || [];
messages.push(message);
fieldMessages['content.input.' + (fieldPath || fieldId)] = messages;
var fieldLabel = Ext.dom.Query.selectValue ('> fieldLabel', fieldData);
detailedMessage += '<li><b>' + (fieldLabel || fieldId) + '</b><br/>' + message + '</li>';
}
}
detailedMessage += '</ul>';
return detailedMessage;
},
/**
* @private
* Filter the given warnings to not keep warnings that have already been bypassed
* @param {HTMLElement[]} allWarnings all the warnings
* @param {Object} bypassedWarnings warnings that have already been bypassed
* @return {HTMLElement[]} the filtered warnings
*/
_filterBypassedWarnings: function(allWarnings, bypassedWarnings)
{
if (Ext.Object.isEmpty(bypassedWarnings))
{
// there is no bypassed warnings, retireve all warnings
return allWarnings;
}
var warnings = [];
for (var i=0; i < allWarnings.length; i++)
{
if (!this._hasWarningBeenBypassed(allWarnings[i], bypassedWarnings))
{
warnings.push(allWarnings[i]);
}
}
return warnings;
},
/**
* @private
* Checks if the given warning has already been bypassed
* @param {HTMLElement} warning the warning to check
* @param {Object} bypassedWarnings warnings that have already been bypassed
* @return {Boolean} true if the given warning has already been bypassed, false otherwise
*/
_hasWarningBeenBypassed(warning, bypassedWarnings)
{
var warningData = warning.parentNode.parentNode;
var warningPath = Ext.dom.Query.selectValue ('> fieldPath', warningData);
for (var bypassedWarningId in bypassedWarnings)
{
for (var bypassedWarning of bypassedWarnings[bypassedWarningId])
{
if (bypassedWarning.type == 'server' && bypassedWarning.fieldName == 'content.input.' + warningPath)
{
return true;
}
}
}
},
}
);