View Full Version : Open source ERP/CRM with Extjs/Oracle/Php
nan21eu
22 Aug 2008, 12:45 AM
Project was moved to www.nan21.net (http://www.nan21.net)
as DNet eBusiness Suite : Human Resources and Customer Relationships Management Software
Technology stack is Extjs user-interface, java middle tier and database independent (MySQL and Oracle officially supported )
This thread reffers to a very early stage of the project, which still exists on google code but just for history :)
-------------------------------------------------------------------------------------------------------------
Hello all,
We'd like to introduce our new project, it is in a very early development stage yet, but gives an overview of what is going to be.
There is an online demo available at http://nan21.phporaclehosting.com/demo/ with a read-only account.
Username/Password: DEMO/DEMO
Details will follow at http://www.nan21.eu .
A first beta release is planned for the beginning of October.
Some things are still missing, as i said is just an early preview
Works with Firefox 2, Opera 9.5. [ tested ]
with IE some layout problems
Feedback with good/bad/ugly is welcome :)
By the way, extjs is really a great stuff, but you already know this
Thank you
elnove
22 Aug 2008, 8:01 AM
Looks real good, great job !
nan21eu
22 Aug 2008, 10:28 PM
Thank you elnove
Chris503
22 Aug 2008, 11:17 PM
that looks cool, and promising, but if you want wide spread adoption it has to be cross browser.
nan21eu
23 Aug 2008, 12:07 AM
Yes Chris503, it's true. I'll try to keep it compatible as much as Extjs is.
For the moment is more FF/Opera oriented as i use these browsers and the preview is a very early one. Perhaps too early :)
nan21eu
23 Aug 2008, 12:40 AM
For those looking for extjs frameworks, here is short description of the UI framework architecture maybe is of interest ...
Lets take as an example the Supplier Invoices screen
[Menu: Purchase->Received Invoice]:
It shows a list of records, navigate through the list and double-click the current row ( or hit enter if navigating with arrow keys ) and the edit form will be opened.
[ Select one record which has the last column "Posted" = "Y" in order to see the correct accounting doc. ]
There you can edit details and in the bottom there are some buttons which open windows with child records [InvItems -> invoice lines, Payment->payments of this invoice, Accdoc-> Accounting doc]
There are several type of base classes:
N21.Base.GridView implements a read-only grid for a data-source. Implements common record-list functionalities like fetch records, delete , print , filter etc
N21.Base.EditForm implements the base functionalities for an editor form: save, load record, synchronize child data-components ...
N21.Base.GridEditForm incapsulates a grid view and editor form class for the same data-source and provide linked functionality for the two layout types For ex: save a new record in form, after succesful operation is added to the grid list also.
Ok, now let's see the implementation:
Open file: http://nan21.phporaclehosting.com/demo/_static/js/dc/DC0026.js
which implements this page.
There you'll see
N21.DataComp.DC0026G = Ext.extend(N21.Base.GridView ....
a data component extending the base grid and provides the necessary data for the instance: record definition, columns, query fields [for filter ]
The next is :
N21.DataComp.DC0026F = Ext.extend(N21.Base.EditForm, {....
the second object which extends the base form and provides the editor.
There are the fields definitions, some layout items [fieldset, window, etc] and event handlers
Then comes the last object , instance of the GridEditForm
N21.DataComp.DC0026 = Ext.extend(N21.Base.GridEditForm, {
which actually specifies the layout for the two components [in this case in separate tab panels ]
------
The child data-components opened by the buttons:
InvItems: DC0041 - the same architecture as presented above but for a different data-source [ invoice lines ]
Accdoc: DC0042 - Accounting document lines for this invoice: The same architecture , different layout
Payment: DC0044 - Payments for this invoice , the same architecture different layout.
Master-detail synchronization performed in N21.Base.EditForm
There is a functionality missing yet, if no detail-records will show all records from child data-source,
but this is to be fixed, just ignore it yet. [ You'll notice this in case you selected a record wich Posted=N ]
Some other base classes also like N21.Base.Combo, N21.Base.Lov, etc
Note that the N21.Base.Lov basically started from Ext.ux.form.LovField.js created by madrabaz (http://extjs.com/forum/member.php?u=3669)
alrahan
27 Aug 2008, 3:34 PM
It looks good.
Are your posting source for it ?
nan21eu
28 Aug 2008, 10:28 PM
Yes there will be source code as well , it's open source isn't it ?
Release in the beginning of October, this is just an early preview.
Thank you for your patience
nan21eu
30 Aug 2008, 6:23 AM
thank you marcov
erichua
30 Aug 2008, 10:29 AM
It's a real good work. I hope I can develop the whole program like this. Showing my respect to you and your team. You gave me a sample to persuade the team member to fellow this OO method.
hxsam
1 Sep 2008, 10:36 PM
sorry for my poor english.
I had downloaded N21.Base.Lov ,and it work in FormPanel,and when i set some LOV000.js to a NEW N21.Base.gridEdit -->Columns--->editor,and LOV can Popup,but DoSelect return nothing to the column of the grid:
this is my code:
Ext.ns("N21.DataComp");
N21.DataComp.DC100101 = Ext.extend(N21.Base.GridEdit, {
dataRecordMeta: Ext.data.Record.create([
{name:"_p_record_status", type:"string"}
,{name:"MAINCODE", type:"float" }
])
,initComponent:function() {
Ext.apply(this, {
store: new Ext.data.JsonStore({
id:"storeDC100101"
,totalProperty:"totalCount"
,root:"records"
,url:"/index.aspx?_p_action=fetch&_p_form=DC1001"
,remoteSort :true
,fields:this.dataRecordMeta
})
,columns: [new Ext.grid.RowNumberer()
,{ id:"SUBJECTCODE",align:'right',
header:this.resourceBundle.FieldLabel.SUBJECTCODE||"SubjectCode",
width:350,dataIndex:'SUBJECTCODE',sortable:true,
render:function (value){
debugger ;
},
editor:new N21.DataComp.LOV5500(
{
allowBlank: false
,fieldMapping:[{column:"SUBJECTCODE",field:"SUBJECTCODE"}]
//paramMapping: [{param:"SUBJECTCODE",field:"SUBJECTCODE"}],
//selectOnFocus:true,
,cls:"x-form-text-in-grid"
,name:"SUBJECTCODE"
,id:"SUBJECTCODE"
,valueField:"SUBJECTCODE"
,displayField:"SUBJECTCODE"
}
)}
.....................
and LOV5500 :
/**
* DataControl: List of Values
* Code: LOV5500
* Type: LOOKUP
*/
Ext.ns("N21.DataComp");
N21.DataComp.LOV5500 = Ext.extend(N21.Base.Lov, {
displayField:"NAME"
,initComponent:function() {
Ext.apply(this, {
lovTitle:"Subjectcode(LOV5500)"
,view: new Ext.grid.GridPanel({
store: new Ext.data.JsonStore({
id:"storeLOV5500"
,root:"records"
,url:"indexLov.aspx?_p_action=fetch&_p_lov=LOV5500"
,remoteSort:true
,fields:[{name:"CODE",type:"float"},{name:"SUBJECTCODE",type:"string"},{name:"NAME",type:"string"}]
})
,columns: [new Ext.grid.RowNumberer(),
{ id:"CODE",align:'left',hidden:true,header:this.resourceBundle.FieldLabel.CODE||"code",width:100,dataIndex:'CODE',sortable:true}
,{ id:"SUBJECTCODE",align:'left',header:this.resourceBundle.FieldLabel.SUBJECTCODE||"subjectcode",width:100,dataIndex:'SUBJECTCODE',sortable:true}
,{ id:"NAME",align:'left',header:this.resourceBundle.FieldLabel.NAME||"name",width:200,dataIndex:'NAME',sortable:true}
]
})
,dataComponentName:"LOV5500"
,displayField:this.displayField
,lovWidth:400
,lovHeight:400
});
N21.DataComp.LOV5500.superclass.initComponent.apply(this, arguments);
}
,onRender:function() {
N21.DataComp.LOV5500.superclass.onRender.apply(this, arguments);
}
});
Ext.reg("LOV5500", N21.DataComp.LOV5500);
when
N21.DataComp.LOV5500 =Ext.extend(N21.Base.Combo....,It work .
:-?:-?:-?:-?
nan21eu
2 Sep 2008, 2:44 AM
thank you erichua
nan21eu
2 Sep 2008, 2:51 AM
Hello hxsam,
i didn't use this from a grid , however a quick and dirty solution would be the following :
In your :
editor:new N21.DataComp.LOV5500(....
add the following:
callFromGrid:this [where 'this' is your grid ]
and use the attached file for Base.Lov
In this case you must pass all the column names where you want values to be returned [including the column with the Lov editor ] in the
fieldMapping:[{column:"SUBJECTCODE",field:"SUBJECTCODE"},....
]
perhaps not a very dirty solution ...
Tell me if it works for you
hi nan21eu :
I had lost this thread url.i will try it tonight.
thank you.
Hello hxsam,
i didn't use this from a grid , however a quick and dirty solution would be the following :
In your :
editor:new N21.DataComp.LOV5500(....
add the following:
callFromGrid:this [where 'this' is your grid ]
and use the attached file for Base.Lov
In this case you must pass all the column names where you want values to be returned [including the column with the Lov editor ] in the
fieldMapping:[{column:"SUBJECTCODE",field:"SUBJECTCODE"},....
]
perhaps not a very dirty solution ...
Tell me if it works for you
hi,nan21
/**
* DataControl: Grid edit inline
* Code: DC0005
* Title: BANK
*/
Ext.ns("N21.DataComp");
N21.DataComp.DC0005 = Ext.extend(N21.Base.GridEdit, {
dataRecordMeta: Ext.data.Record.create([
{name:"_p_record_status", type:"string"}
,{name:"ID", type:"float" }
,{name:"CODE", type:"string" }
,{name:"NAME", type:"string" }
,{name:"SWIFTCODE", type:"string" }
,{name:"LOCATION_ID", type:"float" }
,{name:"CREATEDON", type:"date",dateFormat:Ext.DATE_FORMAT }
,{name:"CREATEDBY", type:"string" }
,{name:"MODIFIEDON", type:"date",dateFormat:Ext.DATE_FORMAT }
,{name:"MODIFIEDBY", type:"string" }
])
,initComponent:function() {
Ext.apply(this, {
store: new Ext.data.JsonStore({
id:"storeDC0005"
,totalProperty:"totalCount"
,root:"records"
,url:"../index.aspx?_p_action=fetch&_p_form=DC0005"
,remoteSort :true
,fields:this.dataRecordMeta
})
,columns: [new Ext.grid.RowNumberer(),
{ id:'ID',header:'Id',width:100,dataIndex:'ID',hidden:true,sortable:true,align:'right',editor:new Ext.form.NumberField({allowBlank: false,cls:"x-form-text-in-grid"})}
,{ id:'CODE',header:'Code',width:80,dataIndex:'CODE',sortable:true,editor:new Ext.form.TextField({allowBlank: false,cls:"x-form-text-in-grid"})}
,{ id:'NAME',header:'Name',width:200,dataIndex:'NAME',sortable:true,editor:new Ext.form.TextField({allowBlank: false,cls:"x-form-text-in-grid"})}
,{ id:'SWIFTCODE',header:'Swiftcode',width:80,dataIndex:'SWIFTCODE',sortable:true,
editor:new N21.DataComp.LOV5500(
{allowBlank: true,
callFromGrid:this.getView().grid,//this not null
cls:"x-form-text-in-grid",
fieldMapping:[
{column:'SUBJECTCODE',field:'SWIFTCODE'},
{column:'NAME',field:'NAME'}
]
})
}
when N21.Base.Lov.onDoSelect
,onDoSelect: function(){
//TODO: fix for Tpl !!!! ComboBox
Ext.form.TriggerField.superclass.setValue.call(this, this.getSelectedRecords()[0].get(this.displayField));
for (var i=0;i<this.fieldMapping.length;i++ ) {
if (!Ext.isEmpty(this.callFromGrid)) {//Ext.isEmpty(this.callFromGrid)=true and this.callFromGrid=undefined
this.callFromGrid.store.getAt(this.callFromGridRow).set(this.fieldMapping[i].field, this.getSelectedRecords()[0].get(this.fieldMapping[i].column));
}
else {
Ext.getCmp(this.fieldMapping[i].field).setValue(this.getSelectedRecords()[0].get(this.fieldMapping[i].column));
}
}
if(Ext.QuickTips){ // fix for floating editors interacting with DND
Ext.QuickTips.enable();
}
this.window.hide();
//this.getEl().focus();
}
and error in Ext.getCmp(this.fieldMapping[i].field) has no properties
[Break on this error] Ext.getCmp(this.fieldMapping[i].field).setValue(this.getSelectedReco...
and change 'callFromGrid:this ,' it work for IE6 ff2:
editor:new N21.DataComp.LOV5500(
{allowBlank: true,
callFromGrid:this ,
cls:"x-form-text-in-grid",
fieldMapping:[
{column:'SUBJECTCODE',field:'SWIFTCODE'},
{column:'NAME',field:'NAME'}
]
})
}
nan21eu
6 Sep 2008, 12:00 AM
sorry for my explanation,
callFromGrid:this [where 'this' is your grid ]
that's what i meant , your N21.Base.GridEdit ,
wow!!! it's amazing what you have accomplished. It must have taken a lot of work. How much time did it took to get to this point ?
tsinghua
10 Oct 2008, 11:53 PM
What time does the first beta release?
nan21eu
12 Oct 2008, 7:59 AM
thank you symx, it took some work, however not as much as one would expect. The most important point behind the application is a code generator, all the user interfaces [the dialogs loaded by menu tree ] as well as the corresponding server-side controllers are generated based on some descriptors [meta-data].
This generator is for the moment in a very "works for me" stage, however, recently i had an idea to polish it enough to be able to release it also. When / how / license, etc i don't know yet, as a hint, i'd like to be somewhere at the beginning of the next year. But don't bet on it :)
tsinghua, the initial plan was to do it in the beginning of October, as this is an open source project gets the attention only in spare time and sometimes the spare time is not enough :)
So, instead of releasing a beta in the beginning of October seems that there will be only an alpha hopefully within 1-2 weeks
thank you for your understanding
tsinghua
12 Oct 2008, 10:04 PM
thank you
ziegethief
15 Oct 2008, 3:59 AM
Really nice job!
I'm wondering if it possible to take a look at this generator? My application has a tree menu (looks almost same as yours) which I load from db with php using JSON. The content in center is gonna work in same way (php+json). The problem is that it takes too(!) long to load all (about 250 rows in db, each row has it own menu tree leaf) details I need to be shown on center panel. I know that I need it to make the same way like you did - first load only tree menu and load center contant only when you click on one of tree leafs. But I don't know how...
xv3n0m
16 Oct 2008, 1:57 AM
that is fantastic, can i download the source to learn it. coz this application match with my imagination to learn extjs.
thx.
nan21eu
19 Dec 2008, 11:41 PM
for everybody asking about source code:
Please check homepage: www.nan21.eu there you find all the links and news.
Thank you
amosspray
4 Jan 2009, 6:43 PM
I have a problem with N21.Base.Lov.js.
I used N21.Base.Lov.js in my test project,
it can work with IE7,but can't work with others(ex:firefox,Apple Safari,google ...etc).
I don't know what to solve it.
I hope someone can help or tell me what's happend and how to solve it.
THANK YOU
nan21eu
4 Jan 2009, 10:54 PM
what is the problem ?
amosspray
11 Jan 2009, 11:06 PM
I am sorry that i thought the LOV has some error. But actually, the error is caused by another mistake.
garyk
14 Jan 2009, 7:27 AM
thank you symx, it took some work, however not as much as one would expect. The most important point behind the application is a code generator, all the user interfaces [the dialogs loaded by menu tree ] as well as the corresponding server-side controllers are generated based on some descriptors [meta-data].
This generator is for the moment in a very "works for me" stage, however, recently i had an idea to polish it enough to be able to release it also. When / how / license, etc i don't know yet, as a hint, i'd like to be somewhere at the beginning of the next year. But don't bet on it :)
Yes great work so far. I can see some value in releasing the code generator, perhaps even more so than the application itself. I work with commercial ERP/CRM offerings so I know whats involved, to deliver a full suit of functionality is a *mammoth* task taking many many man years. I'm not knocking what you have done because it is excellent but you can spend half your life on this and then what? It is so tough to compete with commercial offerings that have been around for many years and are purchased because there is a network of resellers all able to support a given product.
Gary
uchup07
20 Jan 2009, 12:50 AM
can i choose multiple select in your code N21.Base.Lov.js..
I want use something like this thread http://extjs.com/forum/showthread.php?t=26146
this is my code LOV006.js
Ext.ns("N21.DataComp");
N21.DataComp.LOV006 = Ext.extend(N21.Base.Lov, {
displayField:"TITLE"
,initComponent:function() {
Ext.apply(this, {
lovTitle:"Menu Otority"
,view : new Ext.grid.GridPanel({
store: new Ext.data.JsonStore({
id:"storeLOV006"
,root:"records"
,url:"json.php?act=lovMenu"
,remoteSort:true
,fields:[{name:"id"},{name:"title"}]
}), cm: new Ext.grid.ColumnModel([
new Ext.grid.CheckboxSelectionModel(),
{id: 'ID', header: 'Identifier', hidden: true, dataIndex: 'id'},
{id: 'TITLE', header: 'Title', autoWidth: true, dataIndex: 'title'}
]), sm: new Ext.grid.CheckboxSelectionModel({
singleSelect:false,
listeners:{
beforerowselect: function(sm, row_index, keepExisting, record){
sm.suspendEvents();
if (sm.isSelected(row_index))
sm.deselectRow(row_index);
else
sm.selectRow(row_index, true);
sm.resumeEvents();
return false;
}
}
}), border: true,
deferRowRender:false,
viewConfig: { forceFit:true },
stripeRows: true
})
,dataComponentName:"LOV006"
,displayField:this.displayField
,lovHeight : 250
,lovWidth : 500
});
N21.DataComp.LOV006.superclass.initComponent.apply(this, arguments);
}
,onRender:function() {
N21.DataComp.LOV006.superclass.onRender.apply(this, arguments);
}
});
Ext.reg("LOV006", N21.DataComp.LOV006);
and this is main code DC007.js
Ext.ns("N21.DataComp");
Ext.reg("htmledit", Ext.ux.HTMLEditor);
N21.DataComp.DC007G = Ext.extend(N21.Base.GridView, {
dataRecordMeta: Ext.data.Record.create([
{name:"_p_record_status", type:"string"}
,{name:"ID", mapping: "id", type:"int" }
,{name:"GROUPNAME", mapping: "groupname", type:"string" }
,{name:"MENU_OTORITY", mapping: "menu_otority", type:"string" }
,{name:"MENU", mapping: "menu_otority", type:"string"}
,{name:"DESCRIPTION", mapping: "description", type:"string" }
,{name:"INPUT_DATE", mapping:"input_date", type:"date", dateFormat: 'Y-m-d H:i:s' }
,{name:"ADDED_BY", mapping:"added_by", type:"string"}
])
,initComponent:function() {
Ext.apply(this, {
store: new Ext.data.JsonStore({
id:"storeDC007"
,totalProperty:"totalCount"
,root:"records"
,url:"json.php?act=group"
,remoteSort :true
,fields:this.dataRecordMeta
})
,columns: [new Ext.grid.RowNumberer(),
{ id:"ID",header:this.resourceBundle.FieldLabel.ID||"Id",width:100,dataIndex:'ID',hidden:true,sortable:true}
,{ id:"GROUPNAME",header:this.resourceBundle.FieldLabel.GROUPNAME||"Group Name",width:120,dataIndex:'GROUPNAME',sortable:true}
,{ id:"DESCRIPTION",header:this.resourceBundle.FieldLabel.DESCRIPTION||"Description",width:120,dataIndex:'DESCRIPTION',sortable:true}
,{ id:"INPUT_DATE",header:this.resourceBundle.FieldLabel.INPUT_DATE||"Input Date",width:120,dataIndex:'INPUT_DATE',sortable:true, renderer: Ext.util.Format.dateRenderer('d-m-Y')}
,{ id:"ADDED_BY",header:this.resourceBundle.FieldLabel.ADDED_BY||"Author",width:120,dataIndex:'ADDED_BY',sortable:true}
]
,queryFields: [
{xtype: "hidden",name:"QRY_ID",id:"DC007_QRY_ID",width:120,fieldLabel: this.resourceBundle.FieldLabel.ID||"Id"}
,{xtype: "textfield",name:"QRY_TITLE",id:"DC007_QRY_TITLE",width:120,fieldLabel: this.resourceBundle.FieldLabel.TITLE||"Judul"}
]
,dataComponentName:"DC007G"
,viewConfig:{forceFit:true}
,queryArraySize:20
,toolbarConfig:"STANDARD"
});
N21.DataComp.DC007G.superclass.initComponent.apply(this, arguments);
}
,onRender:function() {
N21.DataComp.DC007G.superclass.onRender.apply(this, arguments);
}
,newDataRecord:function() {
return new this.dataRecordMeta({_p_record_status:"insert", ID:"", GROUPNAME: "", DESCRIPTION:"", MENU_OTORITY:"", INPUT_DATE: "", ADDED_BY: "", MENU: ""});
}
});
Ext.reg("DC007G", N21.DataComp.DC007G);
/**
* Data Component: DC007F
*/
Ext.ns("N21.DataComp");
N21.DataComp.DC007F = Ext.extend(N21.Base.EditForm, {
fields: new Ext.util.MixedCollection()
,dataRecordMeta : N21.DataComp.DC007G.prototype.dataRecordMeta
,layoutItems: new Ext.util.MixedCollection()
,initComponent:function() {
this.fields.add("_p_record_status",{xtype: "hidden", allowBlank: true, fieldLabel: "record_status", selectOnFocus: false, style: "", name: "_p_record_status"});
this.fields.add("ID",{xtype: "hidden",name:"ID",id:"DC007F_ID",dataIndex:"ID",width:100,allowBlank:false,labelSeparator:":*" ,fieldLabel: this.resourceBundle.FieldLabel.ID||"Id",insert_allowed:true,update_allowed:true});
this.fields.add("GROUPNAME",{xtype: "textfield",name:"GROUPNAME",id:"DC007F_GROUPNAME",dataIndex:"GROUPNAME",width:200,allowBlank:false,fieldLabel: this.resourceBundle.FieldLabel.GROUPNAME||"Group Name",insert_allowed:true,update_allowed:true});
this.fields.add("MENU_OTORITY", {xtype:"hidden", name:"MENU_OTORITY", id:"DC007F_MENU_OTORITY", dataIndex:"MENU_OTORITY", width:100, allowBlank:true, fieldLabel: this.resourceBundle.FieldLabel.MENU_OTORITY||"Menu Otority", insert_allowed:true, update_allowed:true});
/**************************/
/** THIS IS THE PROBLEM FIELD **/
/**************************/
this.fields.add("MENU",
{
xtype:"LOV006",
fieldLabel: this.resourceBundle.FieldLabel.MENU_OTORITY||"Menu Otority",
id: 'DC007F_MENU',
name: 'MENU',
allowBlank: true,
multiSelect: true,
lovHeight : 250,
lovWidth : 500,
width: 150,
minItem : 0,
valueField: 'id',
displayField: 'title',
/*displayValue: '',
hiddenValue: '', */
valueFieldName: "MENU_OTORITY",
valueFieldId: "DC007F_MENU_OTORITY",
textarea : true,
showOnFocus : true,
insert_allowed:true,
update_allowed:true
}
);
/*************************/
/***** END PROBLEM *********/
/************************/
this.fields.add("DESCRIPTION", {xtype: "htmledit",name: 'DESCRIPTION',fieldLabel:this.resourceBundle.FieldLabel.DESCRIPTION||"Description",dataIndex: 'DESCRIPTION',styles: ['htmleditor.css'],plugins: new Ext.ux.HTMLEditorImage(),allowBlank: false,width: 600,height: 300,insert_allowed:true,update_allowed:true});
Ext.apply(this, {
items:[
this.fields.get("_p_record_status")
,this.fields.get("ID")
,this.fields.get("GROUPNAME")
,this.fields.get("MENU_OTORITY")
,this.fields.get("MENU")
,this.fields.get("DESCRIPTION")
]
,border:false
,layout:"form"
,defaults:{labelWidth:110}
,frame:true
,width: "100%"
,dataComponentName:"DC007F"
,toolbarConfig:"STANDARD"
});
N21.DataComp.DC007F.superclass.initComponent.apply(this, arguments);
}
,onRender:function() {
N21.DataComp.DC007F.superclass.onRender.apply(this, arguments);
}
,newDataRecord:function() {
return new this.dataRecordMeta({_p_record_status:"insert", ID:"", GROUPNAME: "", DESCRIPTION:"", MENU_OTORITY:"", INPUT_DATE: "", ADDED_BY: "", MENU: ""});
}
});
Ext.reg("DC007F", N21.DataComp.DC007F);
/**
* DataControl: Grid with Edit Form
* Code: DC007
*/
Ext.ns("N21.DataComp");
N21.DataComp.DC007 = Ext.extend(N21.Base.GridEditForm, {
initComponent:function() {
Ext.apply(this, {
autoScroll:false
,layout:"border"
,dataComponentName:"DC007"
,masterName:"DC007G"
,detailName:"DC007F"
,mdLayout:"tab"
,border: false
,items: [
{
xtype:"tabpanel"
,id:"MDTab"
,region:"center"
,defaults:{layout:"fit"}
,activeItem:0
,tabPosition: "bottom"
,items: [{
title:"List"
,xtype: "DC007G"
,id: "DC007G"
,loadMask:true
,height:350
},{
title:"Edit Record"
,xtype:"DC007F"
,id:"DC007F"
,height:350
,frame:true
,autoScroll:true
,layout:"form"
}]
}
]
});
N21.DataComp.DC007.superclass.initComponent.apply(this, arguments);
}
});
Ext.reg("DC007", N21.DataComp.DC007);
sorry for my bad english
mjhaston
22 Jan 2009, 12:34 PM
How do you get this effect with the filters over-top of the grid? I like it. I might like the filters in the East, but I have a feeling that's more trouble.
Can you point me to the code for this? I downloaded the 0.5 zip file, but can't seem to find it.
nan21eu
27 Jan 2009, 5:26 AM
uchup07 (http://extjs.com/forum/member.php?u=48251) : the LOV component is intended to be a filterable, paginated list . With the new release {0.7} which is uploaded on the demo site [ source code published also in a couple of days ] it is such. In this situation a multi-selection feature doesn't really fit the picture, what if the results you'd like to select are in different pages?
Possible solutions however would be:
1) use the standard ext-js multi-select combo
2) setup N21.Base.LOV without pagination [ as in version 0.5 ] and add some code to join the selected lines. Perhaps i'll implement this feature in the next month, if it is not urgent for you wait for this.
3) If it is urgent, try the following approach : [ it is just a pseudo code, not the actual copy-paste source ]
in function onDoSelect: of N21.Base.Lov:
where the value is returned change it from :
Ext.getCmp(this.fieldMapping[i].field).setValue(this.getSelectedRecords()[0].get(this.fieldMapping[i].column));
to something like
Ext.getCmp(this.fieldMapping[i].field).setValue(this.joinSelectedRecordsColumn(this.fieldMapping[i].column) );
where joinSelectedRecordsColumn is
joinSelectedRecordsColumn: function(columnName) {
var result;
for (var i=0, i< this.getSelectedRecords().length, i++ ) {
result += (i>0)?',':'';
result += this.getSelectedRecords()[i].get(columnName);
}
return result ;
}
the same for both branches of the
if (!Ext.isEmpty(this.callFromGrid)) .....
hope this helps...
if problems let me know
nan21eu
27 Jan 2009, 5:36 AM
mjhaston:
the code you're looking for is in initComponent() of the base grids, i.e :
N21.Base.GridView and N21.Base.GridEdit
nan21eu
27 Jan 2009, 6:21 AM
Note on filters: wildcard for string is %, for character is _ as in Oracle
If you want to filter "abcd":
Starts with "ab" use: ab%
Ends with "cd" use: %cd
...etc
a search with ab% finds the "abcd" string , however the "ab_" does not .
The "ab_" would find any of the following: "aba", "abb" , "ab1" , .....
It's just an issue which might not be obvious for everybody
at a certain moment there will be a documentation also :)
uchup07
27 Jan 2009, 9:32 PM
this is very urgent for me, so I choose point 3 from you. If I'm right, I change this code just what you say.
This is old code N21.Base.LOV:
,onDoSelect: function(){
//TODO: fix for Tpl !!!! ComboBox
Ext.form.TriggerField.superclass.setValue.call(this, this.getSelectedRecords()[0].get(this.displayField));
for (var i=0;i<this.fieldMapping.length;i++ ) {
if (!Ext.isEmpty(this.callFromGrid)) {
this.callFromGrid.store.getAt(this.callFromGridRow).set(this.fieldMapping[i].field, this.getSelectedRecords()[0].get(this.fieldMapping[i].column));
}
else {
Ext.getCmp(this.fieldMapping[i].field).setValue(this.getSelectedRecords()[0].get(this.fieldMapping[i].column));
}
}
if(Ext.QuickTips){ // fix for floating editors interacting with DND
Ext.QuickTips.enable();
}
this.window.hide();
//this.getEl().focus();
}
and this is new code
,onDoSelect: function(){
//TODO: fix for Tpl !!!! ComboBox
Ext.form.TriggerField.superclass.setValue.call(this, this.getSelectedRecords()[0].get(this.displayField));
for (var i=0;i<this.fieldMapping.length;i++ ) {
if (!Ext.isEmpty(this.callFromGrid)) {
this.callFromGrid.store.getAt(this.callFromGridRow).set(this.fieldMapping[i].field, this.joinSelectedRecordsColumn(this.fieldMapping[i].column));
}
else {
Ext.getCmp(this.fieldMapping[i].field).setValue(this.joinSelectedRecordsColumn(this.fieldMapping[i].column) );
}
}
if(Ext.QuickTips){ // fix for floating editors interacting with DND
Ext.QuickTips.enable();
}
this.window.hide();
//this.getEl().focus();
}
,joinSelectedRecordsColumn: function(columnName) {
var result;
for (var i=0; i< this.getSelectedRecords().length; i++ ) {
result += (i>0)? this.valueSeparator :'';
result += this.getSelectedRecords()[i].get(columnName);
}
return result ;
}
there is no effect. When I choose more than 1 on lov grid, there is still showing 1 select on textbox where I choose from. Like showing in picture:
11656
11657
more problem when I show on firebug, in input form type hidden It should be change to what I selected, but there is no change.
Can you help me?
nan21eu
28 Jan 2009, 1:00 AM
I just tried to includ the code in my project and works.
Here it is:
Base.Lov:
,joinSelectedRecordsColumn: function(columnName) {
var result = '';
// initialise it to avoid an undefined at the beginning of the returned string
for (var i=0; i< this.getSelectedRecords().length; i++ ) {
result += (i>0)? this.valueSeparator :'';
result += this.getSelectedRecords()[i].get(columnName);
}
return result ;
}
The lov instance :
/* N21 eBusiness Suite
* Copyright: Nan21 Electronics srl
* Generated content.
* LOV0017: Products
*/
Ext.ns("N21.DataComp");
N21.DataComp.LOV0017 = Ext.extend(N21.Base.Lov, {
displayField:"NAME"
,queryArraySize:40
,initComponent:function() {
Ext.apply(this, {
lovTitle:"Products (LOV0017)"
,view: new Ext.grid.GridPanel({
store: new Ext.data.JsonStore({
id:"storeLOV0017"
,totalProperty:"totalCount"
,root:"records"
,url:"frmMain.php?_p_form=LOV0017&_p_action=fetch&_p_data_format=json"
,remoteSort:true
,fields:[{name:"CODE",type:"string"},{name:"ID",type:"float"},{name:"NAME",type:"string"},{name:"UOM_CODE",type:"string"}]
})
,columns: [ //new Ext.grid.RowNumberer() ,
new Ext.grid.CheckboxSelectionModel(),
{id:"ID",header:this.resourceBundle.FieldLabel.ID||"Id",width:100,hidden :true,dataIndex:'ID',sortable:true,align:'right'}
,{id:"CODE",header:this.resourceBundle.FieldLabel.CODE||"Code",width:100,dataIndex:'CODE',sortable:true}
,{id:"NAME",header:this.resourceBundle.FieldLabel.NAME||"Name",width:200,dataIndex:'NAME',sortable:true}
,{id:"UOM_CODE",header:this.resourceBundle.FieldLabel.UOM_CODE||"Uom",width:100,dataIndex:'UOM_CODE',sortable:true}
]
, sm: new Ext.grid.CheckboxSelectionModel({
singleSelect:false})
})
,dataComponentName:"LOV0017"
,displayField:this.displayField
,lovWidth:640
,multiSelect:true
,lovHeight:400
,queryFields:[["CODE", this.resourceBundle.FieldLabel.CODE||"Code"],["NAME", this.resourceBundle.FieldLabel.NAME||"Name"]]
});
N21.DataComp.LOV0017.superclass.initComponent.apply(this, arguments);
}
,onRender:function() {
N21.DataComp.LOV0017.superclass.onRender.apply(this, arguments);
}
});
Ext.reg("LOV0017", N21.DataComp.LOV0017);
and the field definition(i tried it for a query field):
this.queryFields.add("PRODUCT_NAME",new N21.DataComp.LOV0017({name:"QRY_PRODUCT_NAME", id:"DC0077F_QRY_PRODUCT_NAME",fieldLabel: this.resourceBundle.FieldLabel.PRODUCT_NAME||"Product", allowBlank:true,width:250,selectOnFocus:true, fieldMapping:[{column:"ID",field:"DC0077F_QRY_PRODUCT_ID"},{column:"NAME",field:"DC0077F_QRY_PRODUCT_NAME"}]}));
nan21eu
28 Jan 2009, 1:08 AM
here some screenshots
uchup07
1 Feb 2009, 11:51 PM
But I still don't understand about the field definition that u give it to me. I'm not used query field. Can u give me more details about your code?
Thanks before
nan21eu
2 Feb 2009, 12:58 AM
Doesn't matter if it is a query field or a regular form edit field, the idea is the same.
Suppose your LOV displays the result for the following sql statement:
select ID, NAME, CITY from companies ...
usually you would like to get the "NAME" column returned into your field.
So you set the LOV component displayField = "NAME"
and you use this LOV in several situations:
1) from the selected record you need only the "NAME" column returned into the field. Basic situation, should be clear.
2) You need all the columns to be returned. Lets say the following:
ID into a COMPANY_ID form field
NAME into a COMPANY_NAME form field
CITY into a DELIVERY_ADRESS_CITY form field
How do you handle this with the 2 basic properties valueField and displayField?
I couldn't figure out a way to do it.
So a possible working solution was to specify a new property: fieldMapping, which implements the above scenario:
fieldMapping:[
{column:"ID",field:"DC0077F_COMPANY_ID"},
{column:"NAME",field:"DC0077F_COMPANY_NAME"},
{column:"CITY",field:"DC0077F_DELIVERY_ADRESS_CITY"}
] the onDoSelect function does exactly this:
It sets the default display field and then checks the fieldMapping property and populates the fields with the associated columns based on the mappings.
3) you could ask in case you need only 2 fields the ID and the NAME columns why to use this fieldMapping approach instead of the valueField and DisplayField approach which works for this situation.
I would then return the question why bother to use 2 different approaches for the same problem when one solution can handle all ?
In my opinion the correct way would be to use the displayField if you need one column to be returned, the fieldMapping if you need more
2 columns usage:
fieldMapping:[
{column:"ID",field:"DC0077F_COMPANY_ID"},
{column:"NAME",field:"DC0077F_COMPANY_NAME"}
]
With the actual implementation of the multi-selection feature [the piece code in my previous post] you'll have to set the fieldMapping even if you need only the NAME column to be returned .
Or change the line:
Ext.form.TriggerField.superclass.setValue.call(this, this.getSelectedRecords()[0].get(this.displayField));
to
Ext.form.TriggerField.superclass.setValue.call(this, this.joinSelectedRecordsColumn(this.displayField));
Does this help ?
uchup07
2 Feb 2009, 1:33 AM
I have been tried your code but when I selected them, on firebug it say undefined, why?
,joinSelectedRecordsColumn: function(columnName) {
var result = '';
// initialise it to avoid an undefined at the beginning of the returned string
for (var i=0; i< this.getSelectedRecords().length; i++ ) {
result += (i>0)? this.valueSeparator :'';
result += this.getSelectedRecords()[i].get(columnName);
}
console.log(result);
return result ;
}
this onSelect code:
,onDoSelect: function(){
//TODO: fix for Tpl !!!! ComboBox
Ext.form.TriggerField.superclass.setValue.call(this, this.getSelectedRecords()[0].get(this.displayField));
for (var i=0;i<this.fieldMapping.length;i++ ) {
if (!Ext.isEmpty(this.callFromGrid)) {
this.callFromGrid.store.getAt(this.callFromGridRow).set(this.fieldMapping[i].field, this.joinSelectedRecordsColumn(this.fieldMapping[i].column));
}
else {
Ext.getCmp(this.fieldMapping[i].field).setValue(this.joinSelectedRecordsColumn(this.fieldMapping[i].column) );
}
}
if(Ext.QuickTips){ // fix for floating editors interacting with DND
Ext.QuickTips.enable();
}
this.window.hide();
//this.getEl().focus();
}
my lov instance:
Ext.ns("N21.DataComp");
N21.DataComp.LOV006 = Ext.extend(N21.Base.Lov, {
displayField:"NAME"
,queryArraySize:40
,initComponent:function() {
Ext.apply(this, {
lovTitle:"MENU"
,view: new Ext.grid.GridPanel({
store: new Ext.data.JsonStore({
id:"storeLOV006"
,totalProperty:"totalCount"
,root:"records"
,url:"json.php?act=lovMenu"
,remoteSort:true
,fields:[{name:"id",type:"int"},{name:"title",type:"string"}]
})
,columns: [ //new Ext.grid.RowNumberer() ,
new Ext.grid.CheckboxSelectionModel(),
{id:"ID",header:"Id",width:100,hidden :true,dataIndex:'id',sortable:true,align:'right'}
,{id:"TITLE",header:"Judul",width:200,dataIndex:'title',sortable:true}
]
, sm: new Ext.grid.CheckboxSelectionModel({
singleSelect:false})
})
,dataComponentName:"LOV006"
,displayField:this.displayField
,lovWidth:640
,multiSelect:true
,lovHeight:400
});
N21.DataComp.LOV006.superclass.initComponent.apply(this, arguments);
}
,onRender:function() {
N21.DataComp.LOV006.superclass.onRender.apply(this, arguments);
}
});
Ext.reg("LOV006", N21.DataComp.LOV006);
and this is the field definition:
this.fields.add("MENU",new N21.DataComp.LOV006({name:"MENU", id:"DC007F_MENU",fieldLabel: this.resourceBundle.FieldLabel.MENU_OTORITY||"Menu Otority",allowBlank:false,labelSeparator:":*",width:250,insert_allowed:true,displayField: 'title',update_allowed:true,selectOnFocus:true,fieldMapping:[{column:"ID",field:"DC007F_MENU_OTORITY"},{column:"TITLE",field:"DC007F_MENU_ITEMS"}]}));
Do I'm right with this code?
uchup07
2 Feb 2009, 1:54 AM
sorry my bad, I fixed and it works...thx for your help nan21
nan21eu
2 Feb 2009, 2:38 AM
i suppose you didn't have one of the fields : C007F_MENU_OTORITY or DC007F_MENU_ITEMS
anyway you're welcome
Fangrn
22 Feb 2009, 2:33 AM
It's very good!
We are looking for similar projects this study,thanks!
naifco
25 Feb 2009, 1:36 PM
Thanks , very good projects
can i know which php framework you used for this project? e.g : zendframework or other framework?
glaweh
25 Feb 2009, 11:16 PM
This LOV doesn't work, in : Administration - System - Access Rights - DC Role Permissions
Value in the column DC (on text) doesn't have any value after i select the data from LOV form UI_DC.
Need help, thank's
alien3d
17 Apr 2009, 5:05 AM
I also make erp system.
My comment
The interface are quite clumsy.
The information require as ERP is non complete.
E.g Inventory :
Where to setup general account
Where to depreciate item.
Where to disposed item.
Where to revaluete item.
Where to write off item.
1.Study other develop system ERP as Sap,Sage and others.Learn from customer implement ERP.
nan21eu
21 Apr 2009, 1:08 AM
1) for those asking about framework , it is an own "framework" a bunch of classes implementing base functionalities, tailored to my specific needs.
2) for those asking about business functionalities: it is still a work in progress and there are many things missing yet, not only those mentioned. Step by step will be implemented. About the SAP and Sage comparison, i'm really impressed to be compared to them :) however as you might guess there is quite a difference between us: thousands of people working for years vs a couple of guys doing some stuff in their spare time.
b4ngb4ng
3 Sep 2009, 8:05 PM
It's great
IS there for database Mysql / PostgreSQL version
If Mysql / PostgreSQL be considered, it will be very nice
thanks
dryphon
6 May 2010, 2:48 AM
Project dead or live?
tortexy
22 Jul 2010, 4:12 AM
Hey!
This is cool stuff!
Very well done guys!
devtig
21 Sep 2010, 2:09 AM
Dead like any software project after a while that meets these criteria:
-no paying customer AND
-no predefined, clear specs AND
-no community that helps building
vijay.comp
23 Nov 2010, 8:48 PM
thanks dear, gud example for lerner.....
kunal.kuntalam
12 Feb 2011, 8:13 PM
Hi Nan21,
All the links provided in the thread seems to be broken? Moved somewhere?
-Kunal
nan21eu
22 Feb 2011, 11:03 PM
Yes, moved to www.nan21.net
the new application's name is DNet eBusiness Suite
nan21eu
22 Feb 2011, 11:26 PM
Actually the thread title is not entirely true any more as the new project is not oracle / php , but it became java server-side and database independent (prefered db's are oracle and mysql ).
nan21eu
7 Oct 2011, 11:34 AM
Milestone 2 ( 1.0-M2 ) available using extjs 4 ; although there are lots of differences in 4 compared to 3 the migration is not really so difficult - and is definitely worth the trouble;
great work sencha team
Powered by vBulletin® Version 4.1.5 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.