Skip to content

Instantly share code, notes, and snippets.

@christocracy
Forked from anonymous/gist:977666
Created May 18, 2011 00:26
Show Gist options
  • Save christocracy/977765 to your computer and use it in GitHub Desktop.
Save christocracy/977765 to your computer and use it in GitHub Desktop.
Some ext code
/**
* @overview FeatureForm.js
* Collection of components related to Feature Forms
* @author Dave Lazar
*/
/**
* @namespace CCA.feature
*/
Ext.namespace('CCA.feature');
/**
* this is an Ext 2.2 override to allow us to use radio buttons with a name feature[foo]
* from forums: http://www.extjs.com/forum/showthread.php?p=210602#post210602
*/
Ext.DomQuery.matchers[2].re = /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?(?:"(.*?)"|'(.*?)'|(.*?)))?[\]\}])/;
Ext.override(Ext.form.Radio, {
getGroupValue : function(){
var c = this.getParent().child('input[name="'+this.el.dom.name+'"]:checked', true);
return c ? c.value : null;
},
toggleValue : function() {
if(!this.checked){
var els = this.getParent().select('input[name="'+this.el.dom.name+'"]');
els.each(function(el){
if(el.dom.id == this.id){
this.setValue(true);
}else{
Ext.getCmp(el.dom.id).setValue(false);
}
}, this);
}
},
setValue : function(v){
if(typeof v=='boolean') {
Ext.form.Radio.superclass.setValue.call(this, v);
} else {
var r = this.getParent().child('input[name="'+this.el.dom.name+'"][value="'+v+'"]', true);
if(r && !r.checked){
Ext.getCmp(r.id).toggleValue();
};
}
}
});
Ext.form.FileUploadField = Ext.extend(Ext.form.TextField, {
/**
* @cfg {String} buttonText The button text to display on the upload button (defaults to
* 'Browse...'). Note that if you supply a value for {@link #buttonCfg}, the buttonCfg.text
* value will be used instead if available.
*/
buttonText: 'Browse...',
/**
* @cfg {Boolean} buttonOnly True to display the file upload field as a button with no visible
* text field (defaults to false). If true, all inherited TextField members will still be available.
*/
buttonOnly: false,
/**
* @cfg {Number} buttonOffset The number of pixels of space reserved between the button and the text field
* (defaults to 3). Note that this only applies if {@link #buttonOnly} = false.
*/
buttonOffset: 3,
/**
* @cfg {Object} buttonCfg A standard {@link Ext.Button} config object.
*/
// private
readOnly: true,
/**
* @hide
* @method autoSize
*/
autoSize: Ext.emptyFn,
// private
initComponent: function(){
Ext.form.FileUploadField.superclass.initComponent.call(this);
this.addEvents(
/**
* @event fileselected
* Fires when the underlying file input field's value has changed from the user
* selecting a new file from the system file selection dialog.
* @param {Ext.form.FileUploadField} this
* @param {String} value The file value returned by the underlying file input field
*/
'fileselected'
);
},
// private
onRender : function(ct, position){
Ext.form.FileUploadField.superclass.onRender.call(this, ct, position);
this.wrap = this.el.wrap({cls:'x-form-field-wrap x-form-file-wrap'});
this.el.addClass('x-form-file-text');
this.el.dom.removeAttribute('name');
this.fileInput = this.wrap.createChild({
id: this.getFileInputId(),
name: this.name||this.getId(),
cls: 'x-form-file',
tag: 'input',
type: 'file',
size: 1
});
var btnCfg = Ext.applyIf(this.buttonCfg || {}, {
text: this.buttonText
});
this.button = new Ext.Button(Ext.apply(btnCfg, {
renderTo: this.wrap,
cls: 'x-form-file-btn' + (btnCfg.iconCls ? ' x-btn-icon' : '')
}));
if(this.buttonOnly){
this.el.hide();
this.wrap.setWidth(this.button.getEl().getWidth());
}
this.fileInput.on('change', function(){
var v = this.fileInput.dom.value;
if (this.isPermittedFileType(v)) {
this.setValue(v);
this.fireEvent('fileselected', this, v);
} else {
Ext.Msg.alert(App.STATUS_NOTICE, "Not an allowed upload filetype");
}
}, this);
},
// private
getFileInputId: function(){
return this.id+'-file';
},
// private
onResize : function(w, h){
Ext.form.FileUploadField.superclass.onResize.call(this, w, h);
this.wrap.setWidth(w);
if(!this.buttonOnly){
var w = this.wrap.getWidth() - this.button.getEl().getWidth() - this.buttonOffset;
this.el.setWidth(w);
}
},
// private
preFocus : Ext.emptyFn,
// private
getResizeEl : function(){
return this.wrap;
},
// private
getPositionEl : function(){
return this.wrap;
},
// private
alignErrorIcon : function(){
this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
},
isPermittedFileType : function(filename) {
var result = true;
var p = this.getPermissions(this.permittedExtensions) || [];
if (p.length > 0) {
result = p.indexOf(this.getFileExtension(filename)) != -1;
}
return result;
},
getPermissions : function (type) {
switch (type) {
case 'video':
case 'videos':
return ['avi', 'AVI', 'mpg','MPEG', 'mpeg', 'mp4', 'MP4', 'MPEG4','mpeg4', 'flv', 'FLV', 'wmv', 'WMV'];
break;
case 'image':
case 'images':
return ['jpg', 'JPG', 'JPEG', 'jpeg', 'GIF', 'gif', 'BMP', 'bmp', 'TIFF', 'tiff', 'PNG', 'png'];
break;
case 'audio':
return ['mp3', 'MP3', 'MPEG3', 'mpeg3', 'FLAC', 'flac', 'OGG', 'ogg', 'THEORA', 'theora'];
break;
case 'document':
case 'documents':
return ['doc', 'DOC', 'pdf', 'PDF', 'zip', 'ZIP', 'sit', 'SIT'];
break;
}
},
getFileExtension : function(filename) {
var result = null;
var parts = filename.split('.');
if (parts.length > 1) {
result = parts.pop();
}
return result;
}
});
Ext.reg('fileuploadfield', Ext.form.FileUploadField);
// globally set validation messages to appear on side of field
Ext.form.Field.prototype.msgTarget = 'side';
CCA.feature.TemplateHelper = function () {
return {
/**
* formatBody
* shrink the incoming string down to some reasonable size
* @param {String} input
*/
formatBody : function (input, size) {
return Ext.util.Format.ellipsis(input, size);
},
/**
* getMediaFields
* the incoming type here will be Audio, Video, Image, Slideshow or OtherMedia.. and this collection was prepped by the server...
* we also remove the file upload field since it makes no sense inside the nice template
* @param {Object} type
*/
getMediaFields : function(type) {
var fields = CCA.feature.MediaFieldMgr.get(type);
var filtered = [];
for (var i = 0, len = fields.length; i < len; i++) {
if(fields[i].xtype != 'fileuploadfield') {
filtered.push(fields[i])
}
}
return filtered;
},
/**
* getEntityFields
* this is used to provide a form without an upload field
* @param {Object} type
*/
getEntityFields : function(type) {
var fields = CCA.feature.EntityFieldMgr.get(type);
var filtered = [];
for (var i = 0, len = fields.length; i < len; i++) {
if(fields[i].xtype != 'fileuploadfield') {
filtered.push(fields[i])
}
}
return filtered;
},
/**
* getAllEntityFields
* this is used to list ALL the fields an entity has
* @param {Object} type
*/
getAllEntityFields : function(type) {
return CCA.feature.EntityFieldMgr.get(type);
},
/**
* formatEntityField
* for now return thumbs.. but we might have to just return the original link
* @param {Object} thumb
* @param {Object} original
*/
formatEntityField : function (thumb, original) {
return '<img src="'+thumb+'" />';
},
isLink : function (value) {
return (value === 'Link')? true : false;
},
isOtherMedia : function (value) {
return (value == 'OtherMedia')? true : false;
},
isCopyrightCleared : function(value) {
return (value)? App.t("y") : App.t("n");
},
isRepresentative : function(value) {
return (value)? App.t("y") : App.t("n");
},
isImage : function (type) {
return (type == 'Image')? true : false;
},
isAudio : function (type) {
return (type == 'Audio')? true : false;
},
isVideo : function (type) {
return (type == 'Video')? true : false;
},
isSlideshow : function (type) {
return (type == 'Slideshow')? true : false;
},
hasVideoThumb : function (values) {
return ( values.type == 'Video' && values.thumb != '')? true : false;
}
}
}();
/**
* CCA.feature.Form
* General feature form. produces form for all types of features.
* NOTE: Dealing with publications is a little weird... it is a serialized object, so it will not render
* without a little extra processing in the case where the Feature is a Publication...
*/
CCA.feature.Form = Ext.extend(Ext.form.FormPanel, {
/**
* @cfg {String} featureType [required]
*/
frame: false,
border: false,
autoScroll: true,
controller: 'feature',
// delete is handled through the grid at this time
actions: {
insert: 'insert',
update: 'update'
},
bodyStyle: 'padding:10px',
labelAlign: 'right',
// these come in for use through the constructor
record: null,
entities: null,
roles: null,
// private
initComponent: function(){
this.header = false;
// set css class (normally would place this above in @cfg props but doesn't work there??)
this.cls = 'cca-feature-form';
// build the form for a Generic Feature
this.items = this.build();
CCA.feature.Form.superclass.initComponent.call(this);
this.form.baseParams = {
"type": this.record.data.type
};
},
/**
* setValues
* In cases of publication, we need to strip off the publication key from data, and map it to the
* form fields which are not keyed off of the prefix 'feature', but 'feature_publication'
* Event Features send along a bunch of dates and times, which will need to be assigned carefully as well
* Look for key event_dates:[] to populate the Dates,Admissions, Locations
* @param {Object} data
*/
setValues: function(data){
/**
* take advantage of our utility singleton to ensure the content is displayed in the correct language
*/
var currLang = CCA.feature.Util.getContentLanguage();
//console.log('currLang for the form set values is ', currLang);
if (!this.controller) {
this.form.setValues(data);
return true;
}
values = {};
for (var key in data) {
switch (key) {
case 'lang':
// 'lang' key identifies a key of an array of translated strings.
// Ex: lang :{'en':{'title': 'English title'}, 'subtitle': 'English sub'},
// {'fr':{'title': 'Titre français'}, 'subtitle': 'Soustitre français'}}
for (var aLocale in data[key]) {
for (var aColumn in data[key][aLocale]){
elname = '[lang]['+aLocale+']['+aColumn+']';
values[this.controller + elname] = data['lang'][aLocale][aColumn];
}
}
break;
case 'publication':
// strip off all the keys inside publication and setup the form elements
for ( var p in data[key][currLang]) {
values['feature_publication['+p+']'] = data[key][currLang][p];
}
break;
case 'layout':
// strip off all the keys inside layout key and setup the form elements
for ( var p in data[key] ) {
// The editor in chief can add template from a different category
// If it's the case, we must add manually this template
// in the combo...
if (p=='template') {
var combo = Ext.getCmp('template_combo_' + data.id);
var keyFound = false;
Ext.each(combo.store.data.keys, function(k){
if (k == data[key][p])
keyFound = true;
});
if (!keyFound) {
Ext.each(this.record.data.layouts, function(l){
if (l[0] == data[key][p]) {
var TemplateRecord = Ext.data.Record.create([
{name: 'id', mapping: 'id'},
{name: 'name', mapping: 'name'}
]);
var newRecord = new TemplateRecord({
id: l[0],
name: l[1]
});
combo.store.add(newRecord);
}
});
}
}
values['feature_layout['+p+']'] = data[key][p];
}
break;
default:
values[this.controller + '[' + key + ']'] = data[key];
break;
}
}
this.form.setValues(values);
if (this.record.data.type == 'Event' || this.record.data.type == 'Series') {
var adm = this.findById('admission_'+this.record.data.id);
if (adm) {
var dates = adm.findByType('eventdate'); // <=== as many eventdate panels as were built need to be filled
if (dates) {
for (var i = 0, len = dates.length; i< len; i++) {
dates[i].setValues(this.record.data.event_dates[i]);
}
}
}
}
},
/**
* hasUnsavedData
* This method checks if any data in the form has changed since editing
* returns true if the data has changed.
* @param {Object} data
*/
hasUnsavedData: function(){
var formValues = this.form.getValues();
var currLang = CCA.feature.Util.getContentLanguage();
var hasChanged = false;
for (var key in this.record.data) {
switch (key) {
case 'lang':
/*
for (var aLocale in this.record.data[key]) {
for (var aColumn in this.record.data[key][aLocale]){
elname = '[lang]['+aLocale+']['+aColumn+']';
values[this.controller + elname] = this.record.data['lang'][aLocale][aColumn];
}
}
*/
break;
case 'publication':
for ( var p in this.record.data[key][currLang]) {
var formValue = formValues['feature_publication[' + p + ']'];
if (formValue != null && typeof(formValue) != 'undefined') {
var recValue = this.record.data[key][currLang][p];
if(recValue != null && typeof(recValue) != 'undefined') {
if (formValue != recValue)
hasChanged = true;
}
}
}
break;
case 'layout':
for ( var p in this.record.data[key] ) {
var formValue = formValues['feature_layout[' + p + ']'];
if (formValue != null && typeof(formValue) != 'undefined') {
var recValue = this.record.data[key][p];
if(recValue != null && typeof(recValue) != 'undefined') {
if (formValue != recValue)
hasChanged = true;
}
}
}
break;
case 'event_dates':
var startDate = Date.parseDate(formValues['feature[start_date]'], 'd/m/Y');
if(startDate == null || typeof(startDate) == 'undefined'){
startDate = '';
} else {
startDate = startDate.format('Y-m-d');
}
var endDate = Date.parseDate(formValues['feature[end_date]'], 'd/m/Y');
if(endDate == null || typeof(endDate) == 'undefined'){
endDate = '';
} else {
endDate = endDate.format('Y-m-d');
}
var startTime = formValues['feature[start_time]'];
var endTime = formValues['feature[end_time]'];
for ( var p in this.record.data[key] ) {
if(typeof(this.record.data[key][p]) == 'object'){
var sd = this.record.data[key][p]['sd'];
var st = this.record.data[key][p]['st'];
var ed = this.record.data[key][p]['ed'];
var et = this.record.data[key][p]['et'];
if(sd != null && typeof(sd) != 'undefined') {
if (sd != startDate)
hasChanged = true;
}
if(ed != null && typeof(ed) != 'undefined') {
if (ed != endDate)
hasChanged = true;
}
if(st != null && typeof(st) != 'undefined' &&
startTime != null && typeof(startTime) != 'undefined') {
if (st != startTime)
hasChanged = true;
}
if(et != null && typeof(et) != 'undefined' &&
endTime != null && typeof(endTime) != 'undefined') {
if (et != endTime)
hasChanged = true;
}
}
}
break;
default:
// there is an array for event dates
if(key == 'start_date' || key == 'start_time' ||
key == 'end_date' || key == 'end_time')
break;
var formValue = formValues['feature[' + key + ']'];
if(formValue != null && typeof(formValue) != 'undefined') {
var recValue = this.record.data[key];
if(recValue != null && typeof(recValue) != 'undefined') {
if (formValue != recValue)
hasChanged = true;
}
}
break;
}
}
/*
if (this.record.data.type == 'Event') {
var adm = this.findById('admission_'+this.record.data.id);
if (adm) {
var dates = adm.findByType('eventdate'); // <=== as many eventdate panels as were built need to be filled
if (dates) {
for (var i = 0, len = dates.length; i< len; i++) {
dates[i].setValues(this.record.data.event_dates[i]);
}
}
}
}
*/
return hasChanged;
},
/**
* save
*/
save: function() {
if (this.form.isValid()) {
if (this.record.data.type == 'Event' || this.record.data.type == 'Series') {
var adm = this.findById('admission_'+this.record.data.id);
if (adm) {
var dates = adm.findByType('eventdate');
if (dates) {
date_data = [];
for (var i = 0, len = dates.length; i< len; i++) {
date_data.push(dates[i].getValues());
dates[i].disableFields();
}
}
}
this.form.baseParams = {eventdates: Ext.encode(date_data)};
}
App.showSpinner('save');
this.form.submit({
url: this.controller + '/' + this.actions.update + '/' + this.record.data.id,
success: function(form, action){
/**
* once the form has been saved, turn on the date and time fields again
*/
if (this.record.data.type == 'Event' || this.record.data.type == 'Series') {
this.enableDateTime();
}
// update the record in the Grid, which is not re-loaded in case the panel is re-loaded after closing
this.record.beginEdit();
Ext.apply(this.record.data,action.result.data.feature);
this.record.endEdit();
this.record.commit();
App.processResponse(action);
},
failure: function(form, action){
/**
* once the form has been saved, turn on the date and time fields again
*/
if (this.record.data.type == 'Event' || this.record.data.type == 'Series') {
this.enableDateTime();
}
App.processResponse(action);
},
scope: this
});
} else {
App.setAlert(App.t('NOTICE'), "The Basic Form has a field not validating");
}
},
/**
* once the form has been saved, turn on the date and time fields again
*/
enableDateTime : function () {
var adm = this.findById('admission_'+this.record.data.id);
if (adm) {
var dates = adm.findByType('eventdate');
if (dates) {
for (var i = 0, len = dates.length; i< len; i++) {
dates[i].enableFields();
}
}
}
},
refreshTemplateCombo: function(checkBox) {
var combo = Ext.getCmp('template_combo_' + this.record.data.id);
var templateData = this.record.data.layouts;
function getTemplateDataSubset(start, end) {
var newArray = new Array();
for(i=start; i<=end; i++)
newArray.push(templateData[i]);
return newArray;
}
switch(checkBox.inputValue) {
case 1:
combo.store.loadData(getTemplateDataSubset(3, 5));
break;
case 2:
combo.store.loadData(getTemplateDataSubset(0, 2));
break;
case 3:
combo.store.loadData(getTemplateDataSubset(8, 9));
break;
case 4:
combo.store.loadData(getTemplateDataSubset(10, 11));
break;
case 5:
combo.store.loadData(getTemplateDataSubset(6, 7));
break;
}
combo.clearValue();
},
buildCategories: function () {
var obj = this;
var cid = this.record.data.category_id;
var items = [];
if (CCA.feature.Util.getCategorizations(this.record.data.content_language).getCount()) {
CCA.feature.Util.getCategorizations(this.record.data.content_language).each(function(c){
items.push({
xtype: 'radio',
fieldLabel: c.name,
name: 'feature[category_id]',
inputValue: c.id,
checked: (cid == c.id)? true : false,
listeners: {
'check': function(cb, isChecked){
if (isChecked && CCA.feature.Util.getAccountProfile() != 'profile.admin' && CCA.feature.Util.getAccountProfile() != 'profile.guest_writer')
obj.refreshTemplateCombo(cb);
},
'render': function(cb){
if (cb.checked && CCA.feature.Util.getAccountProfile() != 'profile.admin' && CCA.feature.Util.getAccountProfile() != 'profile.guest_writer')
obj.refreshTemplateCombo(cb);
}
}
});
}, this);
}
var radios = {
xtype: 'radiogroup',
labelSeparator: '',
columns: 3,
anchor: '99%',
items: items
}
var fieldset = {
xtype: 'fieldset',
labelWidth: 1,
layout: 'form',
title: App.t('category'),
autoHeight: true,
items: radios
}
return fieldset;
},
/**
* build
* provides the form where all the most general details of a Feature are displayed
*/
build: function(){
// these are all the roles that can be assigned to this puppy
// rolename is simply a convenience to map the type which is 'CollectionStory' to 'collection'
var roles = []; // store the 'id' and 'identifier' from the collection for the dropdown
var role_collection = CCA.feature.Util.getFeatureRoles(this.record.data.content_language).filter('prefix', this.record.data.rolename);
role_collection.each(function(r){
roles.push([r.id, r.label]);
});
var combo = {
xtype: 'rolecombo',
roles: roles,
emptyText: App.t('select_type')
};
var content = {
xtype: 'feature_content',
id: 'feature_content_' + this.record.data.id,
feature_id: this.record.data.id,
title: App.t('feature_content'),
data: this.record.data.paragraphs
}
this.record.data.layouts = [['layouts/_exhibitionA1.liquid', 'Exhibition A1'],
['layouts/_exhibitionA2.liquid', 'Exhibition A2'],
['layouts/_exhibitionA5.liquid', 'Exhibition A5'],
['layouts/_collectionB2.liquid', 'Collection B2'],
['layouts/_collectionB3.liquid', 'Collection B3'],
['layouts/_collectionB5.liquid', 'Collection B5'],
['layouts/_recommendsC2.liquid', 'CCA Recommends C2'],
['layouts/_recommendsC3.liquid', 'CCA Recommends C3'],
['layouts/_educationD1.liquid', 'Education & Events D1'],
['layouts/_educationD4.liquid', 'Education & Events D4'],
['layouts/_studycentreE2.liquid', 'Study Centre E2'],
['layouts/_studycentreE3.liquid', 'Study Centre E3']];
var tplStore = new Ext.data.SimpleStore({
fields: ['id', 'name'],
id: 0
});
if (CCA.feature.Util.getAccountProfile() == 'profile.admin' || CCA.feature.Util.getAccountProfile() == 'profile.guest_writer')
tplStore.loadData(this.record.data.layouts);
var templateCombo = {
xtype: 'combo',
hiddenName: 'feature_layout[template]',
hiddenId: Ext.id(),
emptyText: App.t('select_template'),
fieldLabel: App.t('template'),
id: 'template_combo_' + this.record.data.id,
mode: 'local',
store: tplStore,
valueField: 'id',
displayField: 'name',
triggerAction: 'all',
value: ''
}
var themeStore = new Ext.data.SimpleStore({
fields: ['id', 'name'],
data:[['blank','Default'], ['dark','Inverted'], ['accent','Accented-Green']],
id: 0
});
var themeCombo = {
xtype: 'combo',
hiddenName: 'feature_layout[theme]',
hiddenId: Ext.id(),
emptyText: App.t('select_theme'),
fieldLabel: App.t('theme'),
id: 'theme_combo_'+this.record.data.id,
mode: 'local',
store: themeStore,
triggerAction: 'all',
value: '',
valueField: 'id',
displayField: 'name',
autoWidth:false,
width:120
}
var contentStore = new Ext.data.SimpleStore({
fields: ['id', 'name'],
data: [['images','Images'], ['slideshow','SlideShow + anything'], ['video','Video + Images']],
id: 0
});
var contentCombo = {
xtype: 'combo',
hiddenName: 'feature_layout[content]',
hiddenId: Ext.id(),
emptyText: App.t('select_content'),
fieldLabel: App.t('content_kind'),
id: 'kind_combo_' + this.record.data.id,
mode: 'local',
store: contentStore,
valueField: 'id',
displayField: 'name',
triggerAction: 'all',
value: ''
}
var formItems = [
// <=== outer panel container is a column layout ultimately holding two panels
{
xtype: 'panel',
anchor: '99%',
border: false,
titleCollapse: true,
collapsible: true,
title: App.t('general'),
layout: 'column',
iconCls: 'icon-text-signature',
bodyStyle: 'padding: 5px',
items: [{
layout: 'form',
frame: true,
columnWidth: 0.5,
style: 'margin-right: 10px',
items: [{xtype: 'publishedurl', record: this.record},{
xtype: 'textfield',
fieldLabel: App.t('title'),
name: 'feature[title]',
allowBlank: false,
blankText: App.t('required_title'),
anchor: '99%'
}, {
xtype: 'textfield',
name: 'feature[subtitle]',
fieldLabel: App.t('subtitle'),
anchor: '99%'
}, {
xtype: 'textarea',
name: 'feature[synopsis]',
fieldLabel: App.t('synopsis'),
allowBlank: true,
grow: true,
growMax: 200,
anchor: '99%'
}, combo]
},{
layout: 'form',
columnWidth: 0.5,
frame: true,
anchor: '90%',
items: [{
xtype: 'fieldset',
title: 'Layout Settings',
autoHeight: true,
items: [templateCombo,themeCombo]
},this.buildCategories()]
}]// <== two columns closed
}];
// Add the date selector if necessary
// note that we can provide translations via the constructor
if(this.record.data.dateable) {
formItems.push(new CCA.feature.AdmissionForm({
id: 'admission_'+this.record.data.id,
title: App.t('event_dates'),
data: this.record.data.event_dates
}, this));
}
if(this.record.data.type == 'Publication') {
formItems.push(new CCA.feature.PublicationForm({title: App.t('publication')}));
}
formItems.push(content);
return formItems;
},
// private
onInsert: function(btn, ev){
App.showSpinner('saving');
this.form.submit({
url: this.controller + '/' + this.actions.insert
});
this.form.on('actioncomplete', function(form, action){
App.hideSpinner();
});
},
// onCancel
onCancel: function(btn, ev){
this.stopMonitoring();
if (this.useDialog == true) {
//this.dialog.hide();
this.dialog.close();
}
this.fireEvent('cancel', this);
},
/**
* onSave
* we are inside an Ext.form.FormPanel here, so we are not able to nest in a FormPanel
* so instead we will use Ajax to build up the Feature Content
* @param {Object} btn
* @param {Object} ev
*/
onSave : function (btn, ev) {
var text = Ext.getCmp('content_'+this.record.data.id);
var value = text.getValue();
if (value.length) {
App.showSpinner('save');
App.request({
url: this.controller + '/' + 'insert_content' + '/' + this.record.data.id,
method: 'POST',
// perhaps we are too liberal just allowing any old text to be created :)
params: {body: value},
success: function(res){
if (res.success == true) {
// get the dataview...
// add the resulting text to it...
text.setValue("");
}
},
scope: this
});
}
}
});
Ext.reg('featureform', CCA.feature.Form);
/**
* CCA.feature.EntityPanel
* note: these entity panels know about the feature they belong to via the feature_id
*/
CCA.feature.EntityPanel = Ext.extend(Ext.Panel, {
controller: 'feature',
actions: {
'reorder': 'reorder_entity',
'delete': 'delete_entity',
'load': 'load_entity'
},
/**
* @cfg {String} templateId
* default template id to retrieve from TemplateMgr
*/
templateId : 'feature_entity_template',
entity: null,
layout: 'form',
autoScroll: true,
frame: false,
// FeatureEntityType mapping to iconCls
iconMap: {
'Quote': 'icon-comments',
'DateAdmission': 'icon-date',
'Organizer': 'icon-shield',
'Sponsor': 'icon-money',
'Subject': 'icon-user',
'Item': 'icon-package',
'Credit': 'icon-award-gold',
'SeriesEpisode': 'icon-film-add'
},
/**
* @cfg {Integer} feature_id
* This entity's associated Feature id
*/
initComponent: function(){
this.title = App.t(this.entity.type);
this.iconCls = this.iconMap[this.entity.type];
// register this entity's fields with EntityFieldMgr singleton. this is to assist in XTemplate rendering.
CCA.feature.EntityFieldMgr.register(this.entity.type, this.entity.fields);
this.items = [this.buildView()];
var dragdrop = new RExt.DataView.Orderable({
listeners: {
order: function (view, startIndex,records) {
rs = [];
for (var i = 0, len = records.length; i < len; i++) {
rs.push({
id: records[i].data.id,
position: i+startIndex
});
}
App.request({
url: this.controller + '/' + this.actions.reorder,
params: {
data: Ext.encode(rs)
},
success: function (res) {
//console.log('Success', res);
},
failure: function (res) {
//console.log('bummer', res);
}
});
},
scope: this
}
});
this.plugins = dragdrop;
CCA.feature.EntityPanel.superclass.initComponent.call(this);
this.on('render', function () {
Ext.dd.ScrollManager.register(this.body);
}, this);
},
buildView: function(){
var store = new Ext.data.Store({
reader: new Ext.data.ArrayReader({
record: 'entity'
}, CCA.data.FeatureEntity),
data: this.entity.data || [],
baseParams: {},
sortInfo: {
field: 'position',
direction: 'ASC'
}
});
// make a ptr to fields. this is for the XTemplate function getFields
var fields = this.entity.fields;
var tools = new RExt.DataViewEditor({
actions: {
edit: 'edit_entity',
"delete": 'delete_entity',
load: 'load_entity'
},
listeners: {
'edit' : function(view, index, node, ev) {
this.onEdit(view, index, node, ev);
},
'delete' : function(view, index, node, ev) {
this.onDelete(view, index, node, ev);
}, scope: this
}
});
// create view
var view = new Ext.DataView({
id: this.id + '_view',
controller: this.controller,
store: store,
tpl: this.getTemplate(),
singleSelect: true,
overClass: 'x-grid3-row-over',
itemSelector: 'div.feature-entity',
dropZoneCls: 'dropzone',
selectedClass: 'x-grid3-row-selected',
emptyText: '<h2>No items added</h2><h3 class="icon-information r-icon-text">You may add any number of items.</h3>',
plugins: tools
});
return view;
},
getTemplate : function() {
return RExt.util.TemplateMgr.get((RExt.util.TemplateMgr.exists(this.entity.type + '_entity_template')) ? this.entity.type + '_entity_template' : this.templateId);
},
/**
* getView
* returns attached DataView
* @return {Ext.DataView}
*/
getView: function(){
return this.findByType(Ext.DataView).shift();
},
/**
* getValues
* returns array of added Entities
* @return {Hash}
*/
getValues: function(){
var rs = [];
this.getView().store.each(function(rec){
rs.push(rec.data.form);
});
return {
type: this.entity.type,
data: rs
};
},
/**
* onEdit
* 'edit' tool clicked on a row in a DataView
* @param {Object} view
* @param {Object} index
* @param {Object} node
* @param {Object} ev
*/
onEdit : function(view, index, node, ev) {
var record = view.store.getAt(index);
var fpanel = Ext.getCmp('entity_edit_'+this.feature_id);
fpanel.layout.activeItem.doEdit(this, record);
return;
},
/**
* onDelete
* remove a an entity from a Feature
* @param {Ext.DataView} view
* @param {Number} index
* @param {HTMLElement} node
* @param {Ext.EventObject} ev
*/
onDelete : function(view, index, node, ev) {
Ext.MessageBox.confirm('Confirm', 'Delete Entity?', function(btn) {
if (btn == 'yes') {
var rec = view.store.getAt(index);
App.request({
url: this.controller + '/' + this.actions['delete'] + '/' + rec.data.id,
method: 'POST',
success:function(res) {
view.store.remove(rec);
},
failure: function(res) {
App.setAlert('STATUS_ERROR', res.data.msg);
}
});
}
},this);
}
});
/**
* CCA.data.Insitution
* data.Record for Institution combo
*/
CCA.data.Institution = Ext.data.Record.create([
{ name: 'id'},
{ name: 'name'}
]);
/**
* CCA.feature.EntityEditForm
* allows us to edit existing entity records without uploader fields etc...
*/
CCA.feature.EntityEditForm = Ext.extend(Ext.form.FormPanel, {
controller: 'feature',
actions: {
insert: 'create_entity',
update: 'update_entity'
},
defaults: {
anchor: '96%'
},
feature_id: null,
fileUpload:true,
labelAlign: 'right',
frame: true,
border: false,
header: false,
/**
* @cfg {String} fieldPrefix
* the Rails-style prefix to append to each fieldname. eg: field_prefix[field_name]
* if a field-name comes in as "field_name", it'll be turned into field_prefix[field_name]
*/
fieldPrefix: 'feature_entity',
/**
* @cfg {String} entityType
* The AR STI type. will be added to form post
*/
entityType: null,
monitorValid: true,
sender: null,
record: null,
entity: null,
// private initComponent,
initComponent: function(){
// puke if no entity object was provided.
if (typeof(this.entity) != 'object') {
return alert("Error -- CCA.feature.EntityEditForm -- @cfg param 'entity' is required and must be an object");
}
// set cfg params
this.title = this.entity.title;
this.entityType = this.entity.type;
/**
* build form-fields
* append "feature_entity" prefix to each field so each fields is like feature_entity[field_name]
* thing is, we'd also like to control the layout of the form better, so we should look for
* layout setting inside the entity and respect that as well???
*/
this.items = [];
for (var n = 0, len = this.entity.fields.length; n < len; n++) {
var field = Ext.apply({
model: this.entity.type
}, this.entity.fields[n]); // <-- clone the field.
if (typeof(field.hiddenName) != 'undefined') {
field.hiddenName = "feature_entity[" + field.hiddenName + ']';
}
else {
field.name = "feature_entity[" + field.name + ']';
}
this.items.push(field);
}
this.buttons = [{
id: this.id+'_btnSave',
text: 'Save',
handler: this.onSave,
formBind: (this.monitorValid) ? true : false,
scope: this
},{
id: this.id+'_btnUpdate',
text: 'Update',
handler: this.onUpdate,
formBind: (this.monitorValid) ? true : false,
scope: this
},{
id: this.id+'_btnCancel',
text: 'Cancel',
handler: this.onCancel,
scope: this
}];
// super
CCA.feature.EntityEditForm.superclass.initComponent.call(this);
// add "entity_type" to BasicForm's baseParams hash. BasicForm is created *after* super
this.form.baseParams = {
entity_type: this.entity.type
};
// remove this.entity -- we're done with it. no point keeping duplicate data and fattening the object.
delete this.entity;
this.hideButton(this.id+'_btnUpdate');
},
/**
* getEntityType
* returns the AR class of this FeatureEntity
* @return {String} entityType
*/
getEntityType: function(){
return this.entityType;
},
setRecord : function (record) {
this.record = record;
},
setSender : function (sender) {
this.sender = sender;
},
getRecord : function () {
return this.record;
},
getSender : function () {
return this.sender;
},
/**
* doEdit
* called from the EntityEditForm this provides the form with some crucial information
* - the sender panel, giving us the dataview and it's store and template etc.
* - a data record that can be displayed for editing
* @param {CCA.feature.EntityPanel} sender
* @param {Ext.data.Record} record
*/
doEdit : function (sender, record) {
this.setRecord(record);
this.setSender(sender);
this.setValues(record);
this.hideButton(this.id+'_btnSave');
this.showButton(this.id+'_btnUpdate');
},
setValues : function(rec) {
/**
* Entity Forms have some exceptions where combo boxes need a record to work on
*/
var icombo = this.form.findField(this.formName + '[institution_id]');
if (icombo) {
icombo.store.add(new icombo.store.recordType({
id: rec.data.institution_id,
name: rec.data.institution.name
}));
}
var author_combo = this.form.findField(this.formName + '[person_id]');
if (author_combo) {
author_combo.store.add(new author_combo.store.recordType({
id: rec.data.person_id,
name: rec.data.person.first + ' ' + rec.data.person.last
}));
}
if (!this.formName) {
this.form.setValues(rec.data);
return true;
}
values = {};
if (this.formName) {
for (var key in rec.data) {
values[this.formName + '[' + key + ']'] = rec.data[key];
}
}
this.form.setValues(values);
},
/**
* onSave
*/
onSave: function(btn, ev){
if (this.form.isValid()) {
var entity_accordion = Ext.getCmp('entity_panel_' + this.feature_id);
var panel = entity_accordion.layout.activeItem;
App.showSpinner(App.t("saving"));
this.form.submit({
url: this.controller + '/' + this.actions.insert + '/' + this.feature_id,
success: function(form, action) {
var dv = panel.getView();
var r = dv.store.add(new dv.store.recordType(action.result.data.feature_entity));
this.form.reset();
App.processResponse(action);
},
failure: function(form, action){
App.processResponse(action);
},
scope: this
});
}
},
/**
* onUpdate
* send changes to the entity record to the dataview
* @param {Object} btn
* @param {Object} ev
*/
onUpdate : function (btn, ev) {
if (this.isValid()) {
App.showSpinner(App.t("update"));
this.form.submit({
url: this.controller + '/' + this.actions.update + '/' + this.record.data.id,
success: function(form, action) {
/**
* get the view, the index of the record, remove it, add a new record...refesh
* this is due to a problem encountered with XTemplate and nested data keys
*/
var dv = this.sender.getView();
var idx = dv.store.indexOf(this.record);
dv.store.remove(this.record);
var r = dv.store.insert(idx, new dv.store.recordType(action.result.data.feature_entity));
dv.refresh();
/**
* Zero out the form for the next usage
*/
this.sender = null;
this.form.reset();
this.hideButton(this.id+'_btnUpdate');
this.showButton(this.id+'_btnSave');
App.processResponse(action);
},
failure: function(form, action){
App.processResponse(action);
},
scope: this
});
}
},
/**
* onCancel
* cancel and reset the form
* @param {Object} btn
* @param {Object} ev
*/
onCancel : function (btn, ev) {
this.form.reset();
this.showButton(this.id+ '_btnSave');
this.hideButton(this.id+'_btnUpdate');
this.hideButton(this.id+'_cancel');
},
/**
* isValid
* if we do not have a record, then this form cannot possibly be submitted
*/
isValid : function () {
if (typeof this.record == 'undefined') {
App.setStatus(App.t(App.STATUS_ERROR), App.t('select_media'));
return false;
}
return this.form.isValid();
},
/**
* getButtons
* return the buttons we assigned to this panel in the center region
*/
getButtons : function () {
return this.buttons;
},
showButton: function (id) {
var buttons = this.getButtons();
for (var i = 0, len = buttons.length; i < len; i++) {
if (buttons[i].id == id) {
buttons[i].show();
}
}
},
hideButton: function (id) {
var buttons = this.getButtons();
for(var i = 0, len = buttons.length; i< len; i++) {
if (buttons[i].id == id) {
buttons[i].hide();
}
}
}
});
/**
* CCA.feature.MediaPanel
* note: these entity panels know about the feature they belong to via the feature_id
*/
CCA.feature.MediaPanel = Ext.extend(Ext.Panel, {
controller: 'feature',
actions: {
'reorder': 'reorder_media',
'delete': 'delete_media',
'load': 'load_media'
},
/**
* @cfg {String} templateId
* default template id to retrieve from TemplateMgr
*/
templateId : 'feature_media_template',
media: null,
layout: 'fit',
frame: false,
border: false,
autoScroll: true,
iconMap: {
'Image': 'icon-image',
'Audio': 'icon-ipod',
'Video': 'icon-film',
'Slideshow': 'icon-pictures',
'OtherMedia': 'icon-user',
'Link': 'icon-link'
},
/**
* @cfg {Integer} feature_id
* This entity's associated Feature id
*/
initComponent: function(){
this.title = this.media.type;
this.iconCls = this.iconMap[this.media.type];
// register this media's fields with MediaFieldMgr singleton. this is to assist in XTemplate rendering.
//CCA.feature.MediaFieldMgr.register(this.media.type, this.media.fields);
//console.info('registered the media type %s and fields %o', this.media.type, this.media.fields);
this.items = this.buildView();
var dragdrop = new RExt.DataView.Orderable({
listeners: {
order: function (view, startIndex,records) {
rs = [];
for (var i = 0, len = records.length; i < len; i++) {
rs.push({
id: records[i].data.id,
position: i+startIndex
});
}
App.request({
url: this.controller + '/' + this.actions.reorder,
params: {
data: Ext.encode(rs)
},
success: function (res) {
//console.log('Success', res);
},
failure: function (res) {
//console.log('bummer', res);
}
});
},
scope: this
}
});
this.plugins = dragdrop;
CCA.feature.MediaPanel.superclass.initComponent.call(this);
this.on('render', function() {
Ext.dd.ScrollManager.register(this.body);
}, this);
},
buildView: function() {
var store = new Ext.data.Store({
reader: new Ext.data.ArrayReader({
record: 'media'
}, CCA.data.FeatureMedia),
data: this.media.data || [],
baseParams: {},
sortInfo: {
field: 'position',
direction: 'ASC'
}
});
// make a ptr to fields. this is for the XTemplate function getFields
var fields = this.media.fields;
var tools = new RExt.DataViewEditor({
actions: {
edit: 'edit_media',
"delete": 'delete_media',
load: 'load_media'
},
listeners: {
'edit' : function(view, index, node, ev) {
this.onEdit(view, index, node, ev);
},
'delete' : function(view, index, node, ev) {
this.onDelete(view, index, node, ev);
},
scope: this
}
});
// create view
var view = new Ext.DataView({
controller: this.controller,
store: store,
tpl: this.getTemplate(),
singleSelect: true,
overClass: 'x-grid3-row-over',
itemSelector: 'div.feature-media',
dropZoneCls: 'dropzone',
selectedClass: 'x-grid3-row-selected',
emptyText: '<h2>No items added</h2><h3 class="icon-information r-icon-text">You may add any number of items.</h3>',
plugins: tools
});
return [view];
},
getTemplate : function() {
return RExt.util.TemplateMgr.get((RExt.util.TemplateMgr.exists(this.media.type + '_media_template')) ? this.media.type + '_media_template' : this.templateId);
},
/**
* getView
* returns attached DataView
* @return {Ext.DataView}
*/
getView: function(){
return this.findByType(Ext.DataView).shift();
},
/**
* getValues
* returns array of added Entities
* @return {Hash}
*/
getValues: function(){
var rs = [];
this.getView().store.each(function(rec){
rs.push(rec.data.form);
});
return {
type: this.media.type,
data: rs
};
},
/**
* onEdit
* 'edit' tool clicked on a row in a DataView
* show the correct card in the editing form card layout...
* @param {Object} view
* @param {Object} index
* @param {Object} node
* @param {Object} ev
*/
onEdit : function(view, index, node, ev) {
var record = view.store.getAt(index);
var fpanel = Ext.getCmp('media_edit_'+this.feature_id);
fpanel.layout.activeItem.doEdit(this, record);
return;
},
/**
* onDelete
* remove a an entity from a Feature
* @param {Ext.DataView} view
* @param {Number} index
* @param {HTMLElement} node
* @param {Ext.EventObject} ev
*/
onDelete : function(view, index, node, ev) {
Ext.MessageBox.confirm(App.t('confirm'), App.t('delete_media'), function(btn) {
if (btn == 'yes') {
var rec = view.store.getAt(index);
App.request({
url: this.controller + '/' + this.actions['delete'] + '/' + rec.data.id,
method: 'POST',
success:function(res) {
view.store.remove(rec);
/**
* we are smart enough to reset the current panel??? Is this too jarring
* when you switch context from a form panel to a Dataview action like delete
*/
//if (view.ownerCt.xtype == 'slideshow_panel') {
var fpanel = Ext.getCmp('media_edit_' + this.feature_id);
var fm = fpanel.layout.activeItem.form.reset();
//}
},
failure: function(res) {
App.setAlert('STATUS_ERROR', res.data.msg);
},
scope: this
});
}
},this);
}
});
/**
* CCA.feature.MediaEditForm
* A base-class for all FeatureMedia forms.
* Form constructor must be provided with a FeatureMedia object containing title and fields array.
*/
CCA.feature.MediaEditForm = Ext.extend(Ext.form.FormPanel, {
controller: 'feature',
actions: {
insert: 'create_media',
update: 'update_media'
},
defaults: {
anchor: '95%'
},
feature_id: null,
fileUpload: true,
labelAlign: 'right',
labelWidth: 150,
frame: true,
border: false,
header: false,
buttons: null,
autoScroll: true,
monitorValid: true,
reset: true,
/**
* @cfg {String} fieldPrefix
* the Rails-style prefix to append to each fieldname. eg: field_prefix[field_name]
* if a field-name comes in as "field_name", it'll be turned into field_prefix[field_name]
*/
fieldPrefix: 'feature_media',
/**
* @cfg {String} mediaType
* The AR STI type. will be added to form post
*/
mediaType: null,
media: null,
sender: null,
record: null,
// private initComponent,
initComponent: function(){
// puke if no entity object was provided.
if (typeof(this.media) != 'object') {
return alert("Error -- CCA.feature.MediaEditForm -- @cfg param 'media' is required and must be an object");
}
// set cfg params
this.title = this.media.title;
if (this.title == null) { //added so there's no blank titles
this.title = App.t('slideshow_details'); //this shouldn't be hard-coded but hey
}
/**
* build form-fields
* append "feature_media" prefix to each field so each fields is like feature_media[field_name]
* thing is, we'd also like to control the layout of the form better, so we should look for
* layout setting inside the entity and respect that as well???
*/
this.items = [];
for (var n = 0, len = this.media.fields.length; n < len; n++) {
var field = Ext.apply({
model: this.media.type
}, this.media.fields[n]); // <-- clone the field.
if (typeof(field.hiddenName) != 'undefined') {
field.hiddenName = "feature_media[" + field.hiddenName + ']';
}
else {
field.name = "feature_media[" + field.name + ']';
}
this.items.push(field);
}
this.buttons = [{
id: this.id+'_btnSave',
text: 'Save',
handler: this.onSave,
formBind: (this.monitorValid) ? true : false,
scope: this
},{
id: this.id+'_btnUpdate',
text: 'Update',
handler: this.onUpdate,
formBind: (this.monitorValid) ? true : false,
scope: this
},{
id: this.id+'_btnCancel',
text: 'Cancel',
handler: this.onCancel,
scope: this
}];
// add a toolbar to the slideshow meta data panel for use in that form, it is special
if (this.media.type == 'Slideshow') {
this.tbar = [{
xtype: 'tbtext',
text: 'Create Slideshow'
},'-',{
text: 'New',
handler: this.onNew,
scope: this
}];
}
CCA.feature.MediaEditForm.superclass.initComponent.call(this);
// add "media_type" to BasicForm's baseParams hash. BasicForm is created *after* super
this.form.baseParams = {
media_type: this.media.type
};
// remove this.entity -- we're done with it. no point keeping duplicate data and fattening the object.
delete this.media;
this.hideButton(this.id+'_btnUpdate');
this.on('render', function () {
var tb = this.getTopToolbar();
if (tb) {
tb.hide();
}
},this);
},
setRecord : function (record) {
this.record = record;
},
setSender : function (sender) {
this.sender = sender;
},
getRecord : function () {
return this.record;
},
getSender : function () {
return this.sender;
},
// as well as cleaning up the meta data form.. we need to reset the slideshow_edit too
onNew : function (btn, ev) {
var fpanel = Ext.getCmp('media_edit_' + this.feature_id);
var fm = fpanel.layout.activeItem.reset();
},
/**
* doEdit
* called from the MediaEditForm this provides the form with some crucial information
* - the sender panel, giving us the dataview and it's store and template etc.
* - a data record that can be displayed for editing
* @param {CCA.feature.MediaPanel} sender
* @param {Ext.data.Record} record
*/
doEdit : function (sender, record) {
this.setRecord(record);
this.setSender(sender);
this.setValues(record);
this.hideButton(this.id+'_btnSave');
this.showButton(this.id+'_btnUpdate');
/** okay... so the last field in the form is always the file uploader... and the Ext.BasicForm.findField() function
* does not seem to have much luck in finding fields like feature_media[item], so we hack the find... and for updates
* we set the allowBlank property to be TRUE, hence you do not HAVE to upload a new image or other media on UPDATE
*/
var last = this.form.items.getCount();
var field = this.form.findField(last-1);
if (field.xtype =='fileuploadfield') {
field.allowBlank = true;
}
},
/**
* onUpdate
* pressed into service to update a media record delivered from a media panel
* @param {Object} btn
* @param {Object} ev
*/
onUpdate : function (btn, ev) {
if (this.isValid()) {
App.showSpinner(App.t('update'));
var media_accordion = Ext.getCmp('media_panel_' + this.feature_id);
var panel = media_accordion.layout.activeItem;
this.form.submit({
url: this.controller + '/' + this.actions.update + '/' + this.record.data.id,
success: function(form, action) {
/**
* get the view, the index of the record, remove it, add a new record...refesh
* this is due to a problem encountered with XTemplate and nested data keys
*/
var dv = panel.getView();
var idx = dv.store.indexOf(this.record);
dv.store.remove(this.record);
this.record = new dv.store.recordType(action.result.data);
dv.store.insert(idx, this.record);
/**
* Zero out the form for the next usage
* NOTE: This is only for the forms unlike Slideshow
*/
if (this.reset) {
this.record = null;
this.sender = null;
this.form.reset();
this.hideButton(this.id+'_btnUpdate');
this.showButton(this.id+'_btnSave');
}
// turn the fileuploadfield back on for validation in case a save is done next.
var last = this.form.items.getCount();
var field = this.form.findField(last-1);
if(field.xtype == 'fileuploadfield') {
field.allowBlank = false;
}
App.processResponse(action);
},
failure: function(form, action){
App.processResponse(action);
},
scope: this
});
}
},
/**
* onSave
*/
onSave: function(btn, ev){
if (this.form.isValid()) {
var media_accordion = Ext.getCmp('media_panel_' + this.feature_id);
var panel = media_accordion.layout.activeItem;
App.showSpinner(App.t("saving"));
this.form.submit({
url: this.controller + '/' + this.actions.insert + '/' + this.feature_id,
success: function(form, action) {
var dv = panel.getView();
var record = new dv.store.recordType(action.result.data.feature_media);
dv.store.add(record);
/**
* SlideshowEdit is a special case. We have to deal with those a little different
*/
if (this.form.xtype != 'slideshow_form') {
this.form.reset();
} else {
this.fireEvent('created', this, record);
}
App.processResponse(action);
},
failure: function(form, action){
App.processResponse(action);
},
scope: this
});
}
},
/**
* onCancel
* cancel and reset the form but with exception for more complicated slideshow form
* @param {Object} btn
* @param {Object} ev
*/
onCancel : function (btn, ev) {
if (this.form.xtype != 'slideshow_form') {
this.form.reset();
} else {
var fpanel = Ext.getCmp('media_edit_' + this.feature_id); //copied from onNew for panel toolbar
var fm = fpanel.layout.activeItem.reset();
};
this.showButton(this.id+ '_btnSave');
this.hideButton(this.id+'_btnUpdate');
this.hideButton(this.id+'_cancel');
},
/**
* getMediaType
* returns the AR class of this FeatureMedia
* @return {String} mediaType
*/
getMediaType: function(){
return this.mediaType;
},
/**
* isValid
* if we do not have a record, then this form cannot possibly be submitted
*/
isValid : function () {
if (typeof this.record == 'undefined') {
App.setStatus(App.t(App.STATUS_ERROR), App.t('select_media'));
return false; // <=== you did not actually click on some media to edit.... so bug off...
}
return this.form.isValid();
},
/**
* setValues
* handed a record, this will setup the form with the provided values
* @param {Ext.data.Record} rec
*/
setValues : function(rec) {
// if a person combo is found on a media form, pre-populate it with the record's data
var author_combo = this.form.findField(this.formName + '[person_id]');
if (author_combo) {
author_combo.store.add(new author_combo.store.recordType({
id: rec.data.person_id,
name: rec.data.person.first + ' ' + rec.data.person.last
}));
}
if (!this.formName) {
this.form.setValues(rec.data);
return true;
}
values = {};
if (this.formName) {
for (var key in rec.data) {
values[this.formName + '[' + key + ']'] = rec.data[key];
}
}
this.form.setValues(values);
},
/**
* getButtons
* return the buttons we assigned to this panel in the center region
*/
getButtons : function () {
return this.buttons;
},
showButton: function (id) {
var buttons = this.getButtons();
for (var i = 0, len = buttons.length; i < len; i++) {
if (buttons[i].id == id) {
buttons[i].show();
}
}
},
hideButton: function (id) {
var buttons = this.getButtons();
for(var i = 0, len = buttons.length; i< len; i++) {
if (buttons[i].id == id) {
buttons[i].hide();
}
}
}
});
/**
* Slideshows are slightly different from ordinary Media Panels
* - we hack the onAdd function to show the CCA.slideshow.Manager window instead of a
* regular CCA.feature.MediaPanel
*/
CCA.feature.SlideshowPanel = Ext.extend(CCA.feature.MediaPanel, {
controller: 'feature',
actions: {
create: 'create_media',
'delete': 'delete_media',
deleteall: 'delete_all_media',
reorder: 'reorder_media'
},
initComponent : function () {
CCA.feature.SlideshowPanel.superclass.initComponent.call(this);
/*this.tbar.push({
xtype: 'button',
text: 'Delete All',
iconCls: 'icon-delete',
handler: this.onDeleteAll,
scope: this
});
this.tbar.push('-');
*/
},
onDeleteAll : function (btn, ev) {
if (this.getView().store.getCount()) {
Ext.MessageBox.confirm('Confirm', 'Delete ALL Slideshows?', function(btn){
if (btn == 'yes') {
// Remove All records from this store.. and tell the server to remove
// all rows from FeatureMedia where the type is Slideshow and the feature_id is blah
this.getView().store.removeAll();
App.request({
url: this.controller + '/' + this.actions['deleteall'] + '/' + this.feature_id,
method: 'POST',
params: {
media_type: 'Slideshow'
},
success: function(res){
if (res.success == true) {
//console.log('Removed all Slideshows from Server!');
}
},
scope: this
});
}
}, this);
}
},
/**
* onAdd
* first we establish the PK of a new Slideshow in the FeatureMedia table,
* and once we have that PK, we can show the SlideshowManager with both the FeatureID and SlideshowID
* @param {Object} btn
* @param {Object} ev
*/
onAdd : function (btn, ev) {
//console.log('creating a new slideshow');
// prompt the user to create a new slideshow, with a title
Ext.Msg.prompt('New Slideshow', 'Title', function(btn, text){
if (btn == 'ok'){
App.showSpinner('Saving'); // <-- showSpinner
App.request({
url: this.controller + '/' + this.actions.create,
method: "POST",
params : {
"feature_media[title]" : text,
"feature_media[feature_id]" : this.feature_id,
"media_type" : 'Slideshow'
},
success : function(res) {
// create a record for this entry, and then add it to the existing records
// in the store, so that it becomes visible...
var view = this.getView();
var record = new view.store.recordType(res.data.feature_media);
view.store.add(record);
App.hideSpinner(); // <-- hideSpinner
},
failure : function(res) {
App.hideSpinner(); // <-- hideSpinner
},
scope: this
},this);
}
},this);
},
/**
* onEdit
* a click on a slideshow in the panel, will swing into view the slideshow manager, provided with the record of the click
* @param {Ext.DataView} view
* @param {Number} index
* @param {HTMLElement} node
* @param {Ext.EventObject} ev
*/
onEdit : function (view, index, node, ev) {
//console.log('editing an existing slideshow');
var record = view.store.getAt(index);
var fpanel = Ext.getCmp('media_edit_'+this.feature_id);
//var mp = Ext.getCmp('media_panel_' + this.feature_id);
//mp.collapse();
fpanel.layout.activeItem.doEdit(this, record);
}
});
/***
* CCA.feature.Roles
* A drop down we create that provides the roles available for a Feature
* @param {Object} param
*/
CCA.feature.Roles = Ext.extend(Ext.form.ComboBox, {
shadow: false,
tabIndex: 1,
hiddenId: Ext.id(),
hiddenName: 'feature[role_id]',
fieldLabel: App.t('type'),
mode: 'local',
triggerAction: 'all',
valueField: 'id',
displayField: 'identifier',
forceSelection: true,
roles: null,
listWidth: 200,
initComponent: function(){
this.on('select', function () {
});
this.store = new Ext.data.SimpleStore({
fields: ['id','identifier'],
data: this.roles,
id: 0
}, this);
CCA.feature.Roles.superclass.initComponent.call(this);
},
/***
* setTypeId
* @param {Integer} type_id
*/
setTypeId: function(id){
this.type_id = id;
this.store.baseParams.type_id = id;
},
reset: function(){
CCA.feature.Roles.superclass.reset.call(this);
this.lastQuery = null;
this.store.removeAll();
},
getForm: function(){
return Ext.getCmp(this.form_id);
}
});
Ext.reg('rolecombo', CCA.feature.Roles);
/***
* CCA.feature.Admission
* @param {Object} param
*/
CCA.feature.Admission = Ext.extend(Ext.form.ComboBox, {
emptyText: App.t('select_admission'),
shadow: false,
tabIndex: 1,
hiddenId: Ext.id(),
hiddenName: 'feature[admission_id]',
allowBlank: false,
mode: 'local',
triggerAction: 'all',
valueField: 'id',
displayField: 'name',
forceSelection: true,
width: 200,
listWidth: 200,
initComponent: function(){
this.store = new Ext.data.SimpleStore({
fields: ['id', 'name'],
data: CCA.feature.Util.getAdmission(),
id: 0
});
// super
CCA.feature.Admission.superclass.initComponent.call(this);
},
/***
* setAdmissionId
* @param {Integer} admission_id
*/
setAdmissionId: function(id){
this.admission_id = id;
this.store.baseParams.admission_id = id;
},
reset: function(){
CCA.feature.Admission.superclass.reset.call(this);
this.lastQuery = null;
},
getForm: function(){
return Ext.getCmp(this.form_id);
}
});
Ext.reg('admission', CCA.feature.Admission);
/**
* CCA.feature.AdmissionForm
* A panel dedicated to collecting startdate, enddate, price and location fields for Events
* We have to provide for the client to add MULTIPLE dates per event, so this is done with an
* Add button on the form itself, or perhaps a little tool plugin...
*/
CCA.feature.AdmissionForm = Ext.extend(Ext.Panel, {
feature_id: null,
iconCls: 'icon-date',
layout: 'form',
title: '',
border: false,
style: 'margin-top: 10px;',
bodyStyle: 'padding: 5px',
anchor: '99%',
collapsible: true,
titleCollapse: true,
collapsed: true,
tools: [{
id: 'plus',
qtip: 'Add more event date fields.',
handler: function(event, toolEl, panel) {
panel.insert(panel.items.length-1, {xtype: 'eventdate'});
panel.doLayout();
},
scope: this
}],
data: null,
initComponent: function(){
this.items = this.build();
CCA.feature.AdmissionForm.superclass.initComponent.call(this);
},
/**
* build
* will return an array of Ext.form elements and Ext.DatePicker elements as needed
* If we are provided with data... we should create as many eventdate panels as needed to display them all
*/
build: function(){
// first we add all the needed eventdate panels
var panels = [];
if (this.data instanceof Array) {
for (var i = 0, len = this.data.length; i < len; i++) {
panels.push({
xtype: 'eventdate'
});
}
} else {
panels.push({xtype: 'eventdate'});
}
// next we add the admission, location and duration objects.
var fs = {
xtype: 'fieldset',
autoHeight: true,
anchor: '90%',
style: 'margin-bottom:5px; margin-left: 15px;',
items: [
new CCA.feature.Admission({
emptyText: App.t('select_admission'),
fieldLabel: App.t('admission')
}),{
xtype: 'textfield',
fieldLabel: App.t('location'),
name: 'feature[location]',
allowBlank: true,
blankText: App.t('event_location')
},{
xtype: 'textfield',
fieldLabel: App.t('duration'),
name: 'feature[duration]',
allowBlank: true,
blankText: App.t('event_duration')
}]
};
panels.push(fs);
return panels;
}
});
/***
* CCA.feature.Institution
* @param {Object} param
*/
CCA.feature.Institution = Ext.extend(RExt.form.ComboBoxAdd, {
domain: null,
// id of the CompanyForm available via Ext.getCmp
form_id: 'institution_form',
company_id: null,
controller: 'institution',
actions: {
load: 'search',
insert: 'insert'
},
// Ext params
shadow: false,
tabIndex: 1,
anchor: '90%',
hiddenId: Ext.id(),
hiddenName: 'feature_entity[institution_id]',
allowBlank: false,
mode: 'remote',
triggerAction: 'all',
valueField: 'id',
displayField: 'name',
pageSize: 10,
forceSelection: true,
minChars: 3,
initComponent: function(){
this.store = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: this.controller + '/' + this.actions.load
}),
reader: new Ext.data.JsonReader({
root: 'data',
totalProperty: 'total',
id: 0
}, CCA.data.Institution),
baseParams: {
institution_id: null
}
});
// listen to [+] button
this.on('add', this.onAdd, this);
// when user selects an institution, get the person combo (if exists, it might not) and set the company id. this will cause an autoload on
// person combo.
this.on('select', function(){
var fpanel = this.findParentBy(function(c){
return c instanceof Ext.form.FormPanel
});
var person = fpanel.form.items.find(function(f){
return f.getXType() == 'person';
});
if (person) {
//person.setInstitutionId(this.getValue());
}
}, this);
// super
CCA.feature.Institution.superclass.initComponent.call(this);
},
/***
* setInstitutionId
* @param {Integer} institution_id
*/
setInstitutionId: function(id){
this.institution_id = id;
this.store.baseParams.institution_id = id;
},
reset: function(){
CCA.feature.Institution.superclass.reset.call(this);
this.lastQuery = null;
this.store.removeAll();
},
onAdd: function(param){
var fpanel = Ext.getCmp(this.form_id);
//RExt.UploadMgr.allowOnly('image');
fpanel.showInsert();
fpanel.on('actioncomplete', function(form, action){
if (typeof(action.result) != 'undefined') {
var res = action.result;
var rec = this.insert(0, res.data[this.controller]);
//RExt.UploadMgr.flush();
fpanel.hide();
}
}, this);
},
onEdit: function(rec){
var fpanel = this.getForm();
if (fpanel) {
var domain = RExt.company.Util.loadDomainById(rec.data.domain_id);
fpanel.setDomain(domain);
fpanel.load(rec.data.id);
fpanel.on('actioncomplete', function(form, action){
if (action.type == 'submit') {
var res = action.result;
if (res.success == true) {
fpanel.hide();
}
}
});
}
else {
}
},
getForm: function(){
return Ext.getCmp(this.form_id);
}
});
Ext.reg('institution', CCA.feature.Institution);
/**
* CCA.feature.EntityInstitution
* A special combo for selecting companies related to a feature entity.
*/
CCA.feature.InstitutionForm = Ext.extend(RExt.sys.Form, {
controller: 'institution',
fileUpload: true,
actions: {
insert: 'insert',
update: 'update',
"delete": 'delete'
},
layoutConfig: {
fill: true,
activeOnTop: true,
titleCollapse: true
},
title: App.t('institution'),
useDialog: true,
frame: false,
layout: 'fit',
dialogConfig: {
height: 350,
width: 320
},
header: false,
labelAlign: 'right',
labelWidth: 70,
bodyStyle: 'padding: 10px',
/***
* initComponent
*/
initComponent: function(){
this.items =[this.buildProperties()];
CCA.feature.InstitutionForm.superclass.initComponent.call(this);
},
/**
* buildProperties
* @return {Ext.Panel}
*/
buildProperties: function(){
return new Ext.Panel({
title: App.t('properties'),
frame: false,
border: false,
header: false,
layout: 'form',
autoHeight: true,
bodyStyle: 'padding: 10px;',
items: [{
fieldLabel: App.t('name'),
name: 'institution[name]',
xtype: 'textfield',
anchor: '90%',
allowBlank: false
},{
fieldLabel: App.t('description'),
name: 'institution[description]',
xtype: 'textarea',
anchor: '90%',
allowBlank: true
},{
fieldLabel: App.t('location'),
name: 'institution[location]',
xtype: 'textfield',
anchor: '90%',
allowBlank: true
}, {
fieldLabel: App.t('logo'),
permittedExtensions: 'image',
name: 'institution[logo]',
emptyText: App.t("select_logo"),
model: "Institution",
xtype: 'fileuploadfield',
anchor: '90%',
allowBlank: true,
buttonCfg: {
text: '',
iconCls: 'upload-icon'
}
}]
});
},
/**
* buildLocation
* @return {Ext.Panel}
*/
buildLocation: function(){
var formName = 'location';
// get region manager
regionMgr = Ext.ComponentMgr.get('region_manager');
// init the regionManager with the current form name "company"
regionMgr.setFormName(formName);
var comboCountry = regionMgr.renderCountry({
anchor: '90%',
tabIndex: 1,
msgTarget: 'qtip',
allowBlank: true
});
var comboRegion = regionMgr.renderRegion({
width: 120,
tabIndex: 1,
msgTarget: 'qtip',
anchor: '90%',
allowBlank: true
});
// create city combo
var comboCity = regionMgr.renderCity({
queryDelay: 100,
anchor: '90%',
allowBlank: true
});
// sew them all together with RegionMgr::associate
regionMgr.associate(comboCountry, comboRegion, comboCity);
return new Ext.form.FieldSet({
id: this.id + '_fs_location',
checkboxToggle: true,
collapsed: true,
iconCls: 'icon-world',
layout: 'form',
title: 'Address',
defaultType: 'textfield',
autoWidth: true,
autoHeight: true,
bodyStyle: 'padding: 10px',
items: [comboCountry, comboRegion, comboCity, new Ext.form.TextField({
name: 'location[addr1]',
fieldLabel: 'Addr1',
anchor: '90%'
}), new Ext.form.TextField({
name: 'location[zip]',
fieldLabel: 'Postal/Zip',
anchor: '90%'
})]
});
}
});
/***
* CCA.feature.Location
* Every Feature of type Event (or EventSeries) can be assigned a When, Where and How Much)
* which is all collected and organized through the entity called DateAdmission
* @param {Object} param
*/
CCA.feature.Location = Ext.extend(RExt.form.ComboBoxAdd, {
domain: null,
form_id: 'location_form', // our hook the the correct form for this object ie) CCA.feature.LocationForm
controller: 'location',
actions: {
load: 'search',
insert: 'insert'
},
emptyText: 'Select location...',
shadow: false,
tabIndex: 1,
//anchor: '90%',
hiddenId: Ext.id(),
hiddenName: 'feature_entity[location_id]',
fieldLabel: 'Location',
allowBlank: false,
mode: 'remote',
triggerAction: 'all',
valueField: 'id',
displayField: 'name',
pageSize: 10,
forceSelection: true,
initComponent: function(){
this.store = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: this.controller + '/' + this.actions.load
}),
reader: new Ext.data.JsonReader({
root: 'data',
totalProperty: 'total',
id: 0
}, CCA.data.Location),
baseParams: {
location_id: null
}
});
// listen to [+] button
this.on('add', this.onAdd, this);
this.on('select', function(){
var fpanel = this.findParentBy(function(c){
return c instanceof Ext.form.FormPanel
});
var person = fpanel.form.items.find(function(f){
return f.getXType() == 'person';
});
if (person) {
person.setInstitutionId(this.getValue());
}
}, this);
// super
CCA.feature.Location.superclass.initComponent.call(this);
},
/***
* setLocationId
* @param {Integer} location_id
*/
setLocationId: function(id){
this.location_id = id;
this.store.baseParams.location_id = id;
},
reset: function(){
CCA.feature.Location.superclass.reset.call(this);
this.lastQuery = null;
this.store.removeAll();
},
onAdd: function(param){
// the feature entity panel knows a lot of the feature.. so we grab it
var parent = this.findParentBy(function(c){
return c instanceof Ext.form.FormPanel
});
var fpanel = Ext.getCmp(this.form_id);
fpanel.setKey(parent.feature_id);
fpanel.showInsert();
fpanel.on('actioncomplete', function(form, action){
if (typeof(action.result) != 'undefined') {
var res = action.result;
var rec = this.insert(0, res.data[this.controller]);
fpanel.hide();
}
}, this);
},
onEdit: function(rec){
var fpanel = this.getForm();
if (fpanel) {
var domain = RExt.company.Util.loadDomainById(rec.data.domain_id);
fpanel.setDomain(domain);
fpanel.load(rec.data.id);
fpanel.on('actioncomplete', function(form, action){
if (action.type == 'submit') {
var res = action.result;
if (res.success == true) {
fpanel.hide();
}
}
});
}
else {
}
},
getForm: function(){
return Ext.getCmp(this.form_id);
}
});
Ext.reg('location', CCA.feature.Location);
/**
* CCA.feature.LocationForm
* A special combo for selecting locations for a feature.
*/
CCA.feature.LocationForm = Ext.extend(RExt.sys.Form, {
/**
* controller & actions
*/
controller: 'location',
actions: {
insert: 'insert',
update: 'update',
"delete": 'delete'
},
layoutConfig: {
fill: true,
activeOnTop: true,
titleCollapse: true
},
title: 'Event Location',
useDialog: true,
border: false,
frame: false,
layout: 'fit',
dialogConfig: {
height: 260,
width: 300
},
header: false,
labelAlign: 'right',
labelWidth: 70,
style: 'padding: 5px',
/***
* initComponent
*/
initComponent: function(){
this.items = this.buildLocation();
CCA.feature.LocationForm.superclass.initComponent.call(this);
},
getParams : function () {
return {type: 'Feature'}
},
/**
* buildLocation
* @return {Ext.Panel}
*/
buildLocation: function(){
var formName = 'location';
// get region manager
regionMgr = Ext.ComponentMgr.get('region_manager');
// init the regionManager with the current form name "company"
regionMgr.setFormName(formName);
var comboCountry = regionMgr.renderCountry({
anchor: '92%',
tabIndex: 1,
msgTarget: 'qtip',
allowBlank: true
});
var comboRegion = regionMgr.renderRegion({
width: 120,
tabIndex: 1,
msgTarget: 'qtip',
anchor: '92%',
allowBlank: true
});
// create city combo
var comboCity = regionMgr.renderCity({
queryDelay: 100,
tabIndex: 1,
anchor: '92%',
allowBlank: true
});
// sew them all together with RegionMgr::associate
regionMgr.associate(comboCountry, comboRegion, comboCity);
return new Ext.form.FieldSet({
id: this.id + '_fs_location',
//checkboxToggle: true,
collapsed: false,
iconCls: 'icon-world',
layout: 'form',
title: 'Details',
defaultType: 'textfield',
autoWidth: true,
autoHeight: true,
bodyStyle: 'padding: 5px',
items: [comboCountry, comboRegion, comboCity, new Ext.form.TextField({
name: 'location[name]',
tabIndex: 1,
fieldLabel: 'Name',
anchor: '92%'
}), new Ext.form.TextField({
name: 'location[zip]',
tabIndex: 1,
fieldLabel: 'Postal/Zip',
anchor: '92%'
})]
});
}
});
/**
* CCA.data.Person provides a simple record definition for the Person store
*/
CCA.data.Person = Ext.data.Record.create([
{name: 'id'},
{name: 'name'}
]);
/**
* CCA.feature.Person
* A special combo for selecting accounts related to a feature entity
* @author Chris Scott
*/
CCA.feature.Person = Ext.extend(RExt.form.ComboBoxAdd, {
controller: 'institution',
actions: {
load: "search_person",
insert: "insert_person"
},
form_id: 'person_form',
cls: 'person-combo',
hiddenName: 'feature_entity[person_id]',
valueField: 'id',
displayField: 'name',
name: 'contact',
shadow: false,
emptyText: 'Select contact...',
tabIndex: 1,
anchor: '90%',
hiddenId: Ext.id(),
fieldLabel: 'Contact',
allowBlank: false,
mode: 'remote',
triggerAction: 'all',
minChars: 3,
initComponent: function(){
this.store = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: this.controller + '/' + this.actions.load
}),
reader: new Ext.data.JsonReader({
root: 'data',
totalProperty: 'total',
id: 0
}, CCA.data.Person),
baseParams: {
company_id: null
},
listeners: {
// auto-select 1st record on-load
load: function(store, rs, options){
if (rs.length > 0) {
this.onSelect(rs[0], 0);
}
},
scope: this
}
});
this.on('add', this.onAdd, this);
CCA.feature.Person.superclass.initComponent.call(this);
},
reset: function(){
CCA.feature.Person.superclass.reset.call(this);
this.lastQuery = null;
this.store.removeAll();
},
/***
* setInstitutionId
* sets the combo's institution_id. institution_id is automatically added to query params
* @param {Integer} id
*/
setInstitutionId: function(id){
this.institution_id = id;
this.store.baseParams.institution_id = id;
this.reset();
this.doQuery('', true);
},
onAdd: function(param){
var fpanel = Ext.getCmp(this.form_id);
try {
//fpanel.setDomain(this.domain);
fpanel.setInstitutionId(this.institution_id);
fpanel.showInsert();
fpanel.on('actioncomplete', function(form, action){
var res = action.result;
if (res.success == true) {
var rec = this.insert(0, res.data.person);
this.onSelect(rec, 0);
fpanel.hide();
}
}, this);
}
catch (e) {
Application.handleException(this, e);
}
},
/***
* onAddPerson
* called by comboBoAdd
* @param {Object} ev
*/
onAddPerson: function(ev){
this.personField = ev.field;
var companyField = null;
},
/***
* doInsertPerson
* @param {Object} form
* @param {Object} action
*/
doInsertPerson: function(form, action){
if (typeof(action.result) != 'undefined') {
var fpanel = Ext.get(this.form_id);
fpanel.hide();
var combo = this.personField;
var rec = combo.insert(0, action.result.data.person);
combo.onSelect(rec, 0);
}
}
});
// register this field as an xtype
Ext.reg('person', CCA.feature.Person);
/**
* CCA.feature.PersonForm
*/
CCA.feature.PersonForm = Ext.extend(RExt.sys.Form, {
controller: 'institution',
actions: {
insert: 'insert_person'
},
header: false,
title: App.t('person_details'),
useDialog: true,
dialogConfig: {
width: 300,
height: 500
},
labelWidth: 125,
plain: true,
autoScroll: true,
initComponent: function(){
this.items = [new CCA.feature.PersonProperties({})];
CCA.feature.PersonForm.superclass.initComponent.call(this);
},
/**
* setInstitutionId
* sets this person's related institution
* @param {Object} id
*/
setInstitutionId: function(id){
//console.log('set Institution ID is called inside PersonForm');
return;
if (typeof(this.form.baseParams) != 'object') {
this.form.baseParams = {
//"person[institution_id]": null
}
}
//this.form.baseParams["person[institution_id]"] = id
}
});
/**
* CCA.feature.PersonProperties
* fieldset for institution account properties
*/
CCA.feature.PersonProperties = Ext.extend(Ext.Panel, {
header: false,
layout: 'form',
border: false,
initComponent: function(){
this.items = [new Ext.form.TextField({
name: 'person[first]',
fieldLabel: App.t('first'),
allowBlank: false,
anchor: '90%'
}), new Ext.form.TextField({
name: 'person[last]',
fieldLabel: App.t('last'),
allowBlank: false,
anchor: '90%'
}), new Ext.form.TextField({
name: 'person[title]',
fieldLabel: App.t('title'),
width: 50,
anchor: '90%'
}), new Ext.form.TextArea({
name: 'person[description]',
fieldLabel: App.t('extra'),
allowBlank: true,
anchor: '90%'
}),
new CCA.feature.Biographies({
hiddenName: 'person[feature_id]',
emptyText: App.t('select_biography'),
fieldLabel: App.t('biography'),
store: Ext.StoreMgr.get('biography_store')
}),
new CCA.feature.Institution({
hiddenName: 'person[institution_id]',
allowBlank: true,
emptyText: App.t('select_institution'),
fieldLabel: App.t('Institution')
}),
new Ext.form.FieldSet({
title: 'Roles',
items: CCA.feature.Util.getPersonRoles(), // <-- role checkboxes
autoHeight: true
})];
CCA.feature.PersonProperties.superclass.initComponent.call(this);
}
});
/***
* CCA.feature.Biographies
* a drop down of only existing biography features, for use in assigning a person to a biography
* Maps a Person to a Feature of Type Biography.... so there
* @param {Object} param
*/
CCA.feature.Biographies = Ext.extend(Ext.form.ComboBox, {
form_id: 'biography_form',
controller: 'feature',
actions: {
load: 'search_biography'
},
shadow: false,
tabIndex: 1,
anchor: '90%',
allowBlank: true,
mode: 'remote',
triggerAction: 'all',
valueField: 'id',
displayField: 'title',
pageSize: 10,
forceSelection: true,
initComponent: function(){
CCA.feature.Biographies.superclass.initComponent.call(this);
},
reset: function(){
CCA.feature.Biographies.superclass.reset.call(this);
this.lastQuery = null;
this.store.removeAll();
},
getForm: function(){
return Ext.getCmp(this.form_id);
}
});
Ext.reg('biographies', CCA.feature.Biographies);
/**
* CCA.feature.EntityLocation
* A special combo for selecting a location of an EntityCompany
* @author Chris Scott
*/
CCA.feature.EntityLocation = Ext.extend(Ext.form.TextField, {
initComponent: function(){
CCA.feature.EntityLocation.superclass.initComponent.call(this);
}
});
Ext.reg('entity_location', CCA.feature.EntityLocation);
/**
* THIS IS PROBABLY USELESS AND COULD BE DELETED
* CCA.feature.ShowcasingsForm
* Features can be placed into any Showcasings and their rank can also be set
*/
/*
CCA.feature.ShowcasingsForm = Ext.extend(Ext.Panel, {
title: 'Showcasings',
labelAlign: 'right',
labelWidth: 125,
autoHeight: true,
collapsible: true,
titleCollapse: true,
bodyStyle: 'padding: 10px',
layout: 'form',
iconCls: 'icon-application-view-tile',
initComponent: function(){
if (CCA.feature.Util.getShowcases().getCount() > 0) {
this.items = this.build();
}
CCA.feature.ShowcasingsForm.superclass.initComponent.call(this);
},
build: function(){
var items = [];
CCA.feature.Util.getShowcases().each(function(s){
var cfg = {
name: 'showcase[' + s.id + ']',
fieldLabel: s.name,
value: 0,
checked: false,
sliderConfig: {
boxLabel: 'rank',
plugins: new Ext.ux.SliderTip({
getText: function(slider){
return String.format('<b>rank: {0}</b>', slider.getValue());
}
})
}
};
var showcase = this.data.find(function(fs){
return (fs.showcase_id == s.id) ? true : false
});
if (showcase) {
cfg.checked = true;
cfg.value = showcase.rank;
}
items.push(new RExt.form.SliderCheckbox(cfg));
}, this);
return items;
}
});
Ext.reg('showcasings', CCA.feature.ShowcasingsForm);
*/
/**
* CCA.feature.SlideshowImagesView
* a panel containing a DataView that provides the drag drop and other operations on images
*
*/
CCA.feature.SlideshowImagesView = Ext.extend(Ext.Panel, {
controller: 'slideshow',
actions: {
search: 'view',
reorder: 'reorder',
'delete': 'delete'
},
ctCls: 'r-dataview-dropzone',
autoScroll: true,
border: true,
frame: true,
initComponent : function() {
/**
* we can broadcast the event editslideshowevent to whoever is listening...
*/
this.addEvents({
'editslideshowimage' : true
});
this.items = this.build();
var dnd = new RExt.DataView.Orderable({
listeners: {
order: function (view, startIndex,records) {
rs = [];
for (var i = 0, len = records.length; i < len; i++) {
rs.push({
id: records[i].data.id,
position: i+startIndex
});
}
App.request({
url: this.controller + '/' + this.actions.reorder,
params: {
data: Ext.encode(rs)
},
success: function (res) {
},
failure: function (res) {
}
});
},
scope: this
}
});
this.plugins = dnd;
CCA.feature.SlideshowImagesView.superclass.initComponent.call(this);
this.on('render', function () {
Ext.dd.ScrollManager.register(this.body);
}, this);
},
setSlideshowId : function(id) {
this.getView().store.proxy.conn.url = this.controller + '/' + this.actions.search + '/' + id;
},
build : function() {
var store = this.buildStore();
var tools = new RExt.DataViewEditor({
actions: {
"delete": 'delete_image',
edit: 'edit_image'
},
listeners: {
'edit' : function(view, index, node, ev) {
this.onEdit(view, index, node, ev);
},
'delete' : function(view, index, node, ev) {
this.onDelete(view, index, node, ev);
},
scope: this
}
});
var tpl = new Ext.XTemplate(
'<tpl for=".">',
' <div id="feature-media-{id}" class="slideshow-media x-unselectable">',
' <table class="properties">',
' <tbody>',
// ' <tr><th>Title:</th><td><em>{title}</em></td></tr>',
// ' <tr><th>Caption:</th><td><em>{caption}</em></td></tr>',
' <tr><th>Thumb:</th><td><img src="{thumb}" alt="{title}" /></td></tr>',
' <tr><th></th><td>{item_file_name}</td></tr>',
' <tr><th>Tools:</th><td><div class="tools"><a href="#" class="edit">edit</a> | <a class="delete" href="#">delete</a></div></td></tr>',
' </tbody>',
' </table>',
' </div>',
'</tpl>',{
getTitle : function (title) {
return title;
//return (typeof title == 'undefined')? 'none' : title;
}
}
);
//this.bbar = this.buildBottomToolbar(store);
var view = new Ext.DataView({
store: store,
tpl: tpl,
singleSelect: true,
itemSelector: 'div.slideshow-media',
dropZoneCls: 'dropzone',
selectedClass: 'x-grid3-row-selected',
overClass: 'x-grid3-row-over',
plugins: tools
});
return view;
},
/**
* onDelete
* remove a slideshow image
* @param {Ext.DataView} view
* @param {Number} index
* @param {HTMLElement} node
* @param {Ext.EventObject} ev
*/
onDelete : function (view, index, node, ev) {
Ext.MessageBox.confirm(App.t('delete'), App.t('delete_image'), function(btn){
if (btn == 'yes') {
var record = view.store.getAt(index);
App.showSpinner('delete'); // <-- showSpinner
App.request({
url: this.controller + '/' + this.actions["delete"] + '/' + record.data.id,
method: 'POST',
success: function(res){
if (res.success == true) {
view.store.removeAt(index);
}
},
failure: function(res) {
},
scope: this
}, this);
}
}, this);
},
/**
* onEdit
* a click on the edit tool and an image in a slideshow can be edited,
* @param {Ext.DatView} view
* @param {Number} index
* @param {HTMLElement} node
* @param {Ext.EventObject} ev
*/
onEdit : function (view, index, node, ev) {
var record = view.store.getAt(index);
this.fireEvent('editslideshowimage', this, record);
},
// private
load : function(record) {
this.setSlideshowId(record.data.id)
App.showSpinner('loading');
this.getView().store.load();
App.hideSpinner();
this.doLayout(); // <-- this is necessary for some stupid reason.
},
buildBottomToolbar : function(store) {
return new Ext.PagingToolbar({
store: store,
pageSize: this.pageSize,
displayInfo: false
});
},
buildStore : function(params) {
params = params || {};
var url = this.controller + '/' + this.actions.search;
if (this.slideshow_id != null) { url += '/' + this.slideshow_id }
var cfg = Ext.apply({
/*autoLoad: {
params : {
limit: this.pageSize,
start: 0
}
},*/
reader: new Ext.data.JsonReader({
totalProperty: 'total',
root: 'media',
id: 'id'
}, CCA.data.FeatureMedia),
proxy: new Ext.data.HttpProxy({
url: url,
method: "GET"
}),
baseParams : this.baseParams
},params);
if (this.autoLoad === false) {
cfg.autoLoad = false;
}
return new Ext.data.Store(cfg);
},
/**
* getView
* @return {Ext.DataView}
*/
getView : function() {
return this.items.first();
},
/**
* doEdit
* When a slideshow is ready to be updated this call handles the setup of the form panel and view
* @param {Object} data
*/
doEdit : function (data) {
//console.log('Loading the Slideshow with the data ', data);
App.hideSpinner();
},
/**
* onClick
* @param {Object} v
* @param {Object} index
* @param {Object} node
* @param {Object} ev
*/
onClick : function(v, index, node, ev) {
var btn = ev.getTarget('a', 4, true);
if (btn == null) {
this.fireEvent('select', v, index, node, ev); // <-- simply fire select event
return false; // <-- no tool clicked. GTFO
}
// did user click a tool? give chance for any Plugins to service this toolclick event
if (btn.hasClass('tool')) {
return this.fireEvent('toolclick', v, index, node, btn, ev);
}
// link with an href? redir regular <a href="/url">
else if (btn.dom.href) {
document.location = btn.dom.href;
}
},
onLoad : function (store, records, options) {
//console.log('onLoad fired store=%o, records=%o, options=%o', store, records, options);
},
/**
* reset
* empty the store and get ready for new data
*/
reset : function () {
var view = this.getView();
view.store.removeAll();
}
});
Ext.reg('slideshowview', CCA.feature.SlideshowImagesView);
/**
* CCA.feature.SlideshowImageEditor
* The center region will contain two panels, only one of which is visible at a time.
* One panel contains the image, large size, with the current data rendered by an XTemplate
* The second panel contains an editing form where the minute details of an image can be changed
*/
CCA.feature.SlideshowImageEditor = Ext.extend(Ext.form.FormPanel, {
controller: 'slideshow',
frame: true,
border: false,
header: false,
actions: {
update: 'update_media'
},
record: null,
initComponent : function() {
/**
* when building an image editor for a slideshow, we really only need to present three fields, namely
* 1) title 2) caption 3) copyright cleared
*/
var fields = CCA.feature.MediaFieldMgr.get('Image');
var formItems = [];
for ( var i = 0, len = fields.length; i < len; i++) {
switch (fields[i].name) {
case 'title':
case 'caption':
case 'cleared':
var f = {};
Ext.apply(f, fields[i]);
f.name = "feature_media[" + fields[i].name + ']';
f.width = "80%"; // set width of items as percentage of container width
formItems.push(f);
break;
}
}
//console.log('formItems ', formItems);
this.items = formItems;
this.buttons = [{
text: App.t('update'),
handler: this.onUpdate,
scope: this
},{
text: App.t('cancel'),
handler: this.reset,
scope: this
}];
CCA.feature.SlideshowImageEditor.superclass.initComponent.call(this);
},
/**
* onUpdate
* update the title, caption and copyright elements for a slideshow image
* @param {Object} btn
* @param {Object} ev
*/
onUpdate : function (btn, ev) {
var fm = this.getForm();
if (fm.isValid()) {
App.showSpinner(App.t('save'));
fm.submit({
url: this.controller + '/' + this.actions.update + '/' + this.record.data.id,
success: function(form, action) {
var record = this.getRecord();
fm.reset();
this.disableButtons();
var data = action.result.data;
record.fields.each(function(f) {
record.set(f.name, data[f.mapping]);
});
App.processResponse(action);
},
failure: function(form, action){
App.processResponse(action);
},
scope: this
}, this);
}
},
getRecord : function () {
return this.record;
},
/**
* load
* accepts a record, and presents the Media in the record in a nice way
* @param {Object} record
*/
load : function(record) {
//PAT. Find out which code is calling this load method
console.info("SlideShowImageEditor#load record:", record);
// END PAT
this.record = record;
var fm = this.getForm();
fm.setValues(this.formify(record.data));
this.enableButtons();
},
/**
* getButtons
* return the buttons we assigned to this panel in the center region
*/
getButtons : function () {
return this.buttons;
},
disableButtons: function () {
var buttons = this.getButtons();
for (var i = 0, len = buttons.length; i < len; i++) {
buttons[i].disable();
}
},
enableButtons: function () {
var buttons = this.getButtons();
for(var i = 0, len = buttons.length; i< len; i++) {
buttons[i].enable();
}
},
formify : function (data) {
values = {};
for (var key in data) {
values['feature_media[' + key + ']'] = data[key];
}
return values;
}
});
Ext.reg('slideshowimageeditor', CCA.feature.SlideshowImageEditor);
/**
* CCA.feature.SlideshowManager
* This panel contains a pretty sophisticated border layout to handle Slideshows.
* Outer Level: WEST == form holding the Meta Data for the slideshow
* CENTER == border layout for holding the actual details for the selected slideshow
* Inner Level:
* NORTH = file uploader (which is a form)
* CENTER = form with Image details
* EAST = listing of current images assigned to a slideshow
*/
CCA.feature.SlideshowManager = Ext.extend(Ext.Panel, {
controller: 'slideshow',
actions: {
view: 'view',
update: 'update',
reorder: 'reorder',
"delete" : 'delete',
delete_images: 'delete_images',
upload: 'upload'
},
layout: 'border',
media: null,
feature_id: null,
record: null,
initComponent : function () {
this.addEvents({
/**
* @event created
* fires when a slideshow has been created
* @param {Panel} this
* @param {Record} record
*/
'created' : true
});
// we need this to make a slideshow editing form...
var media = {
type: 'Slideshow',
fields: CCA.feature.MediaFieldMgr.get('Slideshow')
}
this.items = [{
region:'west',
xtype: 'slideshow_form',
media: media,
feature_id: this.feature_id,
formName: 'feature_media',
header: true,
border: false,
labelAlign: 'top',
split: true,
width: 250,
minWidth: 200,
maxWidth: 400,
reset: false,
autoHeight:true,
listeners : {
created: this.onCreated,
scope: this
}
}, {
xtype: 'panel',
region: 'center',
layout: 'border',
items: [{
xtype: 'form',
fileUpload: true,
region: 'north',
disabled: true,
height: 40,
header: false,
frame: false,
border: false,
bodyStyle: 'padding: 5px',
labelAlign: 'right',
items: [ {
xtype: 'fileuploadfield',
ctCls: 'slideshow-north',
name: 'item',
fieldLabel: App.t('image'),
emptyText: App.t('select_image'),
allowBlank: true,
permittedExtensions: 'image',
model: 'FeatureMedia',
buttonCfg: {
text: '',
iconCls: 'upload-icon'
},
listeners: {
'fileselected': this.onSelect,
scope: this
}
}]
},{
xtype: 'slideshowimageeditor',
region: 'center',
margins: '5 5 5 5'
},{
region:'east',
xtype: 'slideshowview',
title: 'Images',
frame: false,
split: true,
width: 200,
listeners: {
'editslideshowimage' : function (sender, record) {
this.doEditImage(record);
},
scope: this
}
}]
}];
CCA.feature.SlideshowManager.superclass.initComponent.call(this);
},
setRecord : function (record) {
this.record = record;
},
setSender : function (sender) {
this.sender = sender;
},
getRecord : function () {
return this.record;
},
getSender : function () {
return this.sender;
},
/**
* when a slideshow is created, we need to setup the Slideshow Edit process to be update for the metadata
* and turn on the image uploader in the north
*/
onCreated : function (form, record) {
var uploadPanel = this.getUploadPanel();
uploadPanel.enable();
form.hideButton(form.id+'_btnSave');
form.showButton(form.id+'_btnUpdate');
this.getFormPanel().setRecord(record);
this.getFormPanel().setSender(this.getFormPanel());
this.getFormPanel().getTopToolbar().show();
},
/**
* doEditImage
* accept an image record for display and editing in the center region
* @param {Ext.data.Record} record
*/
doEditImage : function (record) {
var mp = this.getMediaPanel();
mp.load(record);
},
/**
* doEdit
* called from the MediaEditForm this provides the form with some crucial information
* - the sender panel, giving us the dataview and it's store and template etc.
* - a data record that can be displayed for editing
* @param {CCA.feature.MediaPanel} sender
* @param {Ext.data.Record} record
*/
doEdit : function (sender, record) {
this.setRecord(record);
this.setSender(sender);
// this will use the record from the slideshow_panel to load the images
var vp = this.getViewPanel();
if(vp) {
vp.load(record);
}
// turn on the ability to upload more photos to an existing slideshow
var uploadPanel = this.getUploadPanel();
uploadPanel.enable();
// clear out the center region panel to get it ready for edits
var mp = this.getMediaPanel();
mp.form.reset();
// setup the Meta Details form, turn on the update and hide save button
var fp = this.getFormPanel();
fp.setSender(sender);
fp.setRecord(record);
fp.setValues(record);
fp.hideButton(fp.id+'_btnSave');
fp.showButton(fp.id+'_btnUpdate');
fp.getTopToolbar().show();
},
/**
* resetSlideshowEdit
* there are occasions when we want to reset the whole Slideshow Editor to nil
*/
reset : function () {
// this will use the record from the slideshow_panel to load the images
this.setRecord(null);
var vp = this.getViewPanel();
if(vp) {
vp.reset();
}
var fp = this.getFormPanel();
fp.showButton(fp.id+'_btnSave');
fp.hideButton(fp.id+'_btnUpdate');
// this is odd... formpanel has no reset().. so we do it manually.
fp.getForm().items.each(function (f){
f.reset();
});
fp.getTopToolbar().hide();
// turn off the ability to upload photos to an non-editable slideshow
var uploadPanel = this.getUploadPanel();
uploadPanel.form.reset();
uploadPanel.disable();
},
/**
* getUploadPanel
* returns the North region which has been assigned the photo uploader element
*/
getUploadPanel : function () {
var panel = this.getContentPanel();
return panel.items.find(function(p) { return (p.region == 'north') ? true : false; });
},
/**
* getViewPanel
* returns the west region which has been assigned the DataView showing all the slideshow images
*/
getViewPanel : function () {
var panel = this.getContentPanel();
return panel.items.find(function(p) { return (p.region == 'east') ? true : false; });
},
/**
* getMediaPanel
* returns the center region which contains the slideshow image manipulation components
*/
getMediaPanel : function() {
var panel = this.getContentPanel();
return panel.items.find(function(p) { return (p.region == 'center') ? true : false; });
},
/**
* getMediaPanel
* returns the center region which contains the slideshow image manipulation components
*/
getContentPanel : function() {
return this.items.find(function(p) { return (p.region == 'center') ? true : false; });
},
getFormPanel : function () {
return this.items.find(function(p) { return (p.region == 'west') ? true : false; });
},
/**
* onSelect
* if we selected a file, send the Feature controller a command to inform the file upload queue that a file is coming
* @param {Ext.form.ComboBox} combo
* @param {Object} file
*/
onSelect : function (combo, file) {
App.showSpinner(App.t('upload'));
var fPanel = this.getUploadPanel();
fPanel.form.submit({
url: this.controller + '/' + this.actions.upload + '/' + this.getRecord().data.feature_id,
params: {parent_id: this.getRecord().data.id},
success: function(form, action) {
// action.response.responseText contains all the goodies
fPanel.form.reset();
var response = Ext.decode(action.response.responseText);
var vp = this.getViewPanel();
var store = vp.getView().store;
store.add(new store.recordType(response.data));
App.processResponse(action);
},
failure: function(form, action){
App.processResponse(action);
},
scope: this
})
}
});
/**
* CCA.feature.PublishedUrl
* this component provides a semi-smart way of viewing the URL of a published feature
*/
CCA.feature.PublishedUrl = Ext.extend(Ext.Panel,{
controller: 'feature',
actions: {
unpublish: 'unpublish'
},
frame: true,
border: false,
header:false,
record: null,
style: 'margin:5px',
tpl: null,
initComponent : function () {
CCA.feature.PublishedUrl.superclass.initComponent.call(this);
// This template is a handy way of stamping out the record data
this.tpl = new Ext.XTemplate('<tpl for=".">',
'<div class="published_url">',
' <div style="float:left;">',
' URL: <a href="{url}" target="_blank">{url}</a>',
' </div>',
' <tpl if="this.canUnpublish() == true">',
' <div style="float:right;text-align:right;">',
' <span><a href="#" id="unpublish_{id}">' + App.t('unpublish')+ '</a></span>',
' </div>',
' </tpl>',
'</div>',
'</tpl>', {
canUnpublish: function(){
if(CCA.feature.Util.getAccountProfile() == 'profile.writer')
return false;
return true;
}
});
this.on('render', function () {
if(this.record.data.published) {
this.tpl.overwrite(this.body, this.record.data);
if (CCA.feature.Util.getAccountProfile() != 'profile.writer') {
var link = Ext.get('unpublish_' + this.record.data.id);
link.on('click', this.unPublish, this, this.record.data.id);
}
} else {
this.body.update('<p>' + App.t('unpublished_content') + '</p>');
}
}, this);
},
unPublish : function (ev, el, id) {
Ext.MessageBox.confirm('Unpublish', 'Unpublish Feature?', function(btn){
if (btn == 'yes') {
App.showSpinner('save'); // <-- showSpinner
App.request({
url: this.controller + '/' + this.actions['unpublish'] + '/' + id,
success: function(res){
//console.log('res ', res);
if (res.success == true) {
var link = Ext.get('unpublish_'+id);
link.un('click', this);
this.body.update('<p>' + App.t('unpublished_content') + '</p>');
// remove the publication date from the grid too
// eventually just fire an event to tell grid to update itself
var grid = Ext.getCmp('feature_grid');
var store = grid.store;
var range = store.getRange();
for (var i = 0, len = range.length; i < len; i++) {
if (range[i].data.id == id) {
var record = range[i];
}
}
if(record instanceof Ext.data.Record) {
record.set('published_at', null);
record.set('published', false);
}
}
},
failure: function(res) {
var msgBody = '';
if(res.data.features.length > 0 || res.data.showcases.length > 0)
msgBody = 'This feature cannot be unpublished because it is linked with the following items:<br /><br />';
if(res.data.features.length > 0) {
msgBody += 'features:<br />======<br /><br /><ul>';
for(var i=0; i<res.data.features.length; i++) {
var item = res.data.features[i];
msgBody += '<li style="margin-left: 10px; list-style-type: disc !important">' + item.title + ' (id='+ item.id + ')</li>';
if(i == 9){
msgBody += (res.data.features.length - (i + 1)) + ' more...<br /><br />'
break;
}
}
msgBody += '</ul>';
}
if(res.data.showcases.length > 0) {
msgBody += 'showcases:<br />=======<br /><br /><ul>';
for(var i=0; i<res.data.showcases.length; i++) {
var item = res.data.showcases[i];
msgBody += '<li style="margin-left: 10px; list-style-type: disc !important">' + item.title + ' (id='+ item.id + ')</li>';
if(i == 9){
msgBody += (res.data.showcases.length - (i + 1)) + ' more...<br /><br />'
break;
}
}
msgBody += '</ul>';
}
if(msgBody.length > 0)
Ext.Msg.alert('failed to unpublish this feature', msgBody);
},
scope: this
}, this);
}
}, this);
},
update: function (data) {
this.tpl.overwrite(this.body, data);
if (CCA.feature.Util.getAccountProfile() != 'profile.writer') {
var link = Ext.get('unpublish_' + data.id);
link.on('click', this.unPublish, this, data.id);
}
var grid = Ext.getCmp('feature_grid');
var store = grid.store;
var range = store.getRange();
for (var i = 0, len = range.length; i < len; i++) {
if (range[i].data.id == data.id) {
var record = range[i];
}
}
if(record instanceof Ext.data.Record) {
record.set('published_at',data.published_at);
record.set('published',data.published);
}
}
});
Ext.reg('publishedurl', CCA.feature.PublishedUrl);
/**
* register all the Feature Entities as xtypes, making the loop to create the accordian
* much simpler. This way, we can just instantiate new xtypes and not embed presentation logic
* in the models as it is presently done.
*/
Ext.reg('quote_panel', CCA.feature.EntityPanel);
Ext.reg('organizer_panel', CCA.feature.EntityPanel);
Ext.reg('sponsor_panel', CCA.feature.EntityPanel);
Ext.reg('credit_panel', CCA.feature.EntityPanel);
Ext.reg('publisher_panel', CCA.feature.EntityPanel);
Ext.reg('item_panel', CCA.feature.EntityPanel);
Ext.reg('subject_panel', CCA.feature.EntityPanel);
Ext.reg('quote_edit', CCA.feature.EntityEditForm);
Ext.reg('organizer_edit', CCA.feature.EntityEditForm);
Ext.reg('sponsor_edit', CCA.feature.EntityEditForm);
Ext.reg('credit_edit', CCA.feature.EntityEditForm);
Ext.reg('publisher_edit', CCA.feature.EntityEditForm);
Ext.reg('item_edit', CCA.feature.EntityEditForm);
Ext.reg('subject_edit', CCA.feature.EntityEditForm);
Ext.reg('DateAdmission', CCA.feature.AdmissionForm);
/**
* register all the Feature Media as xtypes, panels and forms
*/
Ext.reg('image_panel', CCA.feature.MediaPanel);
Ext.reg('audio_panel', CCA.feature.MediaPanel);
Ext.reg('video_panel', CCA.feature.MediaPanel);
Ext.reg('slideshow_panel', CCA.feature.SlideshowPanel);
Ext.reg('othermedia_panel', CCA.feature.MediaPanel);
Ext.reg('link_panel', CCA.feature.MediaPanel);
/**
* various forms for editing existing media assigned to Features
*/
Ext.reg('image_edit', CCA.feature.MediaEditForm);
Ext.reg('audio_edit', CCA.feature.MediaEditForm);
Ext.reg('video_edit', CCA.feature.MediaEditForm);
Ext.reg('slideshow_edit', CCA.feature.SlideshowManager);
Ext.reg('othermedia_edit', CCA.feature.MediaEditForm);
Ext.reg('slideshow_form', CCA.feature.MediaEditForm);
Ext.reg('link_edit', CCA.feature.MediaEditForm);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment