I'm working on the Jspresso framework (launching the project with Swing). I have made N-N bidirectional relationships between components, but the fields corresponding to these relationships do not appear. For example, I have a relationship between projects and students (a student can have many projects, a project can have many students). When I add a project and open it in its detail view, I can create a new student and add it to the project BUT I can not add an existing student to the project neither search a project according to its students in the search view. Is there a way to display this ?
Here is my view.groovy
// Implement your views here using the SJS DSL.
form('Project.pane',
parent:'decoratedView',
labelsPosition:'ASIDE',
columnCount:2,
fields: ['name','students','technologies','usesTrainers','technicalTrainers']){
actionMap{
actionList('FILE'){
action(ref:'saveModuleObjectFrontAction')
action(ref:'reloadModuleObjectFrontAction')
}
}
}
table'Project-students.table',
parent:'decoratedView',
actionMap:'masterDetailActionMap'
split_vertical'Project.proj.view',
model:'Project',
top:'Project.pane',
bottom:'Project-students.table'
form('Student.pane',
parent:'decoratedView',
labelsPosition:'ASIDE',
columnCount:2){
actionMap{
actionList('FILE'){
action(ref:'saveModuleObjectFrontAction')
action(ref:'reloadModuleObjectFrontAction')
}
}
}
table'Student-technologies.table',
parent:'decoratedView',
actionMap:'masterDetailActionMap'
split_vertical'Student.proj.view',
model:'Student',
top:'Student.pane',
bottom:'Student-technologies.table'
form('Trainer.pane',
parent:'decoratedView',
labelsPosition:'ASIDE',
columnCount:5)
form('Technology.pane',
parent:'decoratedView',
labelsPosition:'ASIDE',
columnCount:5)
And here is my model.groovy
// Implement your domain here using the SJS DSL.
Interface('Traceable',
interceptors: 'TraceableLifecycleInterceptor',
uncloned: ['createTimestamp',
'lastUpdateTimestamp','lastUpdatedBy','createdBy']) {
string_64 'createdBy',readOnly:true
date_time 'createTimestamp', timeZoneAware: true, readOnly: true
string_64 'lastUpdatedBy', readOnly:true
date_time 'lastUpdateTimestamp', timeZoneAware: true, readOnly: true
}
Entity ('Project', extend:'Traceable',toString:'name',
icon:'project.png',
rendered: ['name','lastUpdateTimestamp','lastUpdatedBy','createTimestamp','createdBy'],
queryable: ['name']){
string_64 'name'
set 'technologies', composition:true, ref:'Technology'
set 'technicalTrainers', composition:true, ref:'Trainer'
set 'usesTrainers', composition:true, ref:'Trainer'
set 'students', composition:true, ref:'Student'
}
Entity ('Technology', extend:'Traceable',toString:'name',
icon:'technology.png',
rendered: ['name','lastUpdateTimestamp','lastUpdatedBy','createTimestamp','createdBy'],
queryable: ['name']){
string_64 'name'
set 'projects', ref:'Project', reverse:'Project-technologies'
set 'studentsAbleToUseIt', ref:'Technology', reverse:'Student-technologies'
set 'trainersAbleToTeachIt', ref:'Technology', reverse:'Trainer-technologies'
}
Interface ('Person', extend:'Traceable'){
string_64 'lastname'
string_64 'firstname'
date_time 'createTimestamp', timeZoneAware: true, readOnly: true
date_time 'lastUpdateTimestamp', timeZoneAware: true, readOnly: true
}
Entity ('Trainer',
extend: 'Person',
toString:'firstname',
icon:'trainer.png',
rendered: ['firstname','lastname','lastUpdateTimestamp','lastUpdatedBy','createTimestamp','createdBy'],
queryable: ['firstname','lastname']){
set 'projectsAsTechnicalTrainer', ref:'Project', reverse:'Project-technicalTrainers'
set 'projectsAsUsesTrainer', ref:'Project', reverse:'Project-usesTrainers'
set 'technologies', composition:true, ref:'Technology'
date_time 'createTimestamp', timeZoneAware: true, readOnly: true
date_time 'lastUpdateTimestamp', timeZoneAware: true, readOnly: true
}
Entity ('Student',
extend: 'Person',
toString:'firstname',
icon:'student.png',
rendered: ['firstname','lastname','lastUpdateTimestamp','lastUpdatedBy','createTimestamp','createdBy'],
queryable: ['firstname','lastname']){
set 'technologies', composition:true, ref:'Technology'
set 'projects', ref:'Project', reverse:'Project-students'
date_time 'createTimestamp', timeZoneAware: true, readOnly: true
date_time 'lastUpdateTimestamp', timeZoneAware: true, readOnly: true
}
You can definitely achieve both goals quite easily.
1/ A
N-Nrelationship can simply be regarded as two1-Nrelationships. So you can use theProject-studentsrelationship on aProjectoriented view and theStudent-projectson a Student oriented view. You can either use 2 different filter modules (one onProjectand one onStudent) or complement yourProject.proj.viewin order to add a second level of detail by adding an extra table that will presents theStudent-projectsof the selected student in the 1st table detail.Something like :
2/ Regarding the ability to select and add an existing
ProjectorStudentto the respective collections, you can use a custom LOV action as explained in the 1st chapter of the Jspresso-CE reference documentation.Something like :
3/ As for filtering
ProjectbyStudent(or the reverse), Jspresso supports defining collection properties as filter properties. In that case, the filter view will install a LOV for the student to filter the Projects for.If you want to have it by default on each and every Project filter view, declare it directly on the model.
Something like :