/*
* Copyright 2016 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 provides a widget to select a metadata.
*/
Ext.define('Ametys.cms.form.widget.SelectMetadata', {
extend: 'Ametys.form.AbstractQueryableComboBox',
/**
* @cfg {String} [metadataSetName=main] The desired metadataset name
*/
metadataSetName: 'main',
/**
* @cfg {String} [acceptedTypes] The accepted metadata types (comma separated).
* You can suffix types with "[ENUMERATED]" to only have enumerated of the given type (For example: STRING[ENUMERATED],LONG[ENUMERATED])
* You can suffix types with "[NOT-ENUMERATED]" to only have not enumerated of the given type
* Can be null to allow every types.
*/
/**
* @cfg {String|String[]} [contentTypes] The list of allowed content types, comma separated. If {@link #cfg-contentTypesField} is used, this will be ignored.
*/
/**
* @cfg {String} [contentTypesField] The relative path the content types
* field, to allow the list of metadata to be updated given the
* value of the content types field. To force the content types, use {@link #cfg-contentTypes} instead.
*/
/**
* @private
* @property {String} _contentTypesFieldName The property related to {@link #cfg-contentTypesField}
*/
/**
* @cfg {String} [metadataSetField] The relative path the content field, to
* allow the list of metadata to be updated given the value of the
* metadata set field
*/
/**
* @private
* @property {String} _metadataSetFieldName The property related to {@link #cfg-metadataSetField}
*/
/**
* @cfg {Boolean} [includeSubRepeaters=true] true to include the sub metadata of repeater metadata as well
*/
/**
* @cfg {String/Boolean} allowNoneEntry Set to 'true' to insert the 'None' entry in the list
*/
allowNoneEntry: false,
/**
* @cfg {String/Boolean} withLastModified Set to 'true' to include the last modified date into the list of metadata
*/
withLastModified: false,
/**
* @cfg {String/Boolean} withLastValidation Set to 'true' to include the last validation date into the list of metadata
*/
withLastValidation: false,
/**
* @cfg {String/Boolean} withResources Set to 'true' to include the resources as a content type
*/
withResources: false,
valueField: 'name',
displayField: 'fullLabel',
initComponent: function()
{
// workaround to handle multiple site on the widget side (but not on the storage side because the stored value is a JSON string)
// true by default
this.multiple = this.multiple != false && this.multiple != 'false';
this.contentTypes = Ext.isArray(this.contentTypes) ? this.contentTypes : (this.contentTypes ? this.contentTypes.split(',') : null);
this.acceptedTypes = Ext.isArray(this.acceptedTypes) ? this.acceptedTypes : (this.acceptedTypes ? this.acceptedTypes.split(',') : null);
this._contentTypesFieldName = this.contentTypesField || null;
this._metadataSetFieldName = this.metadataSetField || null;
this._includeSubRepeaters = this.includeSubRepeaters != false && this.includeSubRepeaters != "false"; // true by default
this.form.onRelativeFieldsChange([this._contentTypesFieldName, this._metadataSetFieldName], this, this._relativeFieldChange);
if (!Ext.isEmpty(this.contentTypes))
{
this.form.executeFormReady(this._relativeFieldChange, this);
}
this.callParent(arguments);
},
getComboBoxConfig: function()
{
var cfg = this.callParent(arguments);
cfg.queryMode = 'local';
return cfg;
},
getStore: function()
{
var me = this;
return Ext.create('Ext.data.Store', {
proxy: {
type: 'ametys',
plugin: 'cms',
url: 'common-attributes.json',
reader: {
type: 'json',
rootProperty: 'attributes'
},
extraParams: {
withFullLabel: true,
includeSubRepeaters: this.includeSubRepeaters || this.includeSubRepeaters == 'true',
withLastModified: this.withLastModified || this.allowNoneEntry == 'true',
withLastValidation: this.withLastValidation || this.allowNoneEntry == 'true',
withResources: this.withResources || this.withResources == 'true'
}
},
fields: [
{name: 'id', mapping: 'name'},
{name: 'name', mapping: 'name'},
{name: 'text', mapping: 'label', type: 'string'},
{name: 'fullLabel', mapping: 'fullLabel', type: 'string'},
{name: 'type', mapping: 'type'}
],
sortOnLoad: true,
sorters: [{property: 'fullLabel', direction:'ASC'}],
listeners: {
beforeload: {fn: this._onStoreBeforeLoad, scope: this},
load: {fn: this._onStoreLoad, scope: this}
}
});
},
/**
* Set the value after the store load
* @param {Ext.data.Store} store The store.
* @param {Ext.data.Model[]} records The loaded records.
* @param {Boolean} successful True if the operation was successful.
* @param {Ext.data.operation.Operation} The operation object used by proxy
* @private
*/
_onStoreLoad: function(store, records, successful, operation)
{
if (operation.aborted)
{
// the load has been canceled. Do nothing.
return;
}
var value = Ext.Array.from(this.getValue()),
store = this.combobox.getStore();
if (records && records.length > 0)
{
if (this.allowNoneEntry || this.allowNoneEntry == 'true')
{
// insert the "none" entry as the first entry in the store.
store.insert(0, {
name: '',
text: "{{i18n WIDGET_SELECTTYPEDMETADATA_FILTER_NONE}}",
fullLabel: "{{i18n WIDGET_SELECTTYPEDMETADATA_FILTER_NONE}}"
});
}
// filter out record that are not in the store anymore
value = Ext.Array.filter(value, function(entry) {
return store.getById(entry) != null
});
this.setValue(value);
}
},
/**
* Set the request parameters before loading the store.
* @param {Ext.data.Store} store The store.
* @param {Ext.data.operation.Operation} operation The Ext.data.Operation object that will be passed to the Proxy to load the Store.
* @private
*/
_onStoreBeforeLoad: function(store, operation)
{
var relativeFields = this.form.getRelativeFields([this._contentTypesFieldName, this._metadataSetFieldName], this),
contentTypesField = relativeFields[0],
metadataSetField = relativeFields[1];
if ((contentTypesField && contentTypesField.getValue() == null) || (metadataSetField && metadataSetField.getValue() == null))
{
return false; // cancel the load
}
var params = operation.getParams() || {};
operation.setParams(Ext.apply(params, {
ids: contentTypesField ? contentTypesField.getValue() : this.contentTypes,
viewName: metadataSetField ? metadataSetField.getValue() : this.metadataSetName,
acceptedTypes: this.acceptedTypes
}));
},
/**
* Listener called when the value of a relative field changes
*/
_relativeFieldChange: function()
{
if (this.combobox)
{
this.combobox.getStore().load();
}
}
});