Merge branch 'develop' of git:/git/scipro/scipro into develop

This commit is contained in:
Niklas Herder 2012-03-20 11:58:23 +01:00
commit 1187cdcdf9
48 changed files with 1212 additions and 193 deletions
src
main
test/java/se/su/dsv/scipro/match

@ -3,13 +3,13 @@
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<body>
<wicket:extend>
<div class="span-22 last append-bottom">
<div wicket:id="menuPanel"></div>
</div>
<div class="span-22 last">
<div wicket:id="feedbackPanel"></div>
<div class="span-5 append-1" wicket:id="menuPanel"></div>
<div class="span-15 last">
<wicket:child />
</div>
</div>
</wicket:extend>
</body>
</html>

@ -46,7 +46,7 @@ public abstract class AbstractAdminMatchPage extends AbstractAdminPage {
@Override
protected MenuType getMenuType() {
return MenuType.VERTICAL;
return MenuType.HORIZONTAL;
}
});

@ -30,6 +30,7 @@ public abstract class AbstractAdminStatisticsPage extends AbstractAdminPage {
protected List<MenuItem> getItemList() {
final List<MenuItem> items = new ArrayList<MenuItem>();
items.add(new MenuItem("Supervisor keywords", AdminSupervisorKeywordsPage.class));
items.add(new MenuItem("Project ideas", AdminProjectIdeaStatisticPage.class));
return items;
}

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<body>
<wicket:extend>
<div wicket:id="projectIdeaStatisticPanel"></div>
</wicket:extend>
</body>
</html>

@ -0,0 +1,19 @@
package se.su.dsv.scipro.admin.pages;
import org.apache.wicket.PageParameters;
import se.su.dsv.scipro.admin.pages.AbstractAdminStatisticsPage;
import se.su.dsv.scipro.admin.panels.AdminProjectIdeaStatisticPanel;
import se.su.dsv.scipro.admin.panels.match.AdminSupervisorKeywordPanel;
import se.su.dsv.scipro.security.auth.Authorization;
import se.su.dsv.scipro.security.auth.roles.Roles;
@Authorization(authorizedRoles={Roles.ADMIN})
public class AdminProjectIdeaStatisticPage extends AbstractAdminStatisticsPage {
public AdminProjectIdeaStatisticPage(PageParameters pp) {
super(pp);
add(new AdminProjectIdeaStatisticPanel("projectIdeaStatisticPanel"));
}
}

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8"/>
</head>
<body>
<wicket:panel>
<form wicket:id="form">
<div>
<wicket:enclosure child="identifier">
<div class="info-box rounded-box">This project is synchronized with remote systems, changes made to it
may be overwritten if the remote system updates the projects data (external identifier: <span
wicket:id="identifier">externalId</span>)
</div>
</wicket:enclosure>
</div>
<div wicket:id="wmc">
<div wicket:id="feedbackPanel"></div>
<div><b>Title:</b></div>
<div class="append-bottom"><input wicket:id="titleField"/></div>
<div><b>Level:</b></div>
<div class="append-bottom"><span wicket:id="level"></span></div>
<div><b>Head supervisor:</b></div>
<div class="append-bottom"><input wicket:id="headsupervisorField"/></div>
<div><b>Students:</b></div>
<div wicket:id="studentPanel" class="append-bottom"></div>
<div><b>Project followers:</b></div>
<div wicket:id="followerPanel" class="append-bottom"></div>
<div>
<button wicket:id="saveButton">Save</button>
</div>
</div>
</form>
</wicket:panel>
</body>
</html>

@ -0,0 +1,150 @@
package se.su.dsv.scipro.admin.panels;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.RadioChoice;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import se.su.dsv.scipro.data.dao.interfaces.ProjectClassDao;
import se.su.dsv.scipro.data.dao.interfaces.ProjectDao;
import se.su.dsv.scipro.data.dataobjects.Employee;
import se.su.dsv.scipro.data.dataobjects.Project;
import se.su.dsv.scipro.reusable.AddRemoveProjectFollowerPanel;
import se.su.dsv.scipro.reusable.AddRemoveStudentsPanel;
import se.su.dsv.scipro.reusable.EmployeeAutoComplete;
/**
* @author: fred-fri
* date: 2012 03 15
*/
public abstract class AdminEditProject extends Panel {
private static final long serialVersionUID = -8553559034214432156L;
@SpringBean
ProjectClassDao projectClassDao;
@SpringBean
ProjectDao projectDao;
/**
* Override this method to use AJAX
* @param target
*/
public abstract void onUpdate(AjaxRequestTarget target);
public AdminEditProject(String id, IModel<Project> model) {
super(id, model);
add(new ProjectForm("form", model));
}
private class ProjectForm extends Form {
private static final long serialVersionUID = 5784218491663983845L;
private WebMarkupContainer wmc;
private TextField<String> titleField;
private RadioChoice level;
private AddRemoveStudentsPanel studentsPanel;
private EmployeeAutoComplete headsupervisorField;
private AddRemoveProjectFollowerPanel followerPanel;
private FeedbackPanel feedbackPanel;
public ProjectForm(String id, final IModel<Project> model) {
super(id, model);
final Label externalIdentifier = new Label("identifier", String.valueOf(model.getObject().getIdentifier()));
add(externalIdentifier);
externalIdentifier.setVisible(model.getObject().getIdentifier() != null);
add(wmc = new WebMarkupContainer("wmc"));
wmc.setEnabled(isEditable());
wmc.add(feedbackPanel = new FeedbackPanel("feedbackPanel"));
feedbackPanel.setOutputMarkupId(true);
wmc.add(titleField = new TextField<String>("titleField", new PropertyModel(model.getObject(), "title")));
wmc.add(level = new RadioChoice("level", new PropertyModel(model.getObject(), "projectClass"), projectClassDao.findAll()));
wmc.add(studentsPanel = new AddRemoveStudentsPanel("studentPanel", model.getObject().getProjectParticipants()) {
@Override
public void onUpdate(AjaxRequestTarget target) {
//do nothing
}
});
//TODO: we need to set this one to the one already set in the project, how?
wmc.add(headsupervisorField = new EmployeeAutoComplete("headsupervisorField") {
@Override
public void action(AjaxRequestTarget pTarget, Employee newSelection) {
//do nothing
}
});
headsupervisorField.setModelObject(model.getObject().getHeadSupervisor());
//we need to create any follower object that doesnt already exist with projectfollowerdao AND save project
wmc.add(followerPanel = new AddRemoveProjectFollowerPanel("followerPanel", model.getObject().getProjectFollowers(), model) {
@Override
public void onUpdate(AjaxRequestTarget target) {
//do nothing
}
});
wmc.add(new AjaxButton("saveButton") {
private static final long serialVersionUID = 1L;
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
boolean hasFailed = false;
target.addComponent(feedbackPanel);
if(titleField.getModelObject() == null || titleField.getModelObject().isEmpty()){
error("Enter a title");
hasFailed = true;
}
if(level.getModelObject() == null){
error("Select a level");
hasFailed = true;
}
if (headsupervisorField.getModelObject() == null
|| headsupervisorField.getInput() == null
|| headsupervisorField.getInput().isEmpty()
|| !headsupervisorField.getInput().equals(headsupervisorField.getModelObject().getNameAsString())){
error("Select a head supervisor");
hasFailed = true;
}
if (studentsPanel.getStudentSet() == null || studentsPanel.getStudentSet().isEmpty()){
error("Add at least one student");
hasFailed = true;
}
if (hasFailed == true){
System.out.println("FAIL");
}
else {
System.out.println("GREEN LIGHT");
Project p = model.getObject();
p.setHeadSupervisor(headsupervisorField.getModelObject());
p.setProjectParticipants(studentsPanel.getStudentSet());
p.setProjectFollowers(followerPanel.getProjectFollowerSet());
model.setObject(projectDao.save(p));
onUpdate(target);
}
}
@Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
target.addComponent(feedbackPanel);
}
});
}
}
public abstract boolean isEditable();
}

@ -171,7 +171,6 @@ public class AdminListCheckListTemplatePanel extends Panel{
@Override
protected void populateItem(final ListItem<CheckListTemplate> item) {
Label templateName = new Label("templateName", new PropertyModel<String>(item.getModel(),"name"));
Label templateOwner = new Label("templateOwner", new PropertyModel<String>(item.getModel(), "creator"));
Label templateOuestion = new Label("templateOuestion", new PropertyModel<String>(item.getModel(), "numberOfQuestions"));
String labelMsg = getChecklistCategoryString(item.getModelObject().getCategories());
@ -295,7 +294,6 @@ public class AdminListCheckListTemplatePanel extends Panel{
};
templateLink.add(templateName);
item.add(categoriesLabel);
item.add(templateOwner);
item.add(templateOuestion);
item.add(templateLink);
}

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<body>
<wicket:panel>
<div wicket:id="container">
<table class="rounded-corner">
<thead>
<tr>
<th class="rounded-left-top">Application period</th><th>End date</th><th>Number of students</th>
</tr>
</thead>
<tbody>
<tr wicket:id="periodList">
<!-- <td><span wicket:id="name"></span></</td> -->
<td wicket:id="applicationPeriodName"></td>
<td wicket:id="applicationPeriodEndDate"></td>
<td wicket:id="numberOfStudents"></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" class="rounded-foot">&nbsp;</td>
</tr>
</tfoot>
</table>
</div>
<div wicket:id="nav"></div>
</wicket:panel>
</body>
</html>

@ -0,0 +1,80 @@
package se.su.dsv.scipro.admin.panels;
import java.util.List;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.navigation.paging.PagingNavigator;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.spring.injection.annot.SpringBean;
import se.su.dsv.scipro.match.dao.interfaces.ApplicationPeriodDao;
import se.su.dsv.scipro.match.dataobject.ApplicationPeriod;
import se.su.dsv.scipro.match.dataobject.ProjectIdea;
import se.su.dsv.scipro.match.dataprovider.ProjectIdeaStatisticDataProvider;
public class AdminProjectIdeaStatisticPanel extends Panel {
private static final long serialVersionUID = 1L;
@SpringBean
private ApplicationPeriodDao applicationPeriodDao;
private DataView<ApplicationPeriod> dataView;
private List<ApplicationPeriod> applicationPeriods;
private ProjectIdeaStatisticDataProvider provider;
private WebMarkupContainer container;
private PagingNavigator nav;
public AdminProjectIdeaStatisticPanel(String str) {
super(str);
setup();
setupDataview();
}
private void setup() {
container = new WebMarkupContainer("container");
container.setOutputMarkupId(true);
applicationPeriods = applicationPeriodDao.findAll();
if(!applicationPeriods.isEmpty()){
List<ProjectIdea> projectIdeas = applicationPeriodDao.getProjectIdeas(applicationPeriods.get(0));
System.out.println(applicationPeriods.get(0));
for(ProjectIdea pi : projectIdeas){
System.out.println(pi);
}
}
}
private void setupDataview(){
provider = new ProjectIdeaStatisticDataProvider();
dataView = new DataView<ApplicationPeriod>("periodList", provider, 15) {
private static final long serialVersionUID = 3572766096237883198L;
@Override
protected void populateItem(Item<ApplicationPeriod> item) {
List<ProjectIdea> projectIdeas = applicationPeriodDao.getProjectIdeas(item.getModelObject());
int students = 0;
for (ProjectIdea pi : projectIdeas){
students += pi.getAuthors().size();
}
item.add(new Label("applicationPeriodName", ""+item.getModelObject().getName()));
item.add(new Label("applicationPeriodEndDate", ""+item.getModelObject().getEndDate()));
item.add(new Label("numberOfStudents", ""+students));
}
};
container.add(dataView);
nav = new PagingNavigator("nav", dataView);
nav.setOutputMarkupId(true);
add(container);
add(nav);
}
}

@ -52,7 +52,9 @@ public class AdminViewCheckListTemplatePanel extends Panel {
//Setup form-details
final IModel<String> templateNameModel = new Model<String>(clt.getName());
final AjaxEditableLabel<String> templateNameLabel = new AjaxEditableLabel<String>("templateName",
//REMOVED IN HTML MARKUP - SUPPOSED TO STAY?
/*final AjaxEditableLabel<String> templateNameLabel = new AjaxEditableLabel<String>("templateName",
templateNameModel){
private static final long serialVersionUID = 1L;
@Override
@ -60,7 +62,7 @@ public class AdminViewCheckListTemplatePanel extends Panel {
super.onSubmit(target);
clt.setName(templateNameModel.getObject());
}
};
};*/
questionField = new RequiredTextField<String>("questionField", new PropertyModel<String>(this, "question"));
questionField.setOutputMarkupId(true);
@ -161,7 +163,7 @@ public class AdminViewCheckListTemplatePanel extends Panel {
};
addQuestionButton.setOutputMarkupId(true);
//Add components to hierarchy
container.add(templateNameLabel);
//container.add(templateNameLabel);
container.add(listView);
add(container);
addQuestionForm.add(questionField);

@ -5,6 +5,8 @@
<a href="#" wicket:id="actionLink">Actions</a>
|
<a href="#" wicket:id="watsonLink">Project idea details</a>
|
<a href="#" wicket:id="historyLink">Match history</a>
<div class="prepend-top" wicket:id="mainPanel"></div>
</wicket:panel>
</body>

@ -15,11 +15,8 @@ public class AdminEditProjectIdeaPanel extends Panel {
private static final long serialVersionUID = 1L;
private Panel watsonPanel;
private Panel actionPanel;
private Panel currentPanel;
private AjaxFallbackLink<Void> watsonLink;
private AjaxFallbackLink<Void> actionLink;
private Panel watsonPanel, actionPanel, historyPanel, currentPanel;
private AjaxFallbackLink<Void> watsonLink, actionLink, historyLink;
public AdminEditProjectIdeaPanel(String id, IModel<ProjectIdea> model, final Component feedbackPanel) {
super(id, model);
@ -29,10 +26,12 @@ public class AdminEditProjectIdeaPanel extends Panel {
watsonPanel = new ManualWatsonPanel("mainPanel", model, feedbackPanel);
actionPanel = new ProjectIdeaActionPanel("mainPanel", model, feedbackPanel);
historyPanel = new MatchHistoryPanel("mainPanel", model, feedbackPanel);
currentPanel = actionPanel;
currentPanel.setOutputMarkupId(true);
watsonPanel.setOutputMarkupId(true);
actionPanel.setOutputMarkupId(true);
historyPanel.setOutputMarkupId(true);
watsonLink = new AjaxFallbackLink<Void>("watsonLink") {
private static final long serialVersionUID = 1L;
@ -49,6 +48,7 @@ public class AdminEditProjectIdeaPanel extends Panel {
if (target != null) {
target.addComponent(currentPanel);
target.addComponent(actionLink);
target.addComponent(historyLink);
target.addComponent(this);
}
}
@ -73,6 +73,7 @@ public class AdminEditProjectIdeaPanel extends Panel {
if (target != null) {
target.addComponent(currentPanel);
target.addComponent(watsonLink);
target.addComponent(historyLink);
target.addComponent(this);
}
}
@ -80,6 +81,30 @@ public class AdminEditProjectIdeaPanel extends Panel {
actionLink.setOutputMarkupId(true);
add(actionLink);
historyLink = new AjaxFallbackLink<Void>("historyLink") {
private static final long serialVersionUID = -9010339024625408623L;
@Override
public boolean isEnabled() {
return currentPanel != historyPanel;
}
@Override
public void onClick(AjaxRequestTarget target) {
currentPanel.replaceWith(historyPanel);
currentPanel = historyPanel;
if(target!=null){
target.addComponent(currentPanel);
target.addComponent(watsonLink);
target.addComponent(actionLink);
target.addComponent(this);
}
}
};
historyLink.setOutputMarkupId(true);
add(historyLink);
add(currentPanel);
} else {
this.setVisible(false);

@ -3,7 +3,7 @@
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<body>
<wicket:panel>
<wicket:enclosure child="manual">
<wicket:enclosure child="watson">
<!--<div wicket:id="manual" class="append-bottom"></div>-->
<div wicket:id="watson"></div>
</wicket:enclosure>

@ -17,7 +17,7 @@ public class ManualWatsonPanel extends Panel {
public ManualWatsonPanel(String id, IModel<ProjectIdea> model, final Component feedBack) {
super(id);
if (model.getObject()!=null){
add(new ManualMatchPanel("manual", new PropertyModel<Match>(model, "match"), feedBack, Match.Status.CONFIRMED));
//add(new ManualMatchPanel("manual", new PropertyModel<Match>(model, "match"), feedBack, Match.Status.CONFIRMED));
add(new WatsonInfoPanel("watson", model.getObject().getMatch().getProjectIdea()));
}
}

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<body>
<wicket:panel>
<div>
<table class="rounded-corner">
<thead>
<tr>
<th class="rounded-left-top">Date</th><th>Status</th><th>Supervisor</th><th>Rejected by</th><th class="rounded-right-top">Comment by supervisor</th>
</tr>
</thead>
<tbody>
<tr wicket:id="historyList">
<td wicket:id="date"></td>
<td wicket:id="status"></td>
<td wicket:id="supervisor"></td>
<td wicket:id="rejectedBy"></td>
<td wicket:id="comment"></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" class="rounded-foot">&nbsp;</td>
</tr>
</tfoot>
</table>
</div>
</wicket:panel>
</body>
</html>

@ -0,0 +1,50 @@
package se.su.dsv.scipro.admin.panels.match;
import java.util.List;
import org.apache.wicket.Component;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import se.su.dsv.scipro.match.dao.interfaces.MatchDao;
import se.su.dsv.scipro.match.dataobject.Match;
import se.su.dsv.scipro.match.dataobject.ProjectIdea;
public class MatchHistoryPanel extends Panel {
@SpringBean
private MatchDao matchDao;
private static final long serialVersionUID = 1L;
public MatchHistoryPanel(String id, IModel<ProjectIdea> model, final Component feedBack) {
super(id);
if (model.getObject()!=null){
ProjectIdea pi = model.getObject();
List<Match> matchObjects = matchDao.getMatchHistory(pi);
ListView<Match> historyList = new ListView<Match>("historyList", matchObjects) {
private static final long serialVersionUID = 5246932667444626581L;
@Override
protected void populateItem(ListItem<Match> item) {
Match match = item.getModelObject();
String supervisorName = match.getSupervisor() != null ? match.getSupervisor().getNameAsString() : "";
String rejectedByName = match.getRejectedBy() != null ? match.getRejectedBy().getFullName() : "";
String comment = match.getCommentForAdmin() != null ? match.getCommentForAdmin() : "";
item.add(new Label("date", match.getDateCreated().toString()));
item.add(new Label("status", match.getStatus().toString()));
item.add(new Label("supervisor", supervisorName));
item.add(new Label("rejectedBy", rejectedByName));
item.add(new Label("comment", comment));
add(item);
}
};
add(historyList);
}
}
}

@ -69,6 +69,12 @@ public abstract class Role extends LazyDeletableDomainObject implements Comparab
return str;
}
public String getEmailAsString(){
String str = "";
if(user.getEmailAddress()!=null)
str += user.getEmailAddress();
return str;
}
@Override
public int hashCode() {
final int prime = 31;

@ -82,9 +82,10 @@ public class GreedyMatchingAlgorithm implements MatchingAlgorithm {
continue;
}
if(availability.getProjectClass().toString().equalsIgnoreCase(ProjectClass.BACHELOR) &&
projectIdea.getProjectClass().toString().equalsIgnoreCase(ProjectClass.MASTER)) {
logger.info("A bachelor supervisor cannot handle master ideas.");
if(!availability.getProjectClass().toString().equals(
projectIdea.getProjectClass().toString()) ) {
//logger.info("A bachelor supervisor cannot handle master ideas.");
logger.info("Supervisor availability level and project idea level aren't equal.");
continue;
}

@ -13,7 +13,15 @@ public interface KeywordDao extends LazyDeleteDao<Keyword>{
Set<Keyword> getKeywords(KeywordType type, boolean includeDeleted);
List<Keyword> getKeywordList(Params params);
/**
* Returns the keyword if it is found
* @param keywordType the keyword can be of a specific type i.e. regular, research area or unit, is never NULL
* @param keywordName the search term, can only be a part of the keyword name, but must start with the same characters
* @return List<Keyword> the keyword list
*/
public List<Keyword> getAutoCompleteCapableSupervisors(final KeywordType keywordType, final String keywordName);
public List<Keyword> findAllFromType(KeywordType kt, boolean includeDeleted);
/**

@ -35,9 +35,11 @@ public class ApplicationPeriodDaoJPAImp extends
throws PersistenceException {
TypedQuery<ProjectIdea> query =
em.createQuery(
"select pi FROM ProjectIdea pi WHERE pi.dateCreated <= :endDate AND pi.projectClass IN (:projectClasses) AND pi.project = NULL",
"select pi FROM ProjectIdea pi WHERE pi.applicationPeriod = :period AND pi.projectClass IN (:projectClasses) AND pi.project = NULL",
ProjectIdea.class);
query.setParameter("endDate", applicationPeriod.getEndDate());
// query.setParameter("endDate", applicationPeriod.getEndDate());
//query.setParameter("startDate", applicationPeriod.getStartDate());
query.setParameter("period", applicationPeriod);
query.setParameter("projectClasses", applicationPeriod.getProjectClass());
query.setHint(QueryHints.HINT_CACHEABLE, "true");
try {

@ -23,8 +23,7 @@ import se.su.dsv.scipro.match.dataobject.Keyword;
import se.su.dsv.scipro.match.dataobject.KeywordType;
@Repository("keywordDao")
public class KeywordDaoJPAImp extends LazyDeleteAbstractDaoJPAImp<Keyword> implements
KeywordDao {
public class KeywordDaoJPAImp extends LazyDeleteAbstractDaoJPAImp<Keyword> implements KeywordDao {
public KeywordDaoJPAImp() {
super(Keyword.class);
@ -137,5 +136,21 @@ public class KeywordDaoJPAImp extends LazyDeleteAbstractDaoJPAImp<Keyword> imple
}
});
}
@Override
// TODO should be improved so that it is possible to search on "mining" and find "data mining"
public List<Keyword> getAutoCompleteCapableSupervisors(final KeywordType keywordType, final String keywordName) {
return getJpaTemplate().execute(new JpaCallback<List<Keyword>>() {
public List<Keyword> doInJpa(EntityManager em) throws PersistenceException {
TypedQuery<Keyword> query;
query = em.createQuery("SELECT x FROM "+domainClassString+" x WHERE x.type = :type AND x.keyword LIKE :keywordName ORDER BY keyword", domainClass);
query.setParameter("type", keywordType);
String keyWordNameString = keywordName + "%";
query.setParameter("keywordName", keyWordNameString);
query.setHint(QueryHints.HINT_CACHEABLE, "true");
return query.getResultList();
}
});
}
}

@ -17,7 +17,7 @@ public class Availability implements Serializable {
private Integer numCapable;
private final Employee supervisor;
public Availability(final Employee supervisor,final Long numMatched,final Integer numCapable,final ProjectClass projectClass) {
public Availability(final Employee supervisor, final Long numMatched, final Integer numCapable, final ProjectClass projectClass) {
this.supervisor = supervisor;
this.numMatched = numMatched;
this.numCapable = numCapable;

@ -30,13 +30,42 @@ public class Match extends DomainObject implements Comparable<Match> {
}
public static enum Status {
PENDING,
PUBLISHED,
CONFIRMED,
REJECTED,
REFUSED,
INACTIVE,
UNMATCHED
PENDING
{
public String toString() {
return "Pending";
}
},
PUBLISHED{
public String toString() {
return "Suggested";
}
},
CONFIRMED{
public String toString() {
return "Accepted";
}
},
REJECTED{
public String toString() {
return "Rejected";
}
},
REFUSED{
public String toString() {
return "Refused";
}
},
INACTIVE{
public String toString() {
return "Inactive";
}
},
UNMATCHED{
public String toString() {
return "Unmatched";
}
}
}
public static final int NO_POINTS_ASSIGNED = -1;

@ -0,0 +1,45 @@
package se.su.dsv.scipro.match.dataprovider;
import java.util.Iterator;
import org.apache.wicket.injection.web.InjectorHolder;
import org.apache.wicket.markup.repeater.data.IDataProvider;
import org.apache.wicket.model.IModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import se.su.dsv.scipro.data.DomainObjectDetachableModel;
import se.su.dsv.scipro.match.dao.interfaces.ApplicationPeriodDao;
import se.su.dsv.scipro.match.dataobject.ApplicationPeriod;
public class ProjectIdeaStatisticDataProvider implements IDataProvider<ApplicationPeriod>{
private static final long serialVersionUID = 1L;
@SpringBean
private ApplicationPeriodDao applicationPeriodDao;
public ProjectIdeaStatisticDataProvider(){
InjectorHolder.getInjector().inject(this);
}
@Override
public Iterator<? extends ApplicationPeriod> iterator(int first, int count) {
return applicationPeriodDao.findAll(first, count).iterator();
}
@Override
public int size() {
return (int)applicationPeriodDao.countAll();
}
@Override
public IModel<ApplicationPeriod> model(ApplicationPeriod object) {
return new DomainObjectDetachableModel<ApplicationPeriod>(applicationPeriodDao,object);
}
@Override
public void detach() {
//Do nothing
}
}

@ -24,7 +24,7 @@
<!-- <input style="width:300px;" wicket:id="supervisorField" type="text" /><br/> -->
<!-- <label for="authorField">Author:</label><br/> -->
<!-- <input style="width:300px;" wicket:id="authorField" type="text" /> -->
<div class="span-16 append-bottom last">
<div class="span-22 append-bottom last">
<div class="span-3" wicket:id="projectClassPanel"></div>
<div class="span-7 last append-bottom" wicket:id="matchStatusPanel"></div>
<div class="span-5">
@ -46,7 +46,7 @@
<span class="right">Ideas per page: <select wicket:id="itemsPerPage"></select></span>
</div>
<div class="span-15 last">
<div class="span-22 last">
<table class="rounded-corner">
<thead>
<tr>

@ -9,7 +9,7 @@
<input style="width:300px;" wicket:id="supervisorField" type="text" /><br />
<label for="keywordField">Search on keywords used by supervisor:</label><br />
<input style="width:300px;" wicket:id="keywordField" type="text" />
<div class="span-16 prepend-top append-bottom last">
<div class="span-22 prepend-top append-bottom last">
<div class="span-5">
<label for="unitPanel">Filter by unit:</label><br />
@ -30,7 +30,7 @@
</form>
<div wicket:id="container">
<div class="span-15 last">
<div class="span-22 last">
<table class="rounded-corner">
<thead>
<tr>

@ -52,29 +52,29 @@ public class FilterFormMatchStatusPanel extends Panel {
Match.StatusCheckBox.
}*/
item.add(statusCheckBox);
Label statusName = new Label("statusName", item.getModel().getObject().name());
Label statusName = new Label("statusName", item.getModelObject().toString());
item.add(statusName);
if (item.getModel().getObject().equals(Match.Status.CONFIRMED)){
item.replace(new Label("statusName", item.getModel().getObject().name() + " (accepted by supervisor)"));
item.replace(new Label("statusName", item.getModelObject() + " (accepted by supervisor)"));
}
else if (item.getModel().getObject().equals(Match.Status.PUBLISHED)){
item.replace(new Label("statusName", item.getModel().getObject().name() + " (suggested to supervisor)"));
item.replace(new Label("statusName", item.getModelObject() + " (suggested to supervisor)"));
}
else if (item.getModel().getObject().equals(Match.Status.INACTIVE)){
item.replace(new Label("statusName", item.getModel().getObject().name() + " (e.g. cancelled)"));
item.replace(new Label("statusName", item.getModelObject() + " (e.g. cancelled)"));
}
else if (item.getModel().getObject().equals(Match.Status.REFUSED)){
item.replace(new Label("statusName", item.getModel().getObject().name() + " (poorly written, sent back to author(s) for rewriting)"));
item.replace(new Label("statusName", item.getModelObject() + " (poorly written, sent back to author(s) for rewriting)"));
}
else if (item.getModel().getObject().equals(Match.Status.REJECTED)){
item.replace(new Label("statusName", item.getModel().getObject().name() + " (e.g. declined by supervisor)"));
item.replace(new Label("statusName", item.getModelObject() + " (e.g. declined by supervisor)"));
}
else if (item.getModel().getObject().equals(Match.Status.UNMATCHED)){
item.replace(new Label("statusName", item.getModel().getObject().name() + " (waiting to be matched)"));
item.replace(new Label("statusName", item.getModelObject() + " (waiting to be matched)"));
}
else if (item.getModel().getObject().equals(Match.Status.PENDING)){
item.replace(new Label("statusName", item.getModel().getObject().name() + " (this status is almost never used)"));
item.replace(new Label("statusName", item.getModelObject() + " (this status is almost never used)"));
}
}
};

@ -67,7 +67,7 @@ public abstract class EditProjectPanel extends Panel {
super(id);
FeedbackPanel feedbackPanel = new FeedbackPanel("feedback");
feedbackPanel.add(new EffectBehavior(new Delay(5000))).add(new EffectBehavior(new FadeOut(EffectSpeed.SLOW)));
add(feedbackPanel);
// add(feedbackPanel);
// formContainer = new WebMarkupContainer("formContainer");
// formContainer.setOutputMarkupId(true);

@ -12,7 +12,7 @@
<th>Project level</th>
<th>Title</th>
<th>Author(s)</th>
<th class="rounded-right-top">Status</th>
<th class="rounded-right-top">Supervisor</th>
</tr>
</thead>
<tfoot>
@ -28,7 +28,7 @@
<td wicket:id="level"></td>
<td><a href="#" wicket:id="ideaLink"><span wicket:id="title"></span></a></td>
<td wicket:id="authors"></td>
<td wicket:id="status"></td>
<td wicket:id="supervisor"></td>
</tr>
</tbody>

@ -16,6 +16,7 @@ import se.su.dsv.scipro.data.dataobjects.Student;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.match.dao.interfaces.AuthorDao;
import se.su.dsv.scipro.match.dao.interfaces.ProjectIdeaDao;
import se.su.dsv.scipro.match.dataobject.Match;
import se.su.dsv.scipro.match.dataobject.ProjectIdea;
import se.su.dsv.scipro.match.dataprovider.ProjectIdeaByUserDataProvider;
import se.su.dsv.scipro.project.pages.ProjectIdeaSubmissionPage;
@ -79,7 +80,16 @@ public class MyProjectIdeasPanel extends Panel {
item.add(new DateFormatter(DateFormatter.FORMAT.EXTENDED).createFormattedDateLabel("date", idea.getDateCreated()));
item.add(new Label("level", idea.getProjectClass().getName()));
item.add(new Label("authors", authorString));
item.add(new Label("status", idea.getStatus()));
String supervisor = "";
if(idea.getMatch().getSupervisor()!=null&&idea.getMatch().getStatus().equals(Match.Status.CONFIRMED))
supervisor = idea.getMatch().getSupervisor().getNameAsString()+" ("+idea.getMatch().getSupervisor().getEmailAsString()+")";
else if(idea.getMatch().getStatus().equals(Match.Status.REFUSED))
supervisor = "Project idea refused, needs to be rewritten";
else
supervisor = "Supervisor allocation in progress";
item.add(new Label("supervisor", supervisor));
}

@ -56,7 +56,7 @@
</tfoot>
<tbody wicket:id="dataview">
<tr>
<td wicket:id="projectTitle">Other role</td>
<td><a wicket:id="openLink"><span wicket:id="projectTitle">Other role</span></a></td>
<td wicket:id="projectLevel">Other role</td>
<td wicket:id="authorsLabel">Other role</td>
<td wicket:id="headsupervisorLabel">Other role</td>

@ -1,8 +1,5 @@
package se.su.dsv.scipro.project.panels;
import java.util.HashSet;
import java.util.Set;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.WebMarkupContainer;
@ -13,11 +10,12 @@ import org.apache.wicket.markup.html.panel.EmptyPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.model.Model;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.odlabs.wiquery.ui.dialog.Dialog;
import se.su.dsv.scipro.SciProSession;
import se.su.dsv.scipro.admin.pages.ProjectManagementPage;
import se.su.dsv.scipro.admin.panels.AdminEditProject;
import se.su.dsv.scipro.data.dao.interfaces.Dao.SortableParams.Sort;
import se.su.dsv.scipro.data.dao.interfaces.ProjectDao;
import se.su.dsv.scipro.data.dataobjects.Project;
@ -29,56 +27,91 @@ import se.su.dsv.scipro.reusable.FilterProjectClassPanel;
import se.su.dsv.scipro.reusable.FilterProjectStatusPanel;
import se.su.dsv.scipro.reusable.FilterStringPanel;
import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.util.JavascriptEventConfirmation;
import java.util.HashSet;
import java.util.Set;
public class ProjectManagementPanel extends Panel {
@SpringBean
private ProjectFacade projectFacade;
private static final long serialVersionUID = 1L;
@SpringBean
private ProjectFacade projectFacade;
private static final long serialVersionUID = 1L;
private WebMarkupContainer dataviewContainer;
private ProjectDao.Params params;
private NewProjectDataProvider dataProvider;
private ProjectDao.Params params;
private NewProjectDataProvider dataProvider;
private Label emptyLabel;
private PagingNavigator nav;
private PagingNavigator nav;
private Dialog dialog;
public ProjectManagementPanel(String id) {
super(id);
this.setOutputMarkupId(true);
dataviewSetup();
settingsSetup();
sortSetup();
createSetup();
}
public ProjectManagementPanel(String id) {
super(id);
this.setOutputMarkupId(true);
dataviewSetup();
settingsSetup();
sortSetup();
createSetup();
}
private void ajaxRefresh(AjaxRequestTarget target){
target.addComponent(dataviewContainer); //refresh the container containing the list
nav.setVisible(dataProvider.size()!=0);
target.addComponent(nav);
emptyLabel.setVisible(dataProvider.size()==0);
target.addComponent(emptyLabel);
}
private void ajaxRefresh(AjaxRequestTarget target) {
target.addComponent(dataviewContainer); //refresh the container containing the list
nav.setVisible(dataProvider.size() != 0);
target.addComponent(nav);
emptyLabel.setVisible(dataProvider.size() == 0);
target.addComponent(emptyLabel);
}
private void dataviewSetup(){
params = new ProjectDao.Params();
params.setSortOn("title", Sort.ASCENDING);
// params.setCategories(filterSet);
dataProvider = new NewProjectDataProvider(params);
dataviewContainer = new WebMarkupContainer("dataviewContainer");
dataviewContainer.setOutputMarkupId(true);
add(dataviewContainer);
private void dataviewSetup() {
params = new ProjectDao.Params();
params.setSortOn("title", Sort.ASCENDING);
// params.setCategories(filterSet);
dataProvider = new NewProjectDataProvider(params);
dataviewContainer = new WebMarkupContainer("dataviewContainer");
dataviewContainer.setOutputMarkupId(true);
add(dataviewContainer);
DataView<Project> dataview = new DataView<Project>("dataview", dataProvider, 15) {
private static final long serialVersionUID = 1L;
@Override
protected void populateItem(Item<Project> item) {
final Project p = item.getModelObject();
item.add(new Label("projectTitle", p.getTitle()));
AjaxLink openLink = new AjaxLink<Void>("openLink") {
private static final long serialVersionUID = 1L;
@Override
public void onClick(AjaxRequestTarget target) {
dialog.replace(new AdminEditProject("panel", new Model<Project>(p)) {
private static final long serialVersionUID = -3929246545240675832L;
@Override
public void onUpdate(AjaxRequestTarget target) {
// dialog.close(target);
// ajaxRefresh(target);
// target.addComponent(dialog);
setResponsePage(ProjectManagementPage.class);
}
@Override
public boolean isEditable() {
return false;
}
});
dialog.setTitle("Project details");
target.addComponent(dialog);
dialog.open(target);
}
};
openLink.add(new Label("projectTitle", p.getTitle()));
item.add(openLink);
item.add(new Label("projectLevel", p.getProjectClass().toString()));
item.add(new Label("authorsLabel", p.getProjectParticipantsAsString()));
@ -89,8 +122,6 @@ public class ProjectManagementPanel extends Panel {
item.add(new Label("reviewerLabel", p.getProjectReviewersAsString()));
item.add(new Label("statusLabel", p.getProjectStatus().toString()));
item.add(new Label("editLabel", "edit"));
//edit link. this is ugly and is taken straight out of the old panel. should be done using facades.
AjaxLink testLink = new AjaxLink<Void>("testLink") {
@ -99,22 +130,43 @@ public class ProjectManagementPanel extends Panel {
@Override
public void onClick(AjaxRequestTarget target) {
dialog.replace(new EditProjectPanel("panel", p) {
private static final long serialVersionUID = 1L;
// dialog.replace(new EditProjectPanel("panel", p) {
// private static final long serialVersionUID = 1L;
//
// @Override
// public void onUpdate(AjaxRequestTarget target) {
// dialog.close(target);
// ajaxRefresh(target);
// }
//
// });
dialog.replace(new AdminEditProject("panel", new Model<Project>(p)) {
private static final long serialVersionUID = -633068454448962134L;
@Override
public void onUpdate(AjaxRequestTarget target) {
dialog.close(target);
ajaxRefresh(target);
// dialog.close(target);
// ajaxRefresh(target);
// target.addComponent(dialog);
setResponsePage(ProjectManagementPage.class);
}
@Override
public boolean isEditable() {
return SciProSession.get().authorizedForRole(Roles.SYSADMIN);
}
});
dialog.setTitle("Edit project");
target.addComponent(dialog);
dialog.open(target);
}
};
testLink.add(new ImageObject("editIcon", ImageObject.SIXTEEN + ImageObject.EDIT));
testLink.setVisible(isEditable());
item.add(testLink);
AjaxLink deleteLink = new AjaxLink<Void>("deleteLink") {
private static final long serialVersionUID = 1L;
@ -127,29 +179,31 @@ public class ProjectManagementPanel extends Panel {
};
deleteLink.add(new ImageObject("deleteIcon", ImageObject.SIXTEEN + ImageObject.DELETE));
deleteLink.setVisible(isEditable());
deleteLink.add(new JavascriptEventConfirmation("onclick", "Are you sure you want to delete this project? This action can NOT be undone!"));
item.add(deleteLink);
}
};
dataviewContainer.add(dataview);
dataviewContainer.add(dataview);
nav = new PagingNavigator("nav", dataview); //we need a navigator
nav.setOutputMarkupId(true); //make it ajax-targetable
nav.setVisible(dataProvider.size()!=0);
dataviewContainer.add(nav); //add it
nav = new PagingNavigator("nav", dataview); //we need a navigator
nav.setOutputMarkupId(true); //make it ajax-targetable
nav.setVisible(dataProvider.size() != 0);
dataviewContainer.add(nav); //add it
emptyLabel = new Label("emptyLabel", "No projects to show"); //informs the user that the list is emty
emptyLabel.setOutputMarkupId(true); //make it ajax-targetable
emptyLabel.setVisible(dataProvider.size()==0);
dataviewContainer.add(emptyLabel); //add it
}
emptyLabel = new Label("emptyLabel", "No projects to show"); //informs the user that the list is emty
emptyLabel.setOutputMarkupId(true); //make it ajax-targetable
emptyLabel.setVisible(dataProvider.size() == 0);
dataviewContainer.add(emptyLabel); //add it
}
private void settingsSetup(){
private void settingsSetup() {
WebMarkupContainer settingsContainer = new WebMarkupContainer("settingsContainer");
add(settingsContainer);
add(settingsContainer);
//under here are the filtering components: beginning with the filter on string
settingsContainer.add(new FilterStringPanel("filterStringPanel") {
//under here are the filtering components: beginning with the filter on string
settingsContainer.add(new FilterStringPanel("filterStringPanel") {
private static final long serialVersionUID = 1L;
@Override
@ -158,8 +212,8 @@ public class ProjectManagementPanel extends Panel {
ajaxRefresh(target);
}
});
settingsContainer.add(new DatesPanel("filterDatesPanel") {
settingsContainer.add(new DatesPanel("filterDatesPanel") {
private static final long serialVersionUID = 1L;
@Override
@ -170,8 +224,8 @@ public class ProjectManagementPanel extends Panel {
}
});
settingsContainer.add(new FilterProjectClassPanel("filterProjectClassPanel") {
settingsContainer.add(new FilterProjectClassPanel("filterProjectClassPanel") {
private static final long serialVersionUID = 1L;
@Override
@ -181,8 +235,8 @@ public class ProjectManagementPanel extends Panel {
}
});
settingsContainer.add(new FilterProjectStatusPanel("filterProjectStatusPanel") {
settingsContainer.add(new FilterProjectStatusPanel("filterProjectStatusPanel") {
private static final long serialVersionUID = 1L;
@Override
@ -192,37 +246,38 @@ public class ProjectManagementPanel extends Panel {
}
});
}
}
private void sortSetup(){
final Set<String> sortString = new HashSet<String>(); //make a set with columns you want to be sortable
sortString.add(new String("title"));
// sortString.add(new String("creator")); //this doesnt work because it sorts on user id, not name
// sortString.add(new String("numberOfQuestions"));
private void sortSetup() {
final Set<String> sortString = new HashSet<String>(); //make a set with columns you want to be sortable
sortString.add(new String("title"));
// sortString.add(new String("creator")); //this doesnt work because it sorts on user id, not name
// sortString.add(new String("numberOfQuestions"));
for (final String s : sortString){ //create links for sorting using the set
Link<Void> link = new Link<Void>(s + "Sort"){
private static final long serialVersionUID = 1L;
@Override
public void onClick() {
if (params.getSortField().equals(s) && params.getDirection().equals(Sort.ASCENDING))
params.setSortOn(s, Sort.DESCENDING);
else params.setSortOn(s, Sort.ASCENDING);
}
};
dataviewContainer.add(link); //add the links
}
}
for (final String s : sortString) { //create links for sorting using the set
Link<Void> link = new Link<Void>(s + "Sort") {
private static final long serialVersionUID = 1L;
@Override
public void onClick() {
if (params.getSortField().equals(s) && params.getDirection().equals(Sort.ASCENDING))
params.setSortOn(s, Sort.DESCENDING);
else params.setSortOn(s, Sort.ASCENDING);
}
};
dataviewContainer.add(link); //add the links
}
}
private void createSetup() {
dialog = new Dialog("dialog");
dialog.setModal(true);
dialog.setAutoOpen(false);
dialog.setWidth(450);
dialog.setHeight(525);
add(dialog);
dialog.add(new EmptyPanel("panel"));
private void createSetup(){
dialog = new Dialog("dialog");
dialog.setModal(true);
dialog.setAutoOpen(false);
dialog.setWidth(450);
dialog.setHeight(525);
add(dialog);
dialog.add(new EmptyPanel("panel"));
// dialog.add(new EditProjectPanel("panel", new Project()){
// private static final long serialVersionUID = 1L;
// @Override
@ -234,8 +289,8 @@ public class ProjectManagementPanel extends Panel {
// }
//
// });
//create new link.
//create new link.
AjaxLink<Void> newLink = new AjaxLink<Void>("newLink") {
private static final long serialVersionUID = 1L;
@ -250,26 +305,49 @@ public class ProjectManagementPanel extends Panel {
// dialog.replace(new FunctionalEditChecklistTemplatePanel("panel", dummy));
dialog.replace(new EditProjectPanel("panel", new Project()) {
private static final long serialVersionUID = 1L;
// dialog.replace(new EditProjectPanel("panel", new Project()) {
// private static final long serialVersionUID = 1L;
//
// @Override
// public void onUpdate(AjaxRequestTarget target) {
// // target.addComponent(dialog);
// // dialog.close();
// // ajaxRefresh(target);
// setResponsePage(ProjectManagementPage.class);
// }
//
// });
dialog.replace(new AdminEditProject("panel", new Model<Project>(new Project())) {
private static final long serialVersionUID = -9078483322668302904L;
@Override
public void onUpdate(AjaxRequestTarget target) {
// target.addComponent(dialog);
// dialog.close();
// ajaxRefresh(target);
// dialog.close(target);
// ajaxRefresh(target);
// target.addComponent(dialog);
setResponsePage(ProjectManagementPage.class);
}
@Override
public boolean isEditable() {
return SciProSession.get().authorizedForRole(Roles.SYSADMIN);
}
});
dialog.setTitle("Create new project");
target.addComponent(dialog);
dialog.open(target);
}
};
add(newLink);
add(newLink);
newLink.setVisible(SciProSession.get().authorizedForRole(Roles.SYSADMIN));
}
}
private boolean isEditable(){
return SciProSession.get().authorizedForRole(Roles.SYSADMIN);
}
}

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8"/>
</head>
<body>
<wicket:panel>
<div wicket:id="wmc">
<input wicket:id="addnew"/>
<div wicket:id="listview">
<div><span wicket:id="name"></span> <select wicket:id="role"></select> <a wicket:id="deleteLink"><img wicket:id="deleteImage"></a></div>
</div>
<div wicket:id="emptyLabel"></div>
<!--<table>-->
<!--<tbody>-->
<!--<tr wicket:id="listview">-->
<!--<td><span wicket:id="name"></span></td>-->
<!--<td><select wicket:id="role"></select></td>-->
<!--<td><a wicket:id="deleteLink">Delete</a></td>-->
<!--</tr>-->
<!--</tbody>-->
<!--<tbody>-->
<!--<tr>-->
<!--<td wicket:id="emptyLabel"></td>-->
<!--</tr>-->
<!--</tbody>-->
<!--</table>-->
</div>
</wicket:panel>
</body>
</html>

@ -0,0 +1,113 @@
package se.su.dsv.scipro.reusable;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import se.su.dsv.scipro.SciProSession;
import se.su.dsv.scipro.data.dataobjects.Employee;
import se.su.dsv.scipro.data.dataobjects.Project;
import se.su.dsv.scipro.data.dataobjects.ProjectFollower;
import se.su.dsv.scipro.data.enums.ProjectTeamMemberRoles;
import se.su.dsv.scipro.icons.ImageObject;
import se.su.dsv.scipro.security.auth.roles.Roles;
import java.util.ArrayList;
import java.util.SortedSet;
/**
* @author: fred-fri
* date: 2012 03 16
*/
public abstract class AddRemoveProjectFollowerPanel extends Panel {
private SortedSet<ProjectFollower> followerSet;
private WebMarkupContainer wmc;
private ListView<ProjectFollower> followerListView;
private Label emptyLabel;
private IModel<Project> projectIModel;
/**
* Override this method to use AJAX
* @param target
*/
public abstract void onUpdate(AjaxRequestTarget target);
public AddRemoveProjectFollowerPanel(String id, final SortedSet<ProjectFollower> followerSet, final IModel<Project> projectIModel) {
super(id);
this.followerSet = followerSet;
this.projectIModel = projectIModel;
wmc = new WebMarkupContainer("wmc");
wmc.setOutputMarkupId(true);
add(wmc);
wmc.add(emptyLabel = new Label("emptyLabel", "No followers"));
emptyLabel.setVisible(followerSet.isEmpty());
emptyLabel.setOutputMarkupId(true);
wmc.add(followerListView = new ListView<ProjectFollower>("listview", new ArrayList(followerSet)) {
protected void populateItem(ListItem item) {
final ProjectFollower pf = (ProjectFollower) item.getModelObject();
item.add(new Label("name", pf.getNameAsString()));
ArrayList<ProjectTeamMemberRoles> roleList = new ArrayList<ProjectTeamMemberRoles>();
for (ProjectTeamMemberRoles ptmr : ProjectTeamMemberRoles.values()){
roleList.add(ptmr);
}
item.add(new DropDownChoice("role", new PropertyModel(pf, "projectRole"), roleList));
item.add(new AjaxLink("deleteLink") {
private static final long serialVersionUID = -5174472375922201597L;
@Override
public void onClick(AjaxRequestTarget target) {
followerSet.remove(pf);
followerListView.setList(new ArrayList(followerSet));
target.addComponent(wmc);
emptyLabel.setVisible(followerSet.isEmpty());
target.addComponent(emptyLabel);
onUpdate(target);
}
}.add(new ImageObject("deleteImage", ImageObject.SIXTEEN + ImageObject.DELETE)).setVisible(isEditable()));
}
});
wmc.add(new EmployeeAutoComplete("addnew") {
@Override
public void action(AjaxRequestTarget pTarget, Employee newSelection) {
setSelection(null);
ProjectFollower pf = new ProjectFollower();
pf.setProjectRole(ProjectTeamMemberRoles.CO_SUPERVISOR);
pf.setFollower(newSelection);
pf.setProject(projectIModel.getObject());
followerSet.add(pf);
followerListView.setList(new ArrayList(followerSet));
pTarget.addComponent(wmc);
emptyLabel.setVisible(followerSet.isEmpty());
pTarget.addComponent(emptyLabel);
onUpdate(pTarget);
}
});
}
public SortedSet<ProjectFollower> getProjectFollowerSet(){
return followerSet;
}
private boolean isEditable(){
return SciProSession.get().authorizedForRole(Roles.SYSADMIN);
}
}

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8"/>
</head>
<body>
<wicket:panel>
<div wicket:id="wmc">
<input wicket:id="addnew"/>
<div wicket:id="listview">
<div><span wicket:id="name"></span> <a wicket:id="deleteLink"><img wicket:id="deleteImage"></a></div>
</div>
<div wicket:id="emptyLabel"></div>
<!--<table>-->
<!--<tbody>-->
<!--<tr wicket:id="listview">-->
<!--<td><span wicket:id="name"></span></td>-->
<!--<td><a wicket:id="deleteLink">Delete</a></td>-->
<!--</tr>-->
<!--</tbody>-->
<!--<tbody>-->
<!--<tr>-->
<!--<td wicket:id="emptyLabel"></td>-->
<!--</tr>-->
<!--</tbody>-->
<!--</table>-->
</div>
</wicket:panel>
</body>
</html>

@ -0,0 +1,94 @@
package se.su.dsv.scipro.reusable;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Panel;
import se.su.dsv.scipro.SciProSession;
import se.su.dsv.scipro.data.dataobjects.Student;
import se.su.dsv.scipro.icons.ImageObject;
import se.su.dsv.scipro.security.auth.roles.Roles;
import java.util.ArrayList;
import java.util.SortedSet;
/**
* @author: fred-fri
* date: 2012 03 16
*/
public abstract class AddRemoveStudentsPanel extends Panel {
private static final long serialVersionUID = -7690822667493306854L;
private SortedSet<Student> studentSet;
private WebMarkupContainer wmc;
private ListView<Student> studentListView;
private Label emptyLabel;
private AuthorAutoComplete addnew;
/**
* Override this method to use AJAX
* @param target
*/
public abstract void onUpdate(AjaxRequestTarget target);
public AddRemoveStudentsPanel(String id, final SortedSet<Student> studentSet) {
super(id);
this.studentSet = studentSet;
wmc = new WebMarkupContainer("wmc");
wmc.setOutputMarkupId(true);
add(wmc);
wmc.add(emptyLabel = new Label("emptyLabel", "No students"));
emptyLabel.setVisible(studentSet.isEmpty());
emptyLabel.setOutputMarkupId(true);
wmc.add(studentListView = new ListView<Student>("listview", new ArrayList(studentSet)) {
protected void populateItem(ListItem item) {
final Student s = (Student) item.getModelObject();
item.add(new Label("name", s.getNameAsString()));
item.add(new AjaxLink("deleteLink") {
private static final long serialVersionUID = -5174472375922201597L;
@Override
public void onClick(AjaxRequestTarget target) {
studentSet.remove(s);
studentListView.setList(new ArrayList(studentSet));
target.addComponent(wmc);
emptyLabel.setVisible(studentSet.isEmpty());
target.addComponent(emptyLabel);
onUpdate(target);
}
}.add(new ImageObject("deleteImage", ImageObject.SIXTEEN + ImageObject.DELETE).setVisible(isEditable())));
}
});
wmc.add(addnew = new AuthorAutoComplete("addnew") {
@Override
public void action(AjaxRequestTarget pTarget, Student newSelection) {
setSelection(null);
studentSet.add(newSelection);
studentListView.setList(new ArrayList(studentSet));
pTarget.addComponent(wmc);
pTarget.addComponent(addnew);
emptyLabel.setVisible(studentSet.isEmpty());
pTarget.addComponent(emptyLabel);
onUpdate(pTarget);
}
});
}
public SortedSet<Student> getStudentSet(){
return studentSet;
}
private boolean isEditable(){
return SciProSession.get().authorizedForRole(Roles.SYSADMIN);
}
}

@ -41,12 +41,22 @@ public abstract class AuthorAutoComplete extends AutoCompleteObjectField<Student
@Override
protected Long getId(Student s) {
return s.getId();
// return s.getId();
if(s != null) {
return s.getId();
} else {
return 0L;
}
}
@Override
protected Long convertId(String id) {
return Long.valueOf(id);
// return Long.valueOf(id);
if(id != null && !id.isEmpty()) {
return Long.valueOf(id);
} else {
return 0L;
}
}
@Override
@ -75,7 +85,7 @@ public abstract class AuthorAutoComplete extends AutoCompleteObjectField<Student
@Override
protected String getName(Student item) {
return item.getNameAsString();
return item.getNameAsString() + " <" + item.getUser().getEmailAddress() + ">";
}
/**

@ -41,12 +41,22 @@ public abstract class EmployeeAutoComplete extends AutoCompleteObjectField<Emplo
@Override
protected Long getId(Employee e) {
return e.getId();
// return e.getId();
if(e != null) {
return e.getId();
} else {
return 0L;
}
}
@Override
protected Long convertId(String id) {
return Long.valueOf(id);
// return Long.valueOf(id);
if(id != null && !id.isEmpty()) {
return Long.valueOf(id);
} else {
return 0L;
}
}
@Override
@ -73,6 +83,11 @@ public abstract class EmployeeAutoComplete extends AutoCompleteObjectField<Emplo
}
}
@Override
protected String getName(Employee item) {
return item.getNameAsString() + " <" + item.getUser().getEmailAddress() + ">";
}
/**
* Override this method for actions to be performed when an object is selected.
*

@ -6,8 +6,7 @@
<form wicket:id="form">
<div wicket:id="list">
<div>
<span wicket:id="name"></span> <input wicket:id="check"
type="checkbox" />
<input wicket:id="check" type="checkbox"/> <span wicket:id="name"></span>
</div>
</div>

@ -6,8 +6,7 @@
<form wicket:id="form">
<div wicket:id="list">
<div>
<span wicket:id="name"></span> <input wicket:id="check"
type="checkbox" />
<input wicket:id="check" type="checkbox" /> <span wicket:id="name"></span>
</div>
</div>

@ -43,7 +43,7 @@ public class ScheduleTemplateDetailsPanel extends Panel {
List<ProjectEventTemplate> etList = template.getProjectEventTemplates();
add(new Label("numEventTemplates", etList.size() + ""));
//add(new Label("numEventTemplates", etList.size() + "")); <- Do not exist in HTML markup. Is it supposed to be here?
add(template.getCreator().getDisplayComponent("templateCreator"));
final DateFormatter df = new DateFormatter();
@ -71,8 +71,8 @@ public class ScheduleTemplateDetailsPanel extends Panel {
final PageParameters pp = new PageParameters();
pp.put("tid", template.getId());
BookmarkablePageLink<ScheduleTemplateDetailsPage> directLink = new BookmarkablePageLink<ScheduleTemplateDetailsPage>("directLink", ScheduleTemplateDetailsPage.class, pp);
add(directLink);
// BookmarkablePageLink<ScheduleTemplateDetailsPage> directLink = new BookmarkablePageLink<ScheduleTemplateDetailsPage>("directLink", ScheduleTemplateDetailsPage.class, pp);
// add(directLink);
add(new ListView<ProjectEventTemplate>("eventList", etList){
private static final long serialVersionUID = 1L;

@ -145,7 +145,6 @@ public class SupervisorMatchedThesisPanel extends Panel {
public void onUpdateUpdate(AjaxRequestTarget target2) {
emptyLabel.setVisible(provider.size() == 0);
dialog.close(target2);
target2.addComponent(dialog);
target2.addComponent(dataViewContainer);
target2.addComponent(emptyLabel);
}

@ -13,24 +13,40 @@
<div wicket:id="container">
<div><span wicket:id="dateFrom">datePicker</span> and <span wicket:id="dateTo">datePicker</span></div>
</div>
<div class="span-22 last">
<div class="span-8">
<label for="titleField">Title:</label><br/>
<input style="width:300px;" wicket:id="titleField" type="text"/><br/>
<label for="titleField">Title:</label><br/>
<input style="width:300px;" wicket:id="titleField" type="text"/><br/>
<label for="regKeyWordAC">Regular keyword:</label><br/>
<input style="width:300px;" wicket:id="regKeyWordAC" /><br/>
<label for="titleField">Regular keyword:</label><br/>
<input style="width:300px;" wicket:id="regKeyWordAC" /><br/>
<label for="unitKeyWordAC">Unit keyword:</label><br/>
<input style="width:300px;" wicket:id="unitKeyWordAC" /><br/>
<label for="titleField">Unit keyword:</label><br/>
<input style="width:300px;" wicket:id="unitKeyWordAC" /><br/>
<label for="areaKeyWordAC">Research area keyword:</label><br/>
<input style="width:300px;" wicket:id="areaKeyWordAC" /><br/>
</div>
<div class="span-14 last" >
<strong>Selected keywords and keyword types:</strong>
<ul wicket:id="keyWordsContainer">
<li wicket:id="keywordList">
<h5><span wicket:id="keyWord">[keyword]</span> (<span wicket:id="keyWordType">[keyWordType]</span>)</h5>
</li>
</ul>
</div>
</div>
<label for="titleField">Research area keyword:</label><br/>
<input style="width:300px;" wicket:id="areaKeyWordAC" /><br/>
<div class="span-22 last append-bottom">
<div class="span-3" wicket:id="projectClassPanel">
<div class="span-22 append-bottom last">
<div class="span-3" wicket:id="projectClassPanel"></div>
</div>
<div class="span-5">
<div><input wicket:id="filterButton" type="submit"/></div>
</div>
<div class="span-5">
<div><button wicket:id="clearSearchTermsButton">Clear search terms</button></div>
</div>
</div>
</form>

@ -10,6 +10,8 @@ import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.navigation.paging.PagingNavigator;
import org.apache.wicket.markup.html.panel.EmptyPanel;
import org.apache.wicket.markup.html.panel.Panel;
@ -178,7 +180,8 @@ public class SupervisorUnmatchedThesisPanel extends Panel {
allContainer.add(sortLink);
}
public AutoCompleteObjectField<Keyword, Long> createKeywordAC(final String wicketId, final KeywordTypeDao.TYPE keyWordType, final Collection<Keyword> keywords, final Component feedBackPanel) {
public AutoCompleteObjectField<Keyword, Long> createKeywordAC(final String wicketId, final KeywordTypeDao.TYPE keyWordType,
final List<Keyword> keywords, final Component feedBackPanel, final WebMarkupContainer keyWordsContainer) {
return new AutoCompleteObjectField<Keyword, Long>(wicketId, Keyword.class) {
private static final long serialVersionUID = 7734889540424308421L;
@ -212,7 +215,8 @@ public class SupervisorUnmatchedThesisPanel extends Panel {
@Override
public Iterator<Keyword> getChoices(String input) {
final KeywordType kwtype = keywordTypeDao.findByType(keyWordType); // keyWordType is only the Type, but the object is required in findAllFromType
return keywordDao.findAllFromType(kwtype, false).iterator();
return keywordDao.getAutoCompleteCapableSupervisors(kwtype, input).iterator();
}
@Override
@ -220,11 +224,16 @@ public class SupervisorUnmatchedThesisPanel extends Panel {
super.onNewSelection(pTarget, newSelection);
if (newSelection != null) {
if (pTarget != null) {
keywords.add(newSelection);
if(!keywords.contains(newSelection)) {
keywords.add(newSelection);
}
((ListView) keyWordsContainer.get("keywordList")).setModelObject(keywords);
Session.get().info("Added the keyword " + newSelection + " to the search terms.");
this.setModelObject(null);
this.clearInput();
pTarget.addComponent(this);
pTarget.addComponent(feedBackPanel);
pTarget.addComponent(keyWordsContainer);
}
}
}
@ -238,12 +247,32 @@ public class SupervisorUnmatchedThesisPanel extends Panel {
final Label emptyLabel, final Params params, final Component feedBackPanel) {
super("form");
final TextField<String> titleField = new TextField<String>("titleField", new Model<String>());
titleField.setOutputMarkupId(true);
final List<Keyword> keywords = new ArrayList<Keyword>();
final Collection<Keyword> keywords = new ArrayList<Keyword>();
AutoCompleteObjectField<Keyword, Long> regKeyWordAc = createKeywordAC("regKeyWordAC", KeywordTypeDao.TYPE.REGULAR, keywords, feedBackPanel);
AutoCompleteObjectField<Keyword, Long> unitKeyWordAc = createKeywordAC("unitKeyWordAC", KeywordTypeDao.TYPE.UNIT, keywords, feedBackPanel);
AutoCompleteObjectField<Keyword, Long> areaKeyWordAc = createKeywordAC("areaKeyWordAC", KeywordTypeDao.TYPE.RESEARCH_AREA, keywords, feedBackPanel);
ListView<Keyword> keywordListView = new ListView<Keyword>("keywordList", new Model<ArrayList<Keyword>>()) {
private static final long serialVersionUID = 78442920410294688L;
@Override
protected void populateItem(ListItem<Keyword> keywordListItem) {
//To change body of implemented methods use File | Settings | File Templates.
Keyword keyword = keywordListItem.getModelObject();
keywordListItem.add(new Label("keyWord",keyword.getKeyword()));
keywordListItem.add(new Label("keyWordType",keyword.getType().getName()));
}
};
final WebMarkupContainer keyWordsContainer = new WebMarkupContainer("keyWordsContainer");
keyWordsContainer.setOutputMarkupId(true);
keyWordsContainer.add(keywordListView);
add(keyWordsContainer);
AutoCompleteObjectField<Keyword, Long> regKeyWordAc = createKeywordAC("regKeyWordAC", KeywordTypeDao.TYPE.REGULAR, keywords, feedBackPanel, keyWordsContainer);
AutoCompleteObjectField<Keyword, Long> unitKeyWordAc = createKeywordAC("unitKeyWordAC", KeywordTypeDao.TYPE.UNIT, keywords, feedBackPanel, keyWordsContainer);
AutoCompleteObjectField<Keyword, Long> areaKeyWordAc = createKeywordAC("areaKeyWordAC", KeywordTypeDao.TYPE.RESEARCH_AREA, keywords, feedBackPanel, keyWordsContainer);
regKeyWordAc.setOutputMarkupId(true);
unitKeyWordAc.setOutputMarkupId(true);
areaKeyWordAc.setOutputMarkupId(true);
final CustomDateTimeField dateFrom = new CustomDateTimeField("dateFrom", new Model<Date>(getDateSixMonthsAgo()));
final CustomDateTimeField dateTo = new CustomDateTimeField("dateTo", new Model<Date>(Calendar.getInstance().getTime()));
@ -279,6 +308,18 @@ public class SupervisorUnmatchedThesisPanel extends Panel {
}
};
add(filterButton);
add(new AjaxButton("clearSearchTermsButton") {
private static final long serialVersionUID = 443680343329839590L;
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
((ListView) keyWordsContainer.get("keywordList")).setModelObject(null);
titleField.setModelObject(null);
target.addComponent(keyWordsContainer);
target.addComponent(titleField);
//projectClassPanel => för att noll-ställa
}
});
}
}
}

@ -93,8 +93,7 @@ table.rounded-corner
list-style-type: none;
}
.rounded-box ul li {
background: url('../images/triangle-right.png') left center
no-repeat;
/* background: url('../images/triangle-right.png') left center no-repeat; */
padding-left: 15px;
}

@ -579,18 +579,19 @@ public class TestGreedyMatchingAlgorithm {
* Tests: We now perform a third test "testDavidH_Has_Less_Total_Available_Slots", here we test that "henrikH" is found, because "davidH"
* has less "total available" slots (8) compared to 9 for "henrikH" for project ideas (master + bachelor)
* */
public void testDavidH_Has_Less_Total_Available_Slots() {
public void testDavidH_Has_Less_Available_Slots() {
List<ProjectIdea> projectIdeaList = new ArrayList<ProjectIdea>();
List<Employee> supervisorList = new ArrayList<Employee>();
Employee davidH = createEmployee("David", "Hallberg", languages);
supervisorAvailability.add(new Availability(davidH, 0L, 4, bachelorProjectClass));
supervisorAvailability.add(new Availability(davidH, 1L, 5, masterProjectClass));
Employee henrikH = createEmployee("Henrik", "Hansson", languages);
supervisorAvailability.add(new Availability(henrikH, 1L, 5, bachelorProjectClass));
supervisorAvailability.add(new Availability(henrikH, 0L, 5, masterProjectClass));
supervisorAvailability.add(new Availability(henrikH, 0L, 4, bachelorProjectClass));
//supervisorAvailability.add(new Availability(henrikH, 0L, 5, masterProjectClass));
supervisorList.add(henrikH);
Employee davidH = createEmployee("David", "Hallberg", languages);
supervisorAvailability.add(new Availability(davidH, 1L, 4, bachelorProjectClass));
//supervisorAvailability.add(new Availability(davidH, 1L, 5, masterProjectClass));
ProjectIdea secondBachelorIdea = createProjectIdea(bachelorProjectClass, applicationPeriod);
projectIdeaList.clear();
projectIdeaList.add(secondBachelorIdea); // David Hallberg is preferred supervisor for this project idea
@ -678,4 +679,34 @@ public class TestGreedyMatchingAlgorithm {
assertTrue(result.matches.get(2).getProjectIdea().equals(masterIdea));
}
@Test
@Rollback
@Transactional
/* Test 5
* =============================================================================================
* This test verifies that bachelor project ideas will never be matched with
* a master level Availability object, as opposed to previous practice.
* */
public void testAvailabilityLevelMatching() {
Employee davidH = createEmployee("David", "Hallberg", languages);
supervisorAvailability.add(new Availability(davidH, 1L, 1, bachelorProjectClass));
supervisorAvailability.add(new Availability(davidH, 0L, 1, masterProjectClass));
Employee henrikH = createEmployee("Henrik", "Hansson", languages);
supervisorAvailability.add(new Availability(henrikH, 0L, 1, bachelorProjectClass));
supervisorAvailability.add(new Availability(henrikH, 0L, 1, masterProjectClass));
ProjectIdea bachelorIdea = createProjectIdea(bachelorProjectClass, applicationPeriod);
unmatchedProjectIdeas.add(bachelorIdea);
Keyword båtar = createKeyword(keywordTypeWord, "båtar", false);
davidH.getKeywords().getAll().add(båtar);
bachelorIdea.getKeywords().getAll().add(båtar);
Result result = new GreedyMatchingAlgorithm().match(supervisorAvailability, unmatchedProjectIdeas, weights);
assertTrue(result.matches.get(0).getSupervisor().equals(henrikH));
assertTrue(result.matches.get(0).getProjectIdea().equals(bachelorIdea));
}
}

@ -135,10 +135,8 @@ public class TestApplicationPeriodDao {
@Transactional
@Rollback
public void testShouldReturnAllProjectIdeasForApplicationPeriod() {
projectIdea1.setDateCreated(date("2011-07-02"));
projectIdea2.setDateCreated(date("2011-06-12"));
List<ProjectIdea> projectIdeas = applicationPeriodDao.getProjectIdeas(applicationPeriod);
assertEquals(Arrays.asList(new ProjectIdea[] { projectIdea2 }), projectIdeas);
assertEquals(Arrays.asList(new ProjectIdea[] { projectIdea1, projectIdea2, projectIdea3 }), projectIdeas);
}
@Test
@ -159,11 +157,9 @@ public class TestApplicationPeriodDao {
@Transactional
@Rollback
public void testShouldNotReturnProductIdeasThatAlreadyHaveBecomeProjects() {
projectIdea1.setDateCreated(date("2011-07-01"));
projectIdea1.setProject(project);
projectIdea2.setDateCreated(date("2011-07-01"));
List<ProjectIdea> projectIdeas = applicationPeriodDao.getProjectIdeas(applicationPeriod);
assertEquals(Arrays.asList(new ProjectIdea[] { projectIdea2 }), projectIdeas);
assertEquals(Arrays.asList(new ProjectIdea[] { projectIdea2, projectIdea3 }), projectIdeas);
}
@Test