--- /dev/null
+Ext.require([
+ 'Ext.data.*',
+ 'Ext.panel.Panel',
+ 'Ext.layout.container.Card',
+ 'Ext.tip.QuickTipManager'
+]);
+
+Ext.define('Customer', {
+ extend: 'Ext.data.Model',
+ fields: [{
+ name: 'id',
+ type: 'int'
+ }, 'name', 'phone'],
+ associations: [{
+ model: 'Order',
+ type: 'hasMany',
+ autoLoad: true
+ }],
+ proxy: {
+ type: 'ajax',
+ url: 'customer.php'
+ }
+});
+
+Ext.define('Order', {
+ extend: 'Ext.data.Model',
+ fields: [{
+ name: 'id',
+ type: 'int'
+ },{
+ name: 'customer_id',
+ type: 'int'
+ },{
+ name: 'date',
+ type: 'date',
+ dateFormat: 'Y-m-d'
+ }],
+ belongsTo: 'Customer',
+ associations: [{
+ model: 'OrderItem',
+ type: 'hasMany',
+ autoLoad: true
+ }],
+ proxy: {
+ type: 'ajax',
+ url: 'order.php'
+ }
+});
+
+Ext.define('OrderItem', {
+ extend: 'Ext.data.Model',
+ fields: [{
+ name: 'id',
+ type: 'int'
+ }, {
+ name: 'order_id',
+ type: 'int'
+ },'product', {
+ name: 'quantity',
+ type: 'int'
+ }, {
+ name: 'price',
+ type: 'float'
+ }],
+ belongsTo: 'Order',
+ proxy: {
+ type: 'ajax',
+ url: 'orderitem.php'
+ }
+});
+
+Ext.define('CustomerGrid', {
+ extend: 'Ext.grid.Panel',
+ alias: 'widget.customergrid',
+
+ title: 'Customers',
+
+ initComponent: function(){
+ Ext.apply(this, {
+ store: {
+ autoLoad: true,
+ model: 'Customer',
+ listeners: {
+ load: function() {
+ Logger.log('Customer store loaded', false);
+ }
+ }
+ },
+ columns: [{
+ text: 'Id',
+ dataIndex: 'id'
+ },{
+ text: 'Name',
+ dataIndex: 'name',
+ flex: 1
+ }, {
+ text: 'Phone',
+ dataIndex: 'phone'
+ }],
+ dockedItems: [{
+ xtype: 'toolbar',
+ items: {
+ itemId: 'load',
+ text: 'Load Orders',
+ scope: this,
+ handler: this.loadOrders,
+ disabled: true
+ }
+ }]
+ });
+ this.callParent();
+ this.getSelectionModel().on('selectionchange', this.onSelectChange, this);
+ },
+
+ onSelectChange: function(selModel, selections) {
+ this.active = selections[0];
+ this.down('#load').setDisabled(!this.active);
+ },
+
+ loadOrders: function(){
+ var rec = this.active,
+ name = rec.get('name'),
+ owner = this.ownerCt,
+ orders;
+
+
+ orders = rec.orders();
+ if (orders.isLoading()) {
+ Logger.log('Begin loading orders: ' + rec.getId(), true);
+ }
+ orders.on('load', function(){
+ Logger.log('Order store loaded - ' + rec.getId(), false);
+ });
+ owner.add({
+ title: 'Orders - ' + rec.getId(),
+ customer: rec,
+ xtype: 'ordergrid',
+ store: orders
+ });
+ owner.getLayout().next();
+ }
+});
+
+Ext.define('OrderGrid', {
+ extend: 'Ext.grid.Panel',
+ alias: 'widget.ordergrid',
+
+ initComponent: function(){
+ Ext.apply(this, {
+ columns: [{
+ text: 'Id',
+ dataIndex: 'id'
+ },{
+ flex: 1,
+ text: 'Date',
+ dataIndex: 'date',
+ renderer: Ext.util.Format.dateRenderer('Y-m-d')
+ }],
+ dockedItems: [{
+ xtype: 'toolbar',
+ items: [{
+ text: 'Back',
+ scope: this,
+ handler: this.onBackClick
+ },{
+ itemId: 'load',
+ text: 'Load Order Items',
+ scope: this,
+ handler: this.loadItems,
+ disabled: true
+ }]
+ }]
+ });
+ this.callParent();
+ this.getSelectionModel().on('selectionchange', this.onSelectChange, this);
+ },
+
+ onBackClick: function(){
+ this.ownerCt.getLayout().prev();
+ this.destroy();
+ },
+
+ onSelectChange: function(selModel, selections) {
+ this.active = selections[0];
+ this.down('#load').setDisabled(!this.active);
+ },
+
+ loadItems: function(){
+ var customerName = this.customer.get('name'),
+ rec = this.active,
+ date = Ext.Date.format(rec.get('date'), 'Y-m-d'),
+ owner = this.ownerCt,
+ orderitems;
+
+ orderitems = rec.orderitems();
+ if (orderitems.isLoading()) {
+ Logger.log('Begin loading order items - ' + rec.getId(), true);
+ }
+ orderitems.on('load', function(){
+ Logger.log('Order items loaded - ' + rec.getId(), false);
+ });
+ owner.add({
+ title: 'Order Items - ' + rec.getId(),
+ xtype: 'orderitemgrid',
+ store: orderitems
+ });
+ owner.getLayout().next();
+ }
+});
+
+Ext.define('OrderItemGrid', {
+ extend: 'Ext.grid.Panel',
+ alias: 'widget.orderitemgrid',
+
+ initComponent: function(){
+ Ext.apply(this, {
+ columns: [{
+ text: 'Id',
+ dataIndex: 'id'
+ },{
+ flex: 1,
+ text: 'Product',
+ dataIndex: 'product'
+ }, {
+ text: 'Quantity',
+ dataIndex: 'quantity'
+ }, {
+ text: 'Price',
+ dataIndex: 'price',
+ renderer: Ext.util.Format.usMoney
+ }],
+ dockedItems: [{
+ xtype: 'toolbar',
+ items: [{
+ text: 'Back',
+ scope: this,
+ handler: this.onBackClick
+ }, {
+ itemId: 'load',
+ text: 'Parent association loader',
+ tooltip: 'Demonstrate loading parent relationships - A new record will be created so we ignore any previous associations setup',
+ scope: this,
+ handler: this.onLoadClick,
+ disabled: true
+ }]
+ }]
+ });
+ this.callParent();
+ this.getSelectionModel().on('selectionchange', this.onSelectChange, this);
+ },
+
+ onSelectChange: function(selModel, selections) {
+ this.active = selections[0];
+ this.down('#load').setDisabled(!this.active);
+ },
+
+ onBackClick: function(){
+ this.ownerCt.getLayout().prev();
+ this.destroy();
+ },
+
+ onLoadClick: function(){
+ var rec = this.active,
+ id = rec.getId();
+
+ new ItemLoader({
+ width: 400,
+ height: 400,
+ modal: true,
+ title: this.title.replace('Order Items', 'Order Item ' + id),
+ orderItemData: rec.data,
+ orderItemId: id
+ }).show();
+ }
+});
+
+Ext.define('ItemLoader', {
+ extend: 'Ext.window.Window',
+
+ initComponent: function(){
+ Ext.apply(this, {
+ border: false,
+ dockedItems: [{
+ xtype: 'toolbar',
+ items: [{
+ text: 'Print order detail',
+ scope: this,
+ handler: this.onOrderClick
+ }, {
+ itemId: 'company',
+ text: 'Print company detail',
+ disabled: true,
+ scope: this,
+ handler: this.onCompanyClick
+ }]
+ }],
+ bodyPadding: 5,
+ tpl: '<div>{type} {id} - {value}</div>',
+ tplWriteMode: 'append'
+ });
+ this.callParent();
+ this.orderItem = new OrderItem(this.orderItemData, this.orderItemId);
+ },
+
+ onOrderClick: function(){
+ var id = this.orderItem.get('order_id'),
+ hasOrder = !!this.order;
+
+ if (!hasOrder) {
+ Logger.log('Begin loading order - ' + id, true);
+ }
+ this.orderItem.getOrder({
+ scope: this,
+ success: function(order){
+ this.order = order;
+ this.down('#company').enable();
+ if (!hasOrder) {
+ Logger.log('Order loaded - ' + id, false);
+ }
+ this.update({
+ type: 'Order',
+ id: order.getId(),
+ value: Ext.Date.format(order.get('date'), 'Y-m-d')
+ });
+ }
+ });
+ },
+
+ onCompanyClick: function(){
+ var id = this.order.get('customer_id'),
+ hasCustomer = !!this.customer;
+
+ if (!hasCustomer) {
+ Logger.log('Begin loading customer - ' + id, true);
+ }
+ this.order.getCustomer({
+ scope: this,
+ success: function(customer){
+ this.customer = customer;
+ if (!hasCustomer) {
+ Logger.log('Customer loaded - ' + id, false);
+ }
+ this.update({
+ type: 'Customer',
+ id: customer.getId(),
+ value: customer.get('name')
+ });
+ }
+ });
+ }
+});
+
+Logger = (function(){
+ var panel;
+
+ return {
+ init: function(log){
+ panel = log;
+ },
+
+ log: function(msg, isStart){
+ panel.update({
+ now: new Date(),
+ cls: isStart ? 'beforeload' : 'afterload',
+ msg: msg
+ });
+ panel.body.scroll('b', 100000, true);
+ }
+ };
+})();
+
+Ext.onReady(function(){
+
+ var main = Ext.create('Ext.panel.Panel', {
+ renderTo: document.body,
+ width: 750,
+ height: 400,
+ border: false,
+ layout: {
+ type: 'vbox',
+ align: 'stretch'
+ },
+ items: [{
+ height: 200,
+ xtype: 'container',
+ layout: 'card',
+ margin: '0 0 5 0'
+ }, {
+ flex: 1,
+ title: 'Loader log',
+ tplWriteMode: 'append',
+ tpl: '<div class="{cls}">[{now:date("H:i:s")}] - {msg}</div>',
+ bodyPadding: 5,
+ autoScroll: true,
+ listeners: {
+ render: Logger.init
+ }
+ }]
+ });
+ Logger.log('Begin loading customer store', true);
+ main.items.first().add({
+ xtype: 'customergrid'
+ });
+
+});