Code:
// Application instance for showing user-feedback messages.
var App = new Ext.App({});
// Create a standard HttpProxy instance.
var proxy = new Ext.data.HttpProxy({
api: {
read: {
url: '/entries.xml',
method: 'GET'
}, create: {
url: '/entries.xml',
method: 'POST'
}, update: {
url: '',
method: 'PUT'
}, destroy: {
url: '',
method: 'DELETE'
}
}
});
var reader = new Ext.data.XmlReader({
record: 'entry',
id: 'id'
}, [{
name: 'day',
type: 'date',
dateFormat: 'Y-m-d'
}, {
name: 'job-id'
}, {
name: 'project-id'
}, {
name: 'client-id'
}, {
name: 'time',
type: 'float'
}, {
name: 'submitted',
type: 'boolean'
}]);
// The new DataWriter component.
var writer = new Ext.data.XmlWriter({
root: 'entries'
});
// Typical Store collecting the Proxy, Reader and Writer together.
var store = new Ext.data.GroupingStore({
//restful: true,
// <-- This Store is RESTful
proxy: proxy,
reader: reader,
writer: writer,
// <-- plug a DataWriter into the store just as you would a Reader
sortInfo: {
field: 'day',
direction: "DSC"
}, groupField: 'day',
batch: false
});
store.load(); // load the store immeditately
////
// centralized listening of DataProxy events "beforewrite", "write" and "writeexception"
// upon Ext.data.DataProxy class. This is handy for centralizing user-feedback messaging into one place rather than
// attaching listenrs to EACH Store.
//
// Listen to all DataProxy beforewrite events
//
Ext.data.DataProxy.addListener('beforewrite', function (thisProxy, action, rs) {
if (thisProxy == proxy) {
thisProxy.setApi({
read: {
url: '/entries.xml',
method: 'GET'
}, create: {
url: '/entries.xml',
method: 'POST'
}, update: {
url: '/entries/' + rs.id + '.xml',
method: 'PUT'
}, destroy: {
url: '/entries/' + rs.id + '.xml',
method: 'DELETE'
}
});
if (rs.modified)
{
if (!(rs.modified['job-id']||rs.modified['time']||rs.modified['date']||rs.modified['submitted'] ) )
{
return false;
}
}
}
// App.setAlert(App.STATUS_NOTICE, "Before " + action);
});
////
// all write events
//
Ext.data.DataProxy.addListener('write', function (proxy, action, result, res, rs) {
App.setAlert(true, action);
});
////
// all exception events
//
Ext.data.DataProxy.addListener('exception', function (proxy, type, action, options, res) {
App.setAlert(false, res.responseText);
});
function formatDate(value) {
return value ? value.dateFormat('M d, Y') : '';
}
var summary = new Ext.ux.grid.GroupSummary();
var jobsProxy = new Ext.data.HttpProxy({
api: {
read: {
url: '/jobs.xml',
method: 'GET'
}
}
});
var jobsReader = new Ext.data.XmlReader({
record: 'job',
id: 'id'
}, [{
name: 'id',
type: 'integer'
}, {
name: 'name',
type: 'string'
}, {
name: 'project_id',
type: 'integer'
}]);
var clientsProxy = new Ext.data.HttpProxy({
api: {
read: {
url: '/clients.xml',
method: 'GET'
}
}
});
var clientsReader = new Ext.data.XmlReader({
record: 'client',
id: 'id'
}, [{
name: 'id',
type: 'integer'
}, {
name: 'name',
type: 'string'
}]);
var projectsProxy = new Ext.data.HttpProxy({
api: {
read: {
url: '/projects.xml',
method: 'GET'
}
}
});
var projectsReader = new Ext.data.XmlReader({
record: 'project',
id: 'id'
}, [{
name: 'id',
type: 'integer'
}, {
name: 'name',
type: 'string'
}, {
name: 'client_id',
type: 'ineger'
}]);
var clientsCombo = new Ext.form.ComboBox({
store: new Ext.data.Store({
proxy: clientsProxy,
reader: clientsReader
}),
mode: 'local',
typeAhead: true,
typeAheadDelay: 10,
triggerAction: 'all',
width:135,
lazyRender: true,
forceSelection:true,
valueNotFoundText: 'Select a Client...',
valueField: 'id',
displayField: 'name'
});
clientsCombo.store.load();
var projectsCombo = new Ext.form.ComboBox({
store: new Ext.data.Store({
proxy: projectsProxy,
reader: projectsReader
}),
mode: 'local',
typeAhead: true,
typeAheadDelay: 10,
triggerAction: 'all',
width:135,
lazyRender: true,
valueNotFoundText: 'Select a Project...',
valueField: 'id',
displayField: 'name'
});
projectsCombo.store.load();
var jobsCombo = new Ext.form.ComboBox({
store: new Ext.data.Store({
proxy: jobsProxy,
reader: jobsReader
}),
mode: 'local',
typeAhead: true,
typeAheadDelay: 10,
triggerAction: 'all',
width:135,
lazyRender: true,
valueNotFoundText: 'Select a Job...',
valueField: 'id',
displayField: 'name'
});
jobsCombo.store.load();
clientsCombo.on('change', function(field , newVal , oldVal) {
//console.group('clientsCombo on change')
//console.dir( field, newVal,oldVal)
//console.groupEnd();
if (!field.value.match(/^Select/i))
{
projectsCombo.store.filter('client_id', field.value);
}
});
projectsCombo.on('change', function(field , newVal , oldVal) {
if (!field.value.match(/^Select/i))
{
jobsCombo.store.filter('project_id' ,field.value );
}
});
Ext.onReady(function () {
function refreshGridOnLoad(store) {
if (!store.loadCounter)
{
if (userGrid)
{
userGrid.view.refresh()
}
store.loadCounter = 0;
}
store.loadCounter++;
}
jobsCombo.store.on('load' , refreshGridOnLoad)
projectsCombo.store.on('load' , refreshGridOnLoad)
clientsCombo.store.on('load' , refreshGridOnLoad)
Ext.util.Format.comboRenderer = function (combo) {
return function (value) {
if (!value) {
return combo.valueNotFoundText;
} else {
var record = combo.findRecord(combo.valueField, value);
return record ? record.get(combo.displayField) : combo.valueNotFoundText;
}
}
};
var userColumns = [{
header: "Date",
width: 50,
dataIndex: 'day',
editor: new Ext.form.DateField({
format: 'd/m/y'
}),
renderer: formatDate,
sortable: true
},{
header: "Client",
width: 70,
dataIndex: 'client-id',
editor: clientsCombo,
renderer: Ext.util.Format.comboRenderer(clientsCombo)
}, {
header: "Project",
width: 70,
dataIndex: 'project-id',
editor: projectsCombo,
renderer: Ext.util.Format.comboRenderer(projectsCombo)
}, {
header: "Job",
width: 70,
dataIndex: 'job-id',
editor: jobsCombo,
renderer: Ext.util.Format.comboRenderer(jobsCombo)
}, {
header: "Hours",
width: 50,
dataIndex: 'time',
summaryType: 'sum',
editor: new Ext.form.NumberField({
allowBlank: false,
allowNegative: false,
maxValue: 24
}),
renderer: function (value) {
if (value) {
if (value <= 24) {
return value + " hours"
}
else if (value > 24) {
return "<div class='x-grid3-summary-err'>" + value + " hours ?</div>"
}
}
else if (!value) {
return "0 hours"
}
}
}
];
// Create a typical GridPanel with RowEditor plugin
var userGrid = new Ext.grid.EditorGridPanel({
renderTo: 'user-grid',
// iconCls: 'icon-grid',
frame: true,
title: 'Entries',
autoScroll: true,
height: 500,
store: store,
clicksToEdit: 1,
plugins: summary,
columns: userColumns,
tbar: [{
text: 'Add',
// iconCls: 'silk-add',
handler: onAdd
}, '-', {
text: 'Delete',
// iconCls: 'silk-delete',
handler: onDelete
}, '-', {
text: 'Submit To Management',
handler: onSubmitToManagement
}],
view: new Ext.grid.GroupingView({
forceFit: true,
})
});
/**
* onAdd
*/
function onAdd() {
var e = new userGrid.store.recordType({
day: (new Date()).clearTime(),
project_id: 0,
hours: 0
});
userGrid.stopEditing();
userGrid.store.insert(0, e);
userGrid.startEditing(0);
}
/**
* onDelete
*/
function onDelete() {
var index = userGrid.getSelectionModel().getSelectedCell();
if (!index) {
return false;
}
var rec = userGrid.store.getAt(index[0]);
userGrid.store.remove(rec);
}
/**
* onSubmitToManagement
* & hleper functions
*/
function onSubmitToManagement() {
Ext.Msg.confirm("Death be upon you", "you hereby forgo any right to your soul, past present and future, it will be harvested immediately, Are these terms acceptable?", areYouReallySure)
}
function areYouReallySure(btn) {
if (btn == 'yes') {
Ext.Msg.confirm("Are you sure", "cause it really hurts to have your soul ripped out....", submitEntries)
}
}
function submitEntries(btn) {
if (btn == 'yes') {
console.log("submitting")
userGrid.store.each(function submit() {
this.beginEdit()
this.set('submitted', true);
this.endEdit()
this.commit()
return true;
})
store.filterBy(function (rec, id) {
if (rec.get('submitted')) {
return false;
}
else {
return true;
}
})
userGrid.view.refresh()
}
}
userGrid.on('afteredit', function (e) {
e.grid.view.refresh()
})
});