/*
* Copyright 2013 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 helper provides a dialog box to copy a content as a new content.
* The dialog box brings an advanced mode to allow to select the content attributes to copied in a tree.
* See #open method.
* @private
*/
Ext.define('Ametys.plugins.cms.content.helper.CopyContent', {
singleton: true,
/**
* @property {Ametys.window.DialogBox} _box The dialog box
* @private
*/
/**
* @property {Ametys.plugins.cms.content.tree.ViewTree} _tree The tree that displays the current view and allow the user to select/deselect the desired attributes.
* @private
*/
/**
* @property {String} _content The copied content.
* @private
*/
/**
* @property {Number} [_workflowInitActionId=111] The id of the workflow action to initialize the duplicated content. Can be null to use the default value.
* @private
*/
/**
* @property {Number} [_workflowEditActionId=2] The id of the workflow action to edit the target content. Can be null to use the default value.
* @private
*/
/**
* @property {String} [_viewName="default-edition"] The name of the view to be displayed in attributes tree. Can be null to use the default value.
* @private
*/
/**
* @property {String} [_fallbackViewName="main"] The fallback view to be displayed in attributes tree. Used (for legacy purpose) when _viewName is not found.
* @private
*/
/**
* @property {String} [_viewMode="edition"] The mode of the view to be displayed in attributes tree Can be null to use the default value.
* @private
*/
/**
* @property {Function} _cbFn The callback function to be called after copy process
* @property {Object} _cbFn.report The copy report
* @private
*/
/**
* @property {Object} _scope The scope of the callback function. Can be null.
* @private
*/
/**
* @property {Boolean} [_checkByDefault=true] Indicates if the checkboxes should be checked or not.
* @private
*/
_checkByDefault: true,
/**
* Open a dialog box to select content view in a tree in order to copy content as a new content
* @param {Object} config The configuration options. Has the following parameters:
* @param {Ametys.cms.content.Content} config.content (required) The content to copied
* @param {String} [config.icon] The full path to icon (16x16) for the dialog box
* @param {String} [config.title] The title of the dialog box.
* @param {String} [config.helpMsg1] The message displayed at the top of the dialog box.
* @param {String} [config.helpMsg2] The message displayed at the bottom of the dialog box.
* @param {Number} [config.workflowInitActionId=111] The workflow action id for copy content as a new content
* @param {Number} [config.workflowEditActionId=2] The workflow action id for editing the target content
* @param {String} [config.viewName="default-edition"] The view name
* @param {String} [config.fallbackViewName="main"] The fallback view name to use if 'viewName' does not exist.
* @param {String} [config.viewMode="edition"] The view mode ('view' or 'edition')
* @param {Function} config.callback Callback function called after the dialog box is closed and the copy is processed.
* @param {Object} config.callback.report The copy report
* @param {Object} [config.scope] The callback scope.
*/
open: function(config)
{
if (!config.content)
{
Ametys.Msg.show({
title: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENTVALUES_ERROR_TITLE}}",
msg: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_NO_COPIED_CONTENT}}",
buttons: Ext.Msg.OK,
icon: Ext.Msg.ERROR
});
return;
}
this._cbFn = config.callback || Ext.emptyFn;
this._scope = config.scope;
this._content = config.content;
this._viewName = config.viewName || 'default-edition';
this._fallbackViewName = config.fallbackViewName || 'main';
this._viewMode = config.viewMode || 'edition';
this._workflowInitActionId = config.workflowInitActionId || 111;
this._workflowEditActionId = config.workflowEditActionId || 2;
if (config.checkByDefault != null)
{
this._checkByDefault = config.checkByDefault != "false"
}
// Check the user rights by retrieve the content type
var me = this;
var contentTypes = Ametys.cms.content.ContentTypeDAO.getContentTypes().createFiltered(function(contentType) {
return me._content.getTypes().indexOf(contentType.getId()) != -1
&& contentType.hasRight()
&& !contentType.isMixin()
&& !contentType.isAbstract();
});
if (contentTypes.count() != this._content.getTypes().length)
{
Ametys.Msg.show({
title: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENTVALUES_ERROR_TITLE}}",
msg: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_NO_RIGHT_MSG}}",
buttons: Ext.Msg.OK,
icon: Ext.Msg.WARNING
});
return;
}
this._delayedInitialize(config.iconCls || 'ametysicon-clipboard99',
config.title || "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_DIALOG_TITLE}}",
config.helpMsg1 || "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_DIALOG_HELPMESSAGE1}}" + "<b>'" + Ext.String.escapeHtml(this._content.getTitle()) + "'</b>.",
config.helpMsg2 || "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_DIALOG_HELPMESSAGE2}}");
this._tree.initialize({
contentId: this._content.getId(),
checkMandatory: true,
viewName: this._viewName,
viewMode: this._viewMode,
checkByDefault: this._checkByDefault
});
this._hideTree();
this._box.down('#content-title').setValue(this._content.getTitle() + "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_TITLE_SUFFIX}}");
this._box.show();
},
/**
* Creates the dialog box if it is not already created
* @param {String} iconCls The css classname to display an icon (with a glyph for example)
* @param {String} title The title of the dialog box.
* @param {String} helpMsg1 The message displayed at the top of the dialog box.
* @param {String} helpMsg2 The message displayed at the bottom of the dialog box.
* @private
*/
_delayedInitialize: function(iconCls, title, helpMsg1, helpMsg2)
{
if (!this._initialized)
{
this._tree = Ext.create('Ametys.plugins.cms.content.tree.ViewTree', {
height: 400,
scrollable: true
});
this._box = Ext.create('Ametys.window.DialogBox', {
title: title,
iconCls: iconCls,
width: 400,
scrollable: false,
layout: {
type: 'vbox',
align: 'stretch'
},
items: [{
xtype: 'component',
cls: 'a-text',
html: helpMsg1
},
{
xtype: 'container',
style: {
marginTop: '5px',
marginBottom: '5px'
},
items: {
xtype: 'textfield',
width: 340,
labelAlign: 'right',
labelWidth: 70,
cls: 'ametys',
name: 'contentTitle',
fieldLabel: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_TITLE_LABEL}}",
ametysDescription: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_TITLE_DESC}}",
itemId: 'content-title',
allowBlank: false,
msgTarget: 'side',
validator: function (value) {
var s = Ext.String.deemphasize(value);
if (/^([0-9\-]*|[0-9\-]+.*)[a-z].*$/i.test(s))
{
return true;
}
else
{
return "{{i18n plugin.cms:PLUGINS_CMS_HELPER_COPYCONTENT_TITLE_INVALID}}";
}
}
}
},
{
xtype: 'component',
cls: 'a-text',
html: helpMsg2,
hidden: true
},
this._tree
],
closeAction: 'hide',
defaultFocus: 'content-title',
selectDefaultFocus: true,
referenceHolder: true,
defaultButton: 'validate',
buttons : [{
reference: 'validate',
text: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_BTN_OK}}",
handler: Ext.bind(this._ok, this),
itemId: 'btn-ok'
}, {
text: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_BTN_CANCEL}}",
handler: Ext.bind(function() {this._box.close();}, this)
}, {
text: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_BTN_ADVANCED}}",
handler: Ext.bind(this._toggleTree, this),
itemId: 'btn-advanced'
}],
listeners: {
resize: {fn: this._onBoxResize, scope: this}
}
});
this._initialized = true;
}
else
{
this._box.setIconCls(iconCls);
this._box.setTitle(title);
this._box.items.getAt(0).update(helpMsg1);
this._box.items.getAt(2).update(helpMsg2);
}
},
/**
* Hide the tree.
* Also updating the show/hide button.
*/
_hideTree: function()
{
if (this._tree)
{
this._tree.hide();
this._box.items.get(2).hide();
var btn = this._box.down('#btn-advanced');
if (btn)
{
btn.setText("{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_BTN_ADVANCED}}");
}
}
},
/**
* Show the tree
* Also updating the show/hide button.
* @private
*/
_showTree: function()
{
this._tree.show();
this._box.items.get(2).show();
var btn = this._box.down('#btn-advanced');
if (btn)
{
btn.setText("{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_BTN_BASIC}}");
}
},
/**
* Hide/show the tree
* @private
*/
_toggleTree: function()
{
if (!this._tree.isVisible())
{
this._showTree();
this._box.items.get(2).show();
this._tree.selectAndFocusFirstNode();
}
else
{
this._hideTree();
this._box.items.get(2).hide();
this._box.down('#content-title').focus();
}
},
/**
* This function is called when validating the dialog box.
* Aggregate the parameters to make the server request.
* Run the duplication action on the server.
* @private
*/
_ok: function()
{
// Title
var titleField = this._box.down('#content-title');
if (!titleField.isValid())
{
return null;
}
if (this._tree.isInErrorState())
{
Ametys.Msg.show({
title: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_ERROR_TITLE}}",
msg: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_TREE_ERROR_MSG}}",
buttons: Ext.Msg.OK,
icon: Ext.Msg.ERROR
});
return;
}
var baseContentId = this._content.getId();
var newContentTitle = titleField.getValue();
var viewName = this._viewName;
var fallbackViewName = this._fallbackViewName;
var viewMode = this._viewMode;
// Add tree values if the tree is displayed.
var values = this._tree.isVisible() ? this._tree.getValues() : null;
var valuesToCopy = values ? Ext.JSON.encode(values) : null;
Ametys.data.ServerComm.callMethod({
role: "org.ametys.cms.workflow.copy.CopyContentClientInteraction",
methodName: "createContentByCopy",
parameters: [baseContentId, newContentTitle, valuesToCopy, viewName, fallbackViewName, viewMode, this._workflowInitActionId, this._workflowEditActionId],
callback: {
scope: this,
handler: this._okCb,
ignoreOnError: false
},
waitMessage: {
msg: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_WAIT_MSG}}",
target: this._box
},
errorMessage: {
category: Ext.getClassName(this) + '._ok'
}
});
},
/**
* Callback function called after copy is processed.
* Fires Ametys.message.Message.CREATED message for new created content
* @param {Object} response The JSON result from server :
* @param {String} response.mainContentId The id of main created content
* @param {String[]} response.contentIds The id of created contents
* @param {Object} response.report The copy report
* @param {Object[]} args The callback parameters passed to the {@link Ametys.data.ServerComm#callMethod} method
* @private
*/
_okCb: function(response, args)
{
if (response != null)
{
var contentIds = response.contentIds ? Object.values(response.contentIds) : [];
if (contentIds.length > 0 && contentIds[0] != '')
{
Ext.create("Ametys.message.Message", {
type: Ametys.message.Message.CREATED,
targets: {
id: Ametys.message.MessageTarget.CONTENT,
parameters: { ids: contentIds }
}
});
}
var report = response.report;
this._cbFn.call(this._scope, report);
this._box.close();
// CMS-5137 Open directly the main created content after copied
var mainContentId = response.mainContentId;
if (mainContentId)
{
Ametys.tool.ToolsManager.openTool('uitool-content', {id: mainContentId});
}
}
else
{
// In case of bad response, an error message is displayed thanks to the serverComm API
// but we still want to close the dialog box.
this._box.close();
}
},
/**
* Listener to the box resizing event.
* Used when the tree visibility is toggled.
* @param {Ext.window.Window} box The dialog box
* @param {Number} width The window's new width
* @param {Number} height The window's new height
* @private
*/
_onBoxResize: function(box, width, height)
{
box.center();
}
});