/*
* Copyright 2017 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.
*/
/**
* Singleton class for actions on hierarchical reference tables
*/
Ext.define('Ametys.plugins.cms.content.actions.HierarchicalReferenceTablesActions', {
singleton: true,
/**
* Adds a new (non-leaf) reference table content.
* @param {Ametys.plugins.cms.content.controller.HierarchicalReferenceTablesController} controller The controller calling this function
*/
add: function(controller)
{
var targets = controller.getMatchingTargets();
if (targets.length > 0)
{
if (targets[0].getId() == Ametys.message.MessageTarget.REFERENCE_TABLE_CONTENT)
{
var parentContentId = targets[0].getParameters().id;
controller.serverCall("getContentTypesForChild", [parentContentId], Ext.bind(this._openCreateContentDialog, this, [controller.getInitialConfig(), parentContentId], 1));
}
else
{
controller.serverCall("getContentTypeForRoot", [targets[0].getParameters().contentType], Ext.bind(this._openCreateContentDialog, this, [controller.getInitialConfig(), null], 1));
}
}
},
/**
* @private
* Configure and open dialog box of content creation
* @param {String|String[]} cTypeIds The id of content types to create
* @param {Object} btnConfig The configuration button
* @param {String} [parentId] The id of parent
*/
_openCreateContentDialog: function (cTypeIds, btnConfig, parentId)
{
var contentTypes = [];
var cTypeIds = Ext.Array.from(cTypeIds);
Ext.Array.each(cTypeIds, function (cTypeId) {
contentTypes.push(Ametys.cms.content.ContentTypeDAO.getContentType(cTypeId));
});
var openParams = {
contentTypes: contentTypes,
contentLanguage: btnConfig.contentLanguage,
initWorkflowActionId: btnConfig.initWorkflowActionId,
workflowName: btnConfig.workflowName,
defaultContentTitle: contentTypes[0].getDefaultTitle(),
title: "{{i18n PLUGINS_CMS_UITOOL_HIERARCHICAL_REFERENCE_TABLES_NEW_CONTENT_DIALOG_TITLE}}",
contentMessageTargetType: Ametys.message.MessageTarget.REFERENCE_TABLE_CONTENT
}
Ametys.cms.uihelper.CreateContent.open (openParams, Ext.bind(this._createCb, this, [parentId, cTypeIds, btnConfig], true), this);
},
/**
* @private
* Callback after creating the new content. Set the relation to parent
* @param {String} contentId The newly created content
* @param {String} parentContentId The identifier of the parent content
* @param {String[]} cTypeIds The id of content types
* @param {Object} btnConfig The configuration of the button
*/
_createCb: function(contentId, parentContentId, cTypeIds, btnConfig)
{
if (parentContentId)
{
Ametys.data.ServerComm.callMethod({
role: "org.ametys.cms.content.referencetable.HierarchicalReferenceTablesHelper",
methodName: "getParentAttribute",
parameters: [contentId],
callback: {
handler: this._getParentAttributeCb,
scope: this,
arguments: {
contentId: contentId,
parentContentId: parentContentId,
btnConfig: btnConfig
}
},
waitMessage: false
});
}
else
{
Ext.create("Ametys.message.Message", {
type: Ametys.message.Message.MODIFIED,
targets: {
id: Ametys.message.MessageTarget.REFERENCE_TABLE_CONTENT_ROOT,
parameters: { contentType: cTypeIds}
},
parameters: {
major: false
}
});
}
},
/**
* @private
* Callback invoked after getting the parent attribute path. Set the relation to parent
* @param {String} parentAttributePath The parent attribute path
* @param {Object} args The callback arguments
* @param {String} args.contentId The identifier of the newly created content
* @param {String} args.parentContentId The identifier of the parent content
* @param {Object} args.btnConfig The configuration of the button
*/
_getParentAttributeCb: function(parentAttributePath, args)
{
var me = this,
btnConfig = args.btnConfig,
contentId = args.contentId,
parentContentId = args.parentContentId,
contentIdsToEdit = {};
contentIdsToEdit[contentId] = null;
Ametys.data.ServerComm.callMethod({
role: "org.ametys.core.ui.RelationsManager",
id: "org.ametys.cms.relations.setcontentattribute",
methodName: "setContentAttribute",
parameters: [
[parentContentId],
contentIdsToEdit,
[],
parentAttributePath,
[btnConfig.editWorkflowActionId || "2"]
],
callback: {
handler: function(response, args) {
if (response == null)
{
Ametys.log.ErrorDialog.display({
title: "{{i18n PLUGINS_CMS_HIERARCHICAL_REFERENCE_TABLES_CREATEDNOTASSOCIATED_TITLE}}",
text: "{{i18n PLUGINS_CMS_HIERARCHICAL_REFERENCE_TABLES_CREATEDNOTASSOCIATED_TEXT}}",
category: this.self.getName()
});
}
else
{
var errors = response['errorMessages'];
if (errors && errors.length > 0)
{
var detailedMsg = "";
for (var i=0; i < errors.length; i++)
{
detailedMsg = response['errorMessages'][i] + "<br/>";
}
this.getLogger().error({
message: "{{i18n PLUGINS_CMS_HIERARCHICAL_REFERENCE_TABLES_CREATEDNOTASSOCIATED_TEXT}}",
details: detailedMsg,
defaultFocus: 0
});
Ametys.form.SaveHelper.SaveErrorDialog.showErrorDialog ("{{i18n PLUGINS_CMS_HIERARCHICAL_REFERENCE_TABLES_CREATEDNOTASSOCIATED_TITLE}}", "", detailedMsg);
return;
}
if (response['success'] == true)
{
Ext.create("Ametys.message.Message", {
type: Ametys.message.Message.MODIFIED,
targets: {
id: Ametys.message.MessageTarget.REFERENCE_TABLE_CONTENT,
parameters: { ids: [parentContentId]}
},
parameters: {
major: false
}
});
}
}
},
arguments: null
},
waitMessage: true
});
},
/**
* Rename a (non-leaf) simple content.
* @param {Ametys.plugins.cms.content.controller.HierarchicalReferenceTablesController} controller The controller calling this function
*/
rename: function(controller)
{
var targets = controller.getMatchingTargets();
if (targets.length > 0)
{
var contentId = targets[0].getParameters().id;
controller.serverCall("getTitleForEdition", [contentId], Ext.bind(this._getTitleForEditionCb, this, [contentId, controller.getInitialConfig("editWorkflowActionId")], 1));
}
},
/**
* @private
* Callback function invoked after retrieving current title value and type
* @param {Object} titleInfo The title's properties
* @param {String} titleInfo.type The title's type
* @param {String|Object} titleInfo.value The title's value
* @param {String} contentId The id of content being renamed
* @param {String} actionId The workflow action id
*/
_getTitleForEditionCb: function(titleInfo, contentId, actionId)
{
this._createRenameDialogBox(titleInfo, contentId, actionId);
this._renameBox.show();
},
/**
* Rename a (non-leaf) simple content.
* @param {String} id The id of the content
* @param {String} editWorkflowActionId The id of the edit workflow action
* @param {String|Object} value Value of the new content title
* @param {Function} [callback] Callback function to call after editing
* @param {Object} [scope] The scope for callback
*/
doRename: function(id, editWorkflowActionId, value, callback, scope)
{
Ametys.cms.content.ContentDAO.editContent({
contentId: id,
editWorkflowActionId: editWorkflowActionId,
values: {
"content.input.title": value
}
}, callback, scope, false, Ametys.message.MessageTarget.REFERENCE_TABLE_CONTENT);
},
/**
* @private
* Create the dialog box to rename a content in the tree
* @param {Object} titleInfo The title's properties
* @param {String} titleInfo.type The title's type
* @param {String|Object} titleInfo.value The title's value
* @param {String} contentId The id of content being renamed
* @param {String} actionId The workflow action id
*/
_createRenameDialogBox: function(titleInfo, contentId, actionId)
{
var formPanel = Ext.create('Ext.form.Panel', {
border: false,
defaults: {
cls: 'ametys',
anchor: '95%'
},
fieldDefaults : {
labelAlign: 'right',
labelSeparator: '',
labelWidth: 50
},
items : [{
xtype: titleInfo.type == 'multilingual-string' ? 'edition.multilingual-string' : 'textfield',
name: 'title',
allowBlank: false,
value: titleInfo.value,
fieldLabel: titleInfo.label
}
]
});
this._renameBox = Ext.create('Ametys.window.DialogBox', {
title: "{{i18n PLUGINS_CMS_UITOOL_HIERARCHICAL_REFERENCE_TABLES_RENAME_CONTENT_LABEL}}",
iconCls: 'ametysicon-list6 decorator-ametysicon-text1',
layout :'fit',
width : 350,
items: formPanel,
defaultFocus: formPanel.getForm().findField('title'),
closeAction: 'destroy',
referenceHolder: true,
defaultButton: 'validate',
buttons: [{
reference: 'validate',
text :"{{i18n PLUGINS_CMS_UITOOL_HIERARCHICAL_REFERENCE_TABLES_RENAME_OK_BUTTON}}",
handler : function() {
if (!formPanel.getForm().isValid())
{
return;
}
var value = formPanel.getForm().findField("title").getValue();
this.doRename(contentId, actionId, value, Ext.bind(function() {this._renameBox.close();}, this));
},
scope: this
},{
text :"{{i18n PLUGINS_CMS_UITOOL_HIERARCHICAL_REFERENCE_TABLES_RENAME_CANCEL_BUTTON}}",
handler : Ext.bind(function() {this._renameBox.close();}, this)
}]
});
},
/**
* Delete the contents registered by the controller.
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
delete: function (controller)
{
var contentIds = controller.getContentIds();
var tool = Ametys.tool.ToolsManager.getFocusedTool();
if (contentIds.length > 0)
{
var contentTargets = controller.getMatchingTargets();
var validContentTargets = [];
var contentTitles = [];
Ext.Array.forEach (contentTargets, function (contentTarget) {
if (Ext.Array.contains (contentIds, contentTarget.getParameters().id))
{
validContentTargets.push(contentTarget);
contentTitles.push (contentTarget.getParameters().title);
}
});
Ametys.Msg.confirm("{{i18n CONTENT_DELETE_LABEL}}",
"{{i18n CONTENT_DELETE_CONFIRM}}" + contentTitles.join(', ') + ' ?',
Ext.bind(this._deleteConfirm, this, [controller, contentIds, tool], 1),
this
);
}
},
/**
* Callback function invoked after the #act confirm box is closed
* @param {String} answer Id of the button that was clicked
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling the #act function
* @param {String[]} contentIds The content identifiers
* @param {Ametys.tool.Tool} tool The tool the deletion comes from
* @private
*/
_deleteConfirm: function (answer, controller, contentIds, tool)
{
if (answer == 'yes')
{
Ametys.data.ServerComm.callMethod({
role: "org.ametys.cms.content.referencetable.HierarchicalReferenceTablesDeleteContentDAO",
methodName: "trashContents",
parameters: [contentIds],
callback: {
handler: this._deleteConfirmCb,
scope: this,
arguments: {
targets: controller.getMatchingTargets()
}
},
waitMessage: {
msg: "{{i18n PLUGINS_CMS_UITOOL_HIERARCHICAL_REFERENCE_TABLES_DELETE_CONTENT_WAIT_MSG}}",
target: tool && tool.getContentPanel()
}
});
}
},
/**
* @private
* Callback function called after contents were removed
* @param {Object} response The server result
* @param {Object} args The callback arguments :
* @param {Ametys.message.MessageTarget[]} args.targets The content's targets
* @param {Ametys.message.MessageTarget[]} [args.callback] The callback function
*/
_deleteConfirmCb: function (response, args)
{
var targets = args.targets;
var deletedContents = response['deleted-contents'];
if (deletedContents.length > 0)
{
var deletedContentTargets = [];
for (var i=0; i < deletedContents.length; i++)
{
for (var j=0; j < targets.length; j++)
{
if (targets[j].getParameters().id == deletedContents[i].id)
{
deletedContentTargets.push(targets[j]);
}
}
// Remove content from navigation history
Ametys.navhistory.HistoryDAO.removeEntry (deletedContents[i].id);
// Notify content deletion
Ametys.notify({
type: 'info',
iconGlyph: 'ametysicon-text70',
title: "{{i18n PLUGINS_CMS_NOTIFICATION_DELETE_CONTENT_TITLE}}",
description: Ext.String.format("{{i18n PLUGINS_CMS_NOTIFICATION_DELETE_CONTENT_DESCRIPTION}}", Ext.String.escapeHtml(deletedContents[i].title))
});
}
// Fires deleted event
Ext.create("Ametys.message.Message", {
type: Ametys.message.Message.DELETED,
parameters : {trashed: true},
targets: deletedContentTargets
});
}
var undeletedContents = response['undeleted-contents'];
var referencedContents = response['referenced-contents'];
var lockedContents = response['locked-contents'];
var unauthorizedContents = response['unauthorized-contents'];
if (undeletedContents.length > 0 || referencedContents.length > 0 || lockedContents.length > 0 || unauthorizedContents.length > 0)
{
var message = '';
var message = this._buildErrorMessage(message, undeletedContents, "{{i18n CONTENT_DELETE_FAILED_CONTENTS}}");
message = this._buildErrorMessage(message, referencedContents, "{{i18n CONTENT_DELETE_REFERENCED_CONTENTS}}", ".<br/>{{i18n CONTENT_DELETE_REFERENCED_CONTENTS_END}}");
message = this._buildErrorMessage(message, lockedContents, "{{i18n CONTENT_DELETE_LOCKED_CONTENTS}}");
message = this._buildErrorMessage(message, unauthorizedContents, "{{i18n CONTENT_DELETE_UNAUTHORIZED_CONTENTS}}");
Ametys.Msg.show({
title: "{{i18n CONTENT_DELETE_LABEL}}",
msg: message,
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.ERROR
});
}
if (Ext.isFunction (args.callback))
{
args.callback.call(args.scope, response);
}
},
/**
* @private
* Build error message
* @param {String} message The initial error message
* @param {Object[]} contentsInError The contents in error
* @param {String} startDesc The start description
* @param {String} endDesc The end description
*/
_buildErrorMessage: function(message, contentsInError, startDesc, endDesc)
{
message = message || '';
if (contentsInError.length > 0)
{
if (message.length > 0)
{
message += '<br/><br/>';
}
message += startDesc || '';
for (var i=0; i < contentsInError.length; i++)
{
message += (i > 0 ? ', ' : '') + contentsInError[i].title;
}
message += endDesc || '';
}
return message;
}
});