Added main stream code

1 parent aa93a603
Showing with 1995 additions and 0 deletions
/**
* Main application luncher
*
*/
Ext.application({
name: 'MyMA',
controllers: ['Viewport', 'ProgramMenu', 'Taskpanel', 'Program', 'Users', 'User', 'Aliases', 'Alias', 'Transports'],
enableQuickTips: true
});
/**
* Contains Common overrides and extentions
*
*/
/**
* Adds functions with predefined configs
*/
Ext.override(Ext.Msg, {
onShow: function() {
this.callParent(arguments);
this.center();
// This will fix trace information block
if(!Ext.isEmpty(Ext.query('div.x-msg-trace')) && !Ext.isEmpty(Ext.query('div.x-msg-error'))) {
var error = Ext.get(Ext.query('div.x-msg-error')),
trace = Ext.get(Ext.query('div.x-msg-trace'));
if(trace.first().getHeight() + error.first().getHeight() > this.body.getHeight()) {
trace.first().setHeight(this.body.getHeight() - error.first().getHeight());
}
}
},
showInfo: function(config) {
Ext.Msg.show(Ext.apply({
autoScroll: true,
title: 'Info',
msg: '',
icon: Ext.Msg.INFO,
buttons: Ext.Msg.OK
}, config || {}))
},
showError: function(cfg) {
if(Ext.isObject(cfg.msg)) {
if(cfg.msg.tpl) {
if(Ext.isArray(cfg.msg.tpl) || Ext.isString(cfg.msg.tpl)) {
cfg.msg = new Ext.XTemplate(Ext.isArray(cfg.msg.tpl) ? cfg.msg.tpl.join('') : cfg.msg.tpl).apply(cfg.msg.data || {});
}
else if(cfg.msg.tpl.isTemplate) {
cfg.msg = cfg.msg.tpl.apply(cfg.msg.data || {});
}
}
else if(cfg.msg.error) {
cfg.msg = new Ext.XTemplate(
'<div class="x-msg-error">',
'<tpl if="code">Error code: {code}<br/></tpl>',
'<tpl if="type">Error type: {type}<br/></tpl>',
'Message: <tpl if="message">{message}</tpl><tpl if="!values.message">Unknown error</tpl><br>',
'<tpl if="file">File: {file}<br/></tpl>',
'<tpl if="line">Line: {line}<br/></tpl>',
'</div>',
'<tpl if="traces">',
'<div class="x-msg-trace"><tpl for="traces">',
'({line}) {file}: <div class="x-msg-trace-detail">',
'<tpl if="type == \'-&gt;\'">{class}-&gt;{function}()</tpl>',
'<tpl if="args && args.length &gt; 0"><div><b>Arguments:</b> {[ Ext.encode(values.args) ]}</div></tpl>',
'</div>',
'</tpl></div>',
'</tpl>'
).apply(cfg.msg.error);
}
}
Ext.Msg.show(Ext.apply({
autoScroll: true,
title: 'Error',
msg: '',
icon: Ext.Msg.ERROR,
buttons: Ext.Msg.OK
}, cfg || {}))
}
});
/**
* Adds default settings to the Ext.data.Connection
* The main goal is to change onComplete function to handle common server exceptions
*/
Ext.override(Ext.data.Connection, {
// Default request path
url: '.',
// Default timeoute
timeout: 380000,
/**
* Set guest state to the authorization controller
*/
setGuest: Ext.emptyFn,
/**
* Return isGuest current value
* @return {Boolean}
*/
getGuest: Ext.emptyFn,
/**
* Finds meta tag in the document to set application base url
* @return {string}
*/
getBaseUrl: function() {
if(!Ext.isDefined(this.baseUrl)) {
this.baseUrl = (Ext.query('meta[name=application-url]')[0] || { content: '.' }).content;
this.baseUrl.replace(/[\/\\]+$/, "");
this.url = this.baseUrl;
}
return this.url;
},
/**
* Returns RESTful url using base url and passed route
* @return {string}
*/
getRestUrl: function() {
var route = [];
Ext.iterate(arguments, function(value) {
this.push(value);
}, route);
route = route.join('/');
route.replace(/^[\/\\]+/, "");
return [this.getBaseUrl(), '/index.php/', route].join('');
},
/**
* To be called when the request has come back from the server
* This override needs to catch specific server exceptions and stop callback execution
* @private
* @param {Object} request
* @return {Object} The response
*/
onComplete : function(request) {
var me = this,
options = request.options,
result,
success,
response;
try {
result = me.parseStatus(request.xhr.status);
} catch (e) {
// in some browsers we can't access the status if the readyState is not 4, so the request has failed
result = {
success : false,
isException : false
};
}
success = result.success;
// Run success
if (success) {
response = me.createResponse(request);
me.fireEvent('requestcomplete', me, response, options);
Ext.callback(options.success, options.scope, [response, options]);
} else {
if (result.isException || request.aborted || request.timedout) {
response = me.createException(request);
} else {
response = me.createResponse(request);
}
// Keep unauthorized statuses
if(Ext.isEmpty(me.getGuest()) && (response.status != 404 || response.status != 500)) {
me.setGuest(true);
}
else {
if(options.proxy && options.proxy.isProxy) {
var data = response.responseText ? Ext.decode(response.responseText) : {};
Ext.Msg.showError({
title: data.error.title || 'Error',
msg: {
error: data.error
},
buttons: Ext.Msg.OK
});
}
else {
me.fireEvent('requestexception', me, response, options);
}
Ext.callback(options.failure, options.scope, [response, options]);
}
}
if (!Ext.isDefined(me.isGuest)) {
Ext.callback(options.callback, options.scope, [options, success, response]);
}
delete me.requests[request.id];
return response;
}
});
/**
* Changes for the toolbar element
*/
Ext.override(Ext.Toolbar, {
// Adds function to the toolbar to return input element's values
getValues: function() {
var params = {},
items = this.query('searchfield,textfield,numberfield,checkbox,radio,combo');
Ext.each(items, function(item){
this[item.name || item.itemId || item.getId()] = item.getValue();
}, params);
return params;
}
});
/**
* Additional component to initiate query request on enter key event
*/
Ext.define('Ext.form.SearchField', {
extend: 'Ext.form.field.Text',
alias: 'widget.searchfield',
enableKeyEvents: true,
// If field is in the toolbar than this option may points to button
// or put here function
handler: null,
// Add specialkey listener
initComponent: function() {
this.callParent();
if(!Ext.isEmpty(this.handler)) {
this.on('specialkey', this.checkEnterKey, this);
}
},
// Handle enter key presses, execute the search if the field has a value
checkEnterKey: function(field, e) {
var value = this.getValue();
if (e.getKey() === e.ENTER) {
if(Ext.isFunction(this.handler)) {
this.handler();
}
else if(Ext.isString(this.handler)) {
var point = this.up('toolbar').query('#' + this.handler);
if(point.length > 0 && point[0].getXType() == 'button') {
point[0].fireEvent('click',point[0]);
}
}
}
}
});
\ No newline at end of file
/**
* Conroller: Alias
*
*/
Ext.define('MyMA.controller.Alias', {
extend: 'Ext.app.Controller',
views: ['Alias'],
refs: [{
selector: 'alias',
ref: 'aliasWindow'
}],
init: function() {
this.control({
'alias > toolbar > #savedata': {
click: this.saveData
}
});
},
saveData: function(Button) {
var form = this.getAliasWindow().down('form').getForm(),
id = form.getValues().id || null;
if(!form.isValid()) {
return false;
}
form.submit({
url: Ext.Ajax.getRestUrl('api','alias', id),
clientValidation: true,
method: id > 0 ? 'PUT' : 'POST',
scope: {
controller: this,
win: this.getAliasWindow()
},
success: this.onSuccessSubmit,
failure: this.onFailSubmit
});
},
/**
*
*/
onSuccessSubmit: function(form, action) {
this.win.close();
this.controller.getController('Aliases').getStore('Aliases').reload({
params: {
start: 0
}
});
Ext.Msg.showInfo({
msg: 'Data saved'
})
},
/**
*
*/
onFailSubmit: function(form, action) {
try {
var data = Ext.decode(action.response.responseText);
throw(data);
}
catch(e) {
Ext.Msg.showError({
msg: e
});
}
}
});
Ext.define('MyMA.controller.Aliases', {
extend: 'Ext.app.Controller',
stores: ['Aliases'],
views: ['Aliases','Alias'],
refs: [{
selector: 'aliases > grid',
ref: 'aliasesList'
}],
init: function() {
this.control({
'aliases > grid > toolbar > #addrecord': {
click: this.showForm
},
'aliases > grid > toolbar > #search': {
click: this.onSearch
},
'aliases actioncolumn': {
click: this.onActionColumn
}
});
},
/**
* Handles action columns click
* @param {Object} grid view
* @param {HTMLElement} Element
* @param {Integer} row index
* @param {Integer} column index
* @param {Object} Event object
* @param {Object} Scope object
* @param {Object}
*/
onActionColumn: function(gridview, el, rowIndex, colIndex, e, scope, rowEl) {
if(e.getTarget('.x-ibtn-edit')) {
var record = scope.store.getAt(rowIndex);
var widget = this.getController('Taskpanel').addProgram({
name: 'alias'
});
widget.setTitle('Alias: ' + record.get('alias'));
widget.down('form').getForm().loadRecord(record);
}
if(e.getTarget('.x-ibtn-delete')) {
var record = scope.store.getAt(rowIndex);
Ext.Msg.confirm('Info', 'Press Yes to confirm remove action', function(button) {
if (button === 'yes') {
this.record.destroy({
scope: this,
success: function() {
this.store.remove(this.record)
}
});
}
}, {
store: scope.store,
record: record
});
}
},
/**
* Show form to add new record or edit existing data
* @param {Object} Button
*/
showForm: function(Button) {
this.getController('Taskpanel').addProgram({
name: 'alias',
title: 'New Alias'
});
},
/**
* Search action
*/
onSearch: function(Button) {
this.getAliasesList().getStore().reload({ params: Button.up('toolbar').getValues() });
}
});
Ext.define('MyMA.controller.Program', {
extend: 'Ext.app.Controller',
stores: ['Programs'],
refs: [{
selector: 'taskpanel',
ref: 'taskPanel'
}],
init: function() {
var control = {};
Ext.each(this.refs, function(item){
this.control[item.selector] = {
beforeclose: this.me.programStop,
hide: this.me.programState,
show: this.me.programState,
minimize: this.me.programMinimize
}
}, {
control: control,
me: this
});
this.control(control);
},
/**
* Register controll for the created "Program"
* @param String, selector name
*/
registerControl: function(selector) {
var selector = selector || null,
ctrl = {};
if(!selector) {
return;
}
ctrl[selector] = {
beforeclose: this.programStop,
hide: this.programState,
show: this.programState,
minimize: this.programMinimize
};
this.control(ctrl);
}, // end registerControl()
/**
* Hides widget and sets status to the Store object
* @param {Object} item
*/
programMinimize: function(item) {
var record;
if(!(record = this.getStore('Programs').getProccess({
property: 'item',
value: item.getId()
})))
{
return false;
}
this.getTaskPanel().items.get(record.get('control')).toggle(false);
item.hide();
this.programState(item);
}, // end programMinimize()
/**
* Writes program state to the Store object
* @param {Object} item
* @param {Object} opt
*/
programState: function(item, opt) {
var record;
if(!(record = this.getStore('Programs').getProccess({
property: 'item',
value: item.getId()
})))
{
return false;
}
record.set('state', item.isHidden() ? 'hide' : 'show');
}, // end programState()
/**
* Destroyes wiget and removes program information from the Store
* @param {Object} item
* @param {Object} record
*/
programStop: function(item, record) {
var record = record || Ext.undefined;
if (!record['data']) {
(record = this.getStore('Programs').getProccess({
property: 'item',
value: item.getId()
}));
}
if(item.animateTarget) {
item.animateTarget = null;
}
if(record && record['data']) {
this.getTaskPanel().items.get(record.get('control')).destroy();
this.getStore('Programs').remove(record);
}
} // end programStop()
});
Ext.define('MyMA.controller.ProgramMenu', {
extend: 'Ext.app.Controller',
init: function() {
this.control({
'programmenu > menu': {
click: this.LaunchProgram
}
});
},
LaunchProgram: function(menu, item) {
if (item.itemId == 'logout') {
this.getController('Viewport').Logout();
}
else {
this.getController('Taskpanel').addProgram({
name: item.widgetName,
title: item.text
});
}
}
});
Ext.define('MyMA.controller.Taskpanel', {
extend: 'Ext.app.Controller',
stores: ['Programs'],
refs: [{
selector: 'taskpanel',
ref: 'taskPanel'
}],
init: function() {
this.control({
'taskpanel > button': {
toggle: this.programState
}
});
},
/**
* Add program to the task panel
* @param data
*/
addProgram: function(data) {
var data = data || {
name: null
},
store = this.getStore('Programs'),
record, widget;
if(!(record = store.getProccess({
property: 'name',
value: data.name
})))
{
try {
var widget = Ext.widget(data.name),
progId = (store.max('id') || 0) + 1;
}
catch(e) {
return false;
}
var Button = this.getTaskPanel().add({
xtype: 'button',
ui: 'program-button',
height: 28,
text: data.title || widget.title,
enableToggle: true,
pressed: true,
programId: progId
});
record = store.add({
id: progId,
title: data.title || widget.title,
name: data.name,
state: 'show',
item: widget.getId(),
control: Button.getId()
})[0];
this.getController('Program').registerControl(data.name);
widget.animateTarget = Button.getId();
widget.setTitle(data.title);
widget.show();
}
else {
this.getTaskPanel().items.get(record.get('control')).toggle(true);
if((widget = Ext.getCmp(record.get('item')))) {
widget.show();
}
}
return widget ? widget : null;
},
/**
* Get reference function
* @param {Object} Button
*/
callRef: function(selector) {
var me = this;
try {
for (var i = 0, ln = this.refs.length; i < ln; i++) {
if (this.refs[i]['selector'] == selector) {
return me['get' + Ext.String.capitalize(this.refs[i]['ref'])]();
}
}
}
catch(e) { }
return null;
},
programState: function(Button) {
var store = this.getStore('Programs'),
record, widget;
if(!(record = store.getProccess({
property: 'id',
value: Button.programId
})))
{
return false;
}
if ((widget = Ext.getCmp(record.get('item')))) {
widget[record.get('state') == 'show' ? 'hide' : 'show']();
}
},
/**
* Close all process those are registed in the Programs storage
*/
closeAll: function() {
this.getStore('Programs').each(function(record){
if ((widget = Ext.getCmp(record.get('item')))) {
widget.hide();
this.getTaskPanel().items.get(record.get('control')).destroy();
}
}, this);
}
});
Ext.define('MyMA.controller.Transports', {
extend: 'Ext.app.Controller',
stores: ['Transports'],
views: ['Transports'],
refs: [{
selector: 'transports > grid',
ref: 'transportsList'
}],
init: function() {
this.control({
'transports > grid > toolbar > #addrecord': {
click: this.addRecord
},
'transports > grid > toolbar > #search': {
click: this.onSearch
},
'transports actioncolumn': {
click: this.onActionColumn
},
'transports > grid': {
edit: this.onEditAction
}
});
},
/**
* Handles action columns click
* @param {Object} grid view
* @param {HTMLElement} Element
* @param {Integer} row index
* @param {Integer} column index
* @param {Object} Event object
* @param {Object} Scope object
* @param {Object}
*/
onActionColumn: function(gridview, el, rowIndex, colIndex, e, scope, rowEl) {
if(e.getTarget('.x-ibtn-delete')) {
var record = scope.store.getAt(rowIndex);
Ext.Msg.confirm('Info', 'Press Yes to confirm remove action', function(button) {
if (button === 'yes') {
if(!this.record.get('id')) {
this.store.remove(this.record);
}
else {
this.record.destroy({
scope: this,
success: function() {
this.store.remove(this.record)
}
});
}
}
}, {
store: scope.store,
record: record
});
}
},
/**
* Add record to the store and start editing
*/
addRecord: function(Button) {
this.getTransportsList().getStore().insert(0, this.getTransportsList().getStore().model.create({
id: 0,
domain: null,
transport: 'virtual'
}));
},
/**
* Search action
*/
onSearch: function(Button) {
this.getTransportsList().getStore().reload({ params: Button.up('toolbar').getValues() });
},
/**
* Fires when edit complete and record was updated
* @param {object}, Ext.grid.plugin.Editing
* @param {object}, An edit event
*/
onEditAction: function(editor, e) {
e.record.save({
scope: e,
success: function(record) {
this.store.reload();
}
});
}
});
Ext.define('MyMA.controller.User', {
extend: 'Ext.app.Controller',
views: ['User'],
refs: [{
selector: 'user',
ref: 'userWindow'
}],
init: function() {
this.control({
'user > toolbar > #savedata': {
click: this.saveData
}
});
},
saveData: function(Button) {
var form = this.getUserWindow().down('form').getForm(),
id = form.getValues().id || null;
if(!form.isValid()) {
return false;
}
form.submit({
url: Ext.Ajax.getRestUrl('api','user', id),
clientValidation: true,
method: id > 0 ? 'PUT' : 'POST',
params: Ext.applyIf(Ext.copyTo({}, form.getValues(), 'smtp,imap,manager'), {
smtp: 0,
imap: 0,
manager: 0
}),
scope: {
controller: this,
win: this.getUserWindow()
},
success: this.onSuccessSubmit,
failure: this.onFailSubmit
});
},
/**
*
*/
onSuccessSubmit: function(form, action) {
this.win.close();
this.controller.getController('Users').getStore('Users').reload({
params: {
start: 0
}
});
Ext.Msg.showInfo({
msg: 'Data saved'
})
},
/**
*
*/
onFailSubmit: function(form, action) {
try {
var data = Ext.decode(action.response.responseText);
throw(data);
}
catch(e) {
Ext.Msg.showError({
msg: e
});
}
}
});
Ext.define('MyMA.controller.Users', {
extend: 'Ext.app.Controller',
stores: ['Users', 'Choice'],
views: ['Users', 'User'],
refs: [{
selector: 'users > grid',
ref: 'usersList'
}, {
selector: 'users',
ref: 'usersWindow'
}],
init: function() {
this.control({
'users > grid > toolbar > #addrecord': {
click: this.showForm
},
'users > grid > toolbar > #search': {
click: this.onSearch
},
'users actioncolumn': {
click: this.onActionColumn
}
});
},
/**
* Handles action columns click
* @param {Object} grid view
* @param {HTMLElement} Element
* @param {Integer} row index
* @param {Integer} column index
* @param {Object} Event object
* @param {Object} Scope object
* @param {Object}
*/
onActionColumn: function(gridview, el, rowIndex, colIndex, e, scope, rowEl) {
if(e.getTarget('.x-ibtn-edit')) {
var record = scope.store.getAt(rowIndex);
var widget = this.getController('Taskpanel').addProgram({
name: 'user'
});
widget.setTitle('User: ' + record.get('name'));
widget.down('form').getForm().loadRecord(record);
}
if(e.getTarget('.x-ibtn-delete')) {
var record = scope.store.getAt(rowIndex);
Ext.Msg.confirm('Info', 'Press Yes to conform remove action', function(button) {
if (button === 'yes') {
this.record.destroy({
scope: this,
success: function() {
this.store.remove(this.record)
}
});
}
}, {
store: scope.store,
record: record
});
}
},
/**
* Show form to add new record or edit existing data
* @param {Object} Button
*/
showForm: function(Button) {
this.getController('Taskpanel').addProgram({
name: 'user',
title: 'New User'
});
},
/**
* Search action
*/
onSearch: function(Button) {
this.getUsersList().getStore().reload({ params: Button.up('toolbar').getValues() });
}
});
/**
* Controller: Viewport
*
*/
Ext.define('MyMA.controller.Viewport', {
extend: 'Ext.app.Controller',
views: ['Viewport', 'Authorize'],
refs: [{
selector: 'viewport',
ref: 'appView'
}, {
selector: 'authorize',
ref: 'authPanel'
}, {
selector: 'authorize > form',
ref: 'authForm'
}],
/**
*
*/
isGuest: Ext.undefined,
/**
* A template method that is called when your application boots.
* It is called before the Application's launch function is executed so gives a hook
* point to run any code before your Viewport is created.
*/
init: function(app) {
// Bind Guest to the Ext.data.Connection
Ext.override(Ext.data.Connection, {
/**
* Set guest state to the authorization controller
*/
setGuest: Ext.Function.bind(this.setGuest, this),
/**
* Return isGuest current value
* @return {Boolean}
*/
getGuest: Ext.Function.bind(this.getGuest, this)
});
this.control({
'authorize > form > toolbar > button': {
click: this.Authorize
}
});
this.Authorize();
},
/**
* Authorize
* if passed main application view, the first step need to query
* @param object, main application view
*/
Authorize: function() {
if (this.getAuthPanel()) {
var form = this.getAuthPanel().down('form').getForm();
if(form.isValid()) {
form.submit({
url: Ext.Ajax.getRestUrl('api','login', 'authorize', 0),
method: 'PUT',
clientValidation: true,
scope: this,
success: this.successLogin
})
}
}
else {
Ext.Ajax.request({
url: Ext.Ajax.getRestUrl('api', 'login'),
scope: this,
callback: function(){
if (!this.isGuest && !this.getAppView()) {
this.setGuest(false);
this.getView('Viewport').create();
}
}
});
}
},
/**
* Return isGuest value
* @param state
*/
getGuest: function() {
return this.isGuest;
},
/**
* Set isGuest flag value
* @param object, this controller
* @param boolean, state to set
*/
setGuest: function(state) {
this.isGuest = Ext.isBoolean(state) ? state : true;
if(this.isGuest && !this.getAuthPanel()) {
this.getView('Authorize').create();
}
},
/**
* private
*/
successLogin: function(form, action) {
this.getAuthPanel().close();
if(!this.getAppView()) {
this.getView('Viewport').create();
}
},
/**
* Logout
* public
*/
Logout: function() {
Ext.Ajax.request({
url: Ext.Ajax.getRestUrl('api','login', 'logout', 0),
method: 'PUT',
scope: this,
callback: function() {
if(this.getAppView()) {
this.getController('Taskpanel').closeAll();
this.getAppView().destroy();
}
this.setGuest(this, true);
}
});
}
});
Ext.define('MyMA.model.Aliases', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'int'
}, {
name: 'alias',
type: 'string'
}, {
name: 'recipient',
type: 'string'
}, {
name: 'comment',
type: 'string'
}],
proxy: {
type: 'rest',
url: Ext.Ajax.getRestUrl('api', 'alias'),
reader: {
type: 'json',
root: 'results',
totalProperty: 'total'
},
writer: {
type: 'json',
allowSingle: true
}
}
});
Ext.define('MyMA.model.Brief', {
extend: 'Ext.data.Model',
fields: ['id', 'name'],
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'results'
}
}
});
Ext.define('MyMA.model.Transports', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'int'
}, {
name: 'domain',
type: 'string'
}, {
name: 'transport',
type: 'string'
}],
proxy: {
type: 'rest',
url: Ext.Ajax.getRestUrl('api', 'transport'),
reader: {
type: 'json',
root: 'results',
totalProperty: 'total'
},
writer: {
type: 'json',
allowSingle: true
}
}
});
Ext.define('MyMA.model.Users', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'int'
}, {
name: 'name',
type: 'string'
}, {
name: 'login',
type: 'string'
}, {
name: 'passwd',
type: 'string'
}, {
name: 'uid',
type: 'int',
defaultValue: 8
}, {
name: 'gid',
type: 'int',
defaultValue: 12
}, {
name: 'maildir',
type: 'string'
}, {
name: 'smtp',
type: 'int'
}, {
name: 'imap',
type: 'int'
}, {
name: 'quota',
type: 'int',
defaultValue: 10000000
}, {
name: 'manager',
type: 'int'
}],
validations: [{
type: 'format',
field: 'maildir',
matcher: /^\/[a-z]\.ru\/[a-z_0-9]\/Maildir\/$/
}],
proxy: {
type: 'rest',
url: Ext.Ajax.getRestUrl('api/user'),
reader: {
type: 'json',
root: 'results'
},
writer: {
type: 'json',
allowSingle: true
}
}
});
Ext.define('MyMA.model.Users', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'int'
}, {
name: 'name',
type: 'string'
}, {
name: 'login',
type: 'string'
}, {
name: 'passwd',
type: 'string'
}, {
name: 'uid',
type: 'int',
defaultValue: 8
}, {
name: 'gid',
type: 'int',
defaultValue: 12
}, {
name: 'maildir',
type: 'string'
}, {
name: 'smtp',
type: 'int'
}, {
name: 'imap',
type: 'int'
}, {
name: 'quota',
type: 'int',
defaultValue: 10000000
}, {
name: 'manager',
type: 'int'
}],
validations: [{
type: 'format',
field: 'maildir',
matcher: /^\/[a-z]\.ru\/[a-z_0-9]\/Maildir\/$/
}],
proxy: {
type: 'rest',
url: Ext.Ajax.getRestUrl('api/user'),
reader: {
type: 'json',
root: 'results'
},
writer: {
type: 'json',
allowSingle: true
}
}
});
Ext.define('MyMA.model.Brief', {
extend: 'Ext.data.Model',
fields: ['id', 'name'],
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'results'
}
}
});
Ext.define('MyMA.model.Aliases', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'int'
}, {
name: 'alias',
type: 'string'
}, {
name: 'recipient',
type: 'string'
}, {
name: 'comment',
type: 'string'
}],
proxy: {
type: 'rest',
url: Ext.Ajax.getRestUrl('api', 'alias'),
reader: {
type: 'json',
root: 'results',
totalProperty: 'total'
},
writer: {
type: 'json',
allowSingle: true
}
}
});
Ext.define('MyMA.model.Transports', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'int'
}, {
name: 'domain',
type: 'string'
}, {
name: 'transport',
type: 'string'
}],
proxy: {
type: 'rest',
url: Ext.Ajax.getRestUrl('api', 'transport'),
reader: {
type: 'json',
root: 'results',
totalProperty: 'total'
},
writer: {
type: 'json',
allowSingle: true
}
}
});
Ext.define('MyMA.store.Aliases', {
extend: 'Ext.data.Store',
requires: 'MyMA.model.Aliases',
model: 'MyMA.model.Aliases',
groupField: 'alias',
remoteSort: true,
pageSize: 100
});
Ext.define('MyMA.store.Choice', {
extend: 'Ext.data.Store',
requires: 'MyMA.model.Brief',
model: 'MyMA.model.Brief',
data: [{
id: 0,
name: 'No'
}, {
id: 1,
name: 'Yes'
}]
});
Ext.define('MyMA.store.Programs', {
extend: 'Ext.data.ArrayStore',
fields: ['id', 'name', 'state', 'item', 'title', 'control'],
data: [],
/**
* Get item record from process storage
* @param object
*/
getProccess: function(data) {
var data = data || {
property: 'id',
value: null
},
idx = -1;
if((idx = this.find(data.property, data.value, 0, false, true, true)) > -1) {
return this.getAt(idx);
}
return null;
}
});
Ext.define('MyMA.store.Transports', {
extend: 'Ext.data.Store',
requires: 'MyMA.model.Transports',
model: 'MyMA.model.Transports',
remoteSort: true,
pageSize: 100
});
Ext.define('MyMA.store.Users', {
extend: 'Ext.data.Store',
requires: 'MyMA.model.Users',
model: 'MyMA.model.Users',
remoteSort: true,
pageSize: 100
});
Ext.define('MyMA.view.Alias', {
extend: 'Ext.window.Window',
alias: 'widget.alias',
layout: 'fit',
title: 'Alias',
width: 400,
constrainHeader: true,
closeAction: 'destroy',
buttons: [{
xtype: 'button',
itemId: 'savedata',
text: 'Save',
scope: this
}],
items: [{
xtype: 'form',
frame: true,
monitorValid: true,
defaults: {
xtype: 'textfield',
anchor: '100%',
allowBlank: false
},
items: [{
xtype: 'hidden',
name: 'id'
}, {
fieldLabel: 'Alias',
name: 'alias',
vtype: 'email'
}, {
fieldLabel: 'Recipient',
name: 'recipient',
vtype: 'email'
}, {
fieldLabel: 'Comment',
xtype: 'textarea',
name: 'comment'
}]
}]
});
Ext.define('MyMA.view.Aliases', {
extend: 'Ext.window.Window',
alias: 'widget.aliases',
layout: 'fit',
minimizable: true,
constrainHeader: true,
closeAction: 'destroy',
width: 900,
listeners: {
render: function(win) {
if(Ext.getBody().getHeight() > 500) {
win.setHeight(Ext.getBody().getHeight() - 150);
}
}
},
items: [{
xtype: 'grid',
border: false,
viewConfig: {
plugins: {
ptype: 'gridviewdragdrop'
},
listeners: {
/**
* This event is fired through the GridView.
* Add listeners to the GridView object Fired when a drop operation has been completed and the data has been moved or copied
* @param {} node
* @param {} data
* @param {} overModel
* @param {} dropPosition
* @param {} eOpts
*/
beforedrop: function(node, data, overModel, dropPosition, eOpts) {
Ext.each(data.records, function(record) {
if(record.get('alias') != this.groupName) {
record.set('alias', this.groupName);
record.save({
action: 'update',
scope: this,
failure: function(record) {
record.store.reload();
}
});
}
}, {
data: data,
groupName: this.getFeature('alias-groups').getGroupName(node),
model: overModel
});
}
}
},
tbar: [{
xtype: 'button',
itemId: 'addrecord',
iconCls: 'x-ibtn-add',
text: 'New Item'
}, {
xtype: 'tbseparator',
width: 5
}, {
xtype: 'searchfield',
handler: 'search',
name: 'query'
}, {
xtype: 'tbspacer',
width: 5
}, {
xtype: 'button',
itemId: 'search',
text: 'Search'
}],
bbar: {
xtype: 'pagingtoolbar',
displayInfo: true,
store: 'Aliases'
},
features: [{
ftype: 'grouping',
id: 'alias-groups',
groupHeaderTpl: 'Group: {name} ({rows.length})',
startCollapsed: false
}],
selModel: {
selType: 'rowmodel'
},
columns: [{
xtype: 'actioncolumn',
width: 30,
items: [{
getClass: function() {
return 'x-ibtn-edit x-ibtn-def';
}
}]
}, {
header: 'ID',
dataIndex: 'id',
width: 40
}, {
header: 'Recipient',
dataIndex: 'recipient',
flex: 1
}, {
header: 'Alias',
hidden: true,
dataIndex: 'alias'
}, {
header: 'Comment',
dataIndex: 'comment',
flex: 1
}, {
xtype: 'actioncolumn',
width: 30,
items: [{
getClass: function() {
return 'x-ibtn-delete x-ibtn-def';
}
}]
}],
selType: 'rowmodel',
multiSelect: true,
store: 'Aliases'
}]
});
Ext.define('MyMA.view.Authorize', {
extend: 'Ext.Window',
alias: 'widget.authorize',
layout: 'fit',
autoShow: true,
layout: 'fit',
width: 350,
closable: false,
constrain: true,
draggable: false,
resizable: false,
modal: true,
cls: 'x-window-authbaner',
dockedItems: [{
dock: 'top',
xtype: 'toolbar',
ui: 'authform-baner',
height: 43,
html: '{LOGIN @ MAIL . PANEL }'
}],
items: [{
xtype: 'form',
url: 'index.php',
monitorValid: true,
frame: false,
border: false,
defaults: {
anchor: '100%'
},
buttons: [{
text: 'Login'
}],
items: [{
fieldLabel: 'Login',
xtype: 'textfield',
allowBlank: false,
name: 'login'
}, {
fieldLabel: 'Password',
xtype: 'textfield',
name: 'pass',
inputType: 'password'
}]
}]
});
Ext.define('MyMA.view.ProgramMenu', {
extend: 'Ext.Button',
alias: 'widget.programmenu',
text: 'Menu',
height: 30,
ui: 'program-menu',
menu: [{
text: 'Users',
widgetName: 'users'
}, {
text: 'Aliases',
widgetName: 'aliases'
}, {
text: 'Transports',
widgetName: 'transports'
}, '-', {
text: 'Logout',
itemId: 'logout'
}]
});
Ext.define('MyMA.view.Taskpanel', {
extend: 'Ext.Toolbar',
alias: 'widget.taskpanel',
ui: 'programbar',
height: 28,
style: {
border: 0,
padding: 0
},
autoScroll: true,
items: []
});
Ext.define('MyMA.view.Transports', {
extend: 'Ext.window.Window',
alias: 'widget.transports',
layout: 'fit',
minimizable: true,
constrainHeader: true,
closeAction: 'destroy',
width: 900,
listeners: {
render: function(win) {
if(Ext.getBody().getHeight() > 500) {
win.setHeight(Ext.getBody().getHeight() - 150);
}
}
},
items: [{
xtype: 'grid',
border: false,
tbar: [{
xtype: 'button',
itemId: 'addrecord',
iconCls: 'x-ibtn-add',
text: 'New Item'
}, {
xtype: 'tbseparator',
width: 5
}, {
xtype: 'searchfield',
handler: 'search',
name: 'query'
}, {
xtype: 'tbspacer',
width: 5
}, {
xtype: 'button',
itemId: 'search',
text: 'Search'
}],
bbar: {
xtype: 'pagingtoolbar',
displayInfo: true,
store: 'Transports'
},
columns: [{
header: 'ID',
dataIndex: 'id',
width: 40
}, {
header: 'Domain',
dataIndex: 'domain',
editor: {
xtype: 'textfield',
allowBlank: false
},
flex: 1
}, {
header: 'Transport',
dataIndex: 'transport'
}, {
xtype: 'actioncolumn',
width: 30,
items: [{
getClass: function() {
return 'x-ibtn-delete x-ibtn-def';
}
}]
}],
selType: 'rowmodel',
plugins: [
Ext.create('Ext.grid.plugin.RowEditing', {
clicksToEdit: 1
})
],
store: 'Transports'
}]
});
Ext.define('MyMA.view.User', {
extend: 'Ext.window.Window',
alias: 'widget.user',
layout: 'fit',
title: 'User',
width: 400,
constrainHeader: true,
closeAction: 'destroy',
buttons: [{
xtype: 'button',
itemId: 'savedata',
text: 'Save',
scope: this
}],
items: [{
xtype: 'form',
frame: true,
monitorValid: true,
defaults: {
xtype: 'textfield',
anchor: '100%',
allowBlank: false
},
items: [{
xtype: 'hidden',
name: 'id'
}, {
xtype: 'checkbox',
fieldLabel: 'Manager',
name: 'manager',
inputValue: 1
}, {
xtype: 'checkbox',
fieldLabel: 'SMTP',
name: 'smtp',
inputValue: 1
}, {
xtype: 'checkbox',
fieldLabel: 'IMAP',
name: 'imap',
inputValue: 1
}, {
fieldLabel: 'Name',
name: 'name'
}, {
fieldLabel: 'Login',
name: 'login',
vtype: 'email'
}, {
fieldLabel: 'Password',
name: 'passwd'
}, {
xtype: 'numberfield',
allowDecimal: false,
fieldLabel: 'UID',
name: 'uid',
anchor: '50%',
value: 8
}, {
xtype: 'numberfield',
allowDecimal: false,
fieldLabel: 'GID',
name: 'gid',
anchor: '50%',
value: 12
}, {
fieldLabel: 'Mail directory',
name: 'maildir'
}, {
xtype: 'numberfield',
name: 'quota',
allowDecimal: false,
fieldLabel: 'Quota',
anchor: '60%',
value: 100000000
}]
}]
});
Ext.define('MyMA.view.Users', {
extend: 'Ext.window.Window',
alias: 'widget.users',
layout: 'fit',
minimizable: true,
constrainHeader: true,
closeAction: 'destroy',
width: 900,
listeners: {
render: function(win) {
if(Ext.getBody().getHeight() > 500) {
win.setHeight(Ext.getBody().getHeight() - 150);
}
}
},
items: [{
xtype: 'grid',
border: false,
listeners: {
/**
* Initiate data save through proxy
* @param editor : Ext.grid.plugin.Editing
* @param object
* grid - The grid
* record - The record that was edited
* field - The field name that was edited
* value - The value being set
* row - The grid table row
* column - The grid Column defining the column that was edited.
* rowIdx - The row index that was edited
* colIdx - The column index that was edited
* originalValue - The original value for the field, before the edit (only when using CellEditing)
* originalValues - The original values for the field, before the edit (only when using RowEditing)
* newValues - The new values being set (only when using RowEditing)
* view - The grid view (only when using RowEditing)
* store - The grid store (only when using RowEditing)
*/
edit: function(editor, data) {
if(data.originalValue == data.value) {
return;
}
data.record.save({
action: 'update',
scope: data,
success: function() {
this.record.commit();
//this.view.refresh();
}
});
}
},
tbar: [{
xtype: 'button',
iconCls: 'x-ibtn-add',
itemId: 'addrecord',
text: 'New Item'
}, {
xtype: 'tbseparator',
width: 5
}, {
xtype: 'searchfield',
handler: 'search',
name: 'query'
}, {
xtype: 'tbspacer',
width: 5
}, {
xtype: 'button',
itemId: 'search',
text: 'Search'
}],
bbar: {
xtype: 'pagingtoolbar',
displayInfo: true,
store: 'Users'
},
plugins: [
Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1
})
],
selModel: {
selType: 'cellmodel'
},
columns: [{
xtype: 'actioncolumn',
width: 30,
items: [{
getClass: function() {
return 'x-ibtn-edit x-ibtn-def';
}
}]
}, {
header: 'ID',
dataIndex: 'id',
width: 40
}, {
header: 'Name',
dataIndex: 'name',
editor: {
xtype: 'textfield'
},
flex: 1
}, {
header: 'Login',
dataIndex: 'login',
width: 120
}, {
header: 'Password',
hidden: true,
dataIndex: 'passwd'
}, {
header: 'uid',
dataIndex: 'uid',
width: 40
}, {
header: 'gid',
dataIndex: 'gid',
width: 40
}, {
header: 'Mail directory',
dataIndex: 'maildir'
}, {
header: 'SMTP',
dataIndex: 'smtp',
editor: {
xtype: 'combo',
valueField: 'id',
displayField: 'name',
triggerAction: 'all',
editable: false,
store: 'Choice'
},
renderer: function(value) {
if(value==1) {
return 'Yes';
}
return 'No';
}
}, {
header: 'IMAP',
dataIndex: 'imap',
editor: {
xtype: 'combo',
valueField: 'id',
displayField: 'name',
triggerAction: 'all',
editable: false,
store: 'Choice'
},
renderer: function(value) {
if(value==1) {
return 'Yes';
}
return 'No';
}
}, {
header: 'Quota',
dataIndex: 'quota',
editor: {
xtype: 'numberfield',
allowDecimal: false
}
}, {
xtype: 'actioncolumn',
width: 30,
items: [{
getClass: function() {
return 'x-ibtn-delete x-ibtn-def';
}
}]
}],
store: 'Users'
}]
});
Ext.define('MyMA.view.Viewport', {
extend: 'Ext.container.Viewport',
requires: [
'MyMA.view.ProgramMenu',
'MyMA.view.Taskpanel',
'MyMA.view.Users',
'MyMA.view.Aliases'
],
layout: 'fit',
statics: {
ready: false
},
items: {
xtype: 'panel',
layout: 'fit',
border: false,
dockedItems: [{
dock: 'top',
xtype: 'toolbar',
height: 30,
ui: 'programbar-panel',
items: [{
xtype: 'programmenu',
width: 100
}, '-', {
xtype: 'taskpanel',
flex: 1
}]
}],
items: [{
xtype: 'panel',
border: false,
ui: 'desk-panel',
bodyCls: 'x-desk-panel-bg',
layout: {
type: 'fit'
}
}]
}
});
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
No preview for this file type
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!