diff --git a/gemeinsamforschen/pom.xml b/gemeinsamforschen/pom.xml index e23a29992f526e80c3722a35ceb67be4d603cc01..1f8ac1027375f2b712c50715652d7b90a379b5e3 100644 --- a/gemeinsamforschen/pom.xml +++ b/gemeinsamforschen/pom.xml @@ -165,11 +165,49 @@ <version>1.3.4</version> </dependency> + <!-- websocket api --> + <dependency> + <groupId>javax.websocket</groupId> + <artifactId>javax.websocket-api</artifactId> + <version>1.1</version> + <scope>provided</scope> + </dependency> + + <!-- gson --> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.8.5</version> + </dependency> + <dependency> <groupId>com.atlassian.commonmark</groupId> <artifactId>commonmark</artifactId> <version>0.11.0</version> </dependency> + + + <!-- https://mvnrepository.com/artifact/de.dev-eth0.dummycreator/dummy-creator --> + <!-- <dependency> + <groupId>de.dev-eth0.dummycreator</groupId> + <artifactId>dummy-creator</artifactId> + <version>1.2</version> + </dependency>--> + + <!-- https://mvnrepository.com/artifact/org.mockito/mockito-all --> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>2.19.0</version> + </dependency> + + <dependency> + <groupId>uk.co.jemos.podam</groupId> + <artifactId>podam</artifactId> + <version>7.1.1.RELEASE</version> + </dependency> + + </dependencies> </project> \ No newline at end of file diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/assignments/Assignee.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/assignments/Assignee.java new file mode 100644 index 0000000000000000000000000000000000000000..3e3df15225bbdacc627bfe7cdbe77d799fde5374 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/assignments/Assignee.java @@ -0,0 +1,15 @@ +package unipotsdam.gf.assignments; + + public enum Assignee { + AXEL, + CHRISTIAN, + KATHARINA, + LUDWIG, + MARTIN, + MIRJAM, + QUARK, + SVEN, + THOMAS + + +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/assignments/NotImplementedLogger.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/assignments/NotImplementedLogger.java new file mode 100644 index 0000000000000000000000000000000000000000..67e379f9a28b642da2a86de58dbcd7a0a803b3d1 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/assignments/NotImplementedLogger.java @@ -0,0 +1,69 @@ +package unipotsdam.gf.assignments; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import unipotsdam.gf.modules.communication.view.CommunicationView; +import unipotsdam.gf.modules.researchreport.ResearchReportManagement; + +import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; + +public class NotImplementedLogger { + + private static final Logger log = LoggerFactory.getLogger(NotImplementedLogger.class); + private static final ConcurrentHashMap<String, Boolean> messagesSend = new ConcurrentHashMap<String, Boolean>(); + + public static synchronized void logAssignment(Assignee assignee, Class element) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(assignee.name()); + stringBuilder.append(": Please implement "); + stringBuilder.append(element); + String result = stringBuilder.toString(); + + if (!getMessageMap().keySet().contains(result)) { + log.info(result); + } + messagesSend.put(result, true); + } + + public static synchronized void logAssignment(Assignee assignee, Class element, String fakeMessage) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(assignee.name()); + stringBuilder.append(": Please implement "); + stringBuilder.append(element + "\n"); + stringBuilder.append("process: " + fakeMessage + "\n"); + String result = stringBuilder.toString(); + + if (!getMessageMap().keySet().contains(result)) { + log.info(result); + } + messagesSend.put(result, true); + } + + + + public static void logAssignment(Assignee assignee, Class className, String method, String fakeMessage) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(assignee.name()); + stringBuilder.append(": Please implement "); + stringBuilder.append(className.getCanonicalName()); + stringBuilder.append(":"); + stringBuilder.append(method); + stringBuilder.append("\n"); + stringBuilder.append(fakeMessage); + String result = stringBuilder.toString(); + + if (!getMessageMap().keySet().contains(result)) { + log.info(result); + } + messagesSend.put(result, true); + } + + public static synchronized ConcurrentHashMap<String, Boolean> getMessageMap() { + if (messagesSend == null) { + return new ConcurrentHashMap<String, Boolean>(); + } + return messagesSend; + } + +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/config/GFApplicationBinder.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/config/GFApplicationBinder.java index 554cf0504b8783acc9589f00deaa64eb8356a581..6ffde6e89fef8ca74e399b2a63461e2feb9e6c0c 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/config/GFApplicationBinder.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/config/GFApplicationBinder.java @@ -3,13 +3,39 @@ package unipotsdam.gf.config; import org.glassfish.hk2.utilities.binding.AbstractBinder; import unipotsdam.gf.core.management.Management; import unipotsdam.gf.core.management.ManagementImpl; -import unipotsdam.gf.interfaces.ICommunication; +import unipotsdam.gf.core.states.PhasesImpl; +import unipotsdam.gf.core.testsandbox.TestList; +import unipotsdam.gf.core.testsandbox.TestListInterface; +import unipotsdam.gf.interfaces.*; +import unipotsdam.gf.modules.assessment.controller.service.PeerAssessment; +import unipotsdam.gf.modules.assessment.controller.service.PeerAssessmentDummy; import unipotsdam.gf.modules.communication.service.CommunicationDummyService; +import unipotsdam.gf.modules.groupfinding.DummyGroupfinding; +import unipotsdam.gf.modules.journal.DummyJournalImpl; +import unipotsdam.gf.modules.journal.model.Journal; +import unipotsdam.gf.modules.journal.service.DummyJournalService; +import unipotsdam.gf.modules.peer2peerfeedback.DummyFeedback; +import unipotsdam.gf.modules.researchreport.DummyResearchReportManagement; +import unipotsdam.gf.modules.researchreport.ResearchReport; +import unipotsdam.gf.modules.researchreport.ResearchReportManagement; public class GFApplicationBinder extends AbstractBinder { + + /** + * TODO replace DummyImplementation + */ @Override protected void configure() { bind(CommunicationDummyService.class).to(ICommunication.class); bind(ManagementImpl.class).to(Management.class); + bind(DummyFeedback.class).to(Feedback.class); + bind(DummyJournalImpl.class).to(IJournal.class); + bind(PeerAssessmentDummy.class).to(IPeerAssessment.class); + bind(PhasesImpl.class).to(IPhases.class); + bind(ManagementImpl.class).to(Management.class); + bind(DummyResearchReportManagement.class).to(ResearchReportManagement.class); + bind(TestList.class).to(TestListInterface.class); + bind(DummyGroupfinding.class).to(IGroupFinding.class); + } } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/config/GFDatabaseConfig.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/config/GFDatabaseConfig.java index 252905102d2472eaa125f06499bbdfe1663ea254..cefe2e289c2727db459f27dc5606aa0ceb9f9d6b 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/config/GFDatabaseConfig.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/config/GFDatabaseConfig.java @@ -7,7 +7,7 @@ public class GFDatabaseConfig { public static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; public static final String DB_URL = "jdbc:mysql://localhost"; // Database credentials - public static final String USER = "root"; - public static final String PASS = ""; + public static final String USER = "root2"; + public static final String PASS = "voyager2"; public static final String DB_NAME = "fltrail"; } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/database/mysql/MysqlConnect.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/database/mysql/MysqlConnect.java index 7ce548e4f2df27d260a82745520ed08e0962f389..d5c42e2cceb64410da5b040a276c63c10083d4ee 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/database/mysql/MysqlConnect.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/database/mysql/MysqlConnect.java @@ -3,13 +3,15 @@ package unipotsdam.gf.core.database.mysql; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import unipotsdam.gf.config.GFDatabaseConfig; +import unipotsdam.gf.modules.communication.view.CommunicationView; import java.sql.*; import java.util.Date; public class MysqlConnect { - private final Logger log = LoggerFactory.getLogger(MysqlConnect.class); + private static final Logger log = LoggerFactory.getLogger(MysqlConnect.class); + public Connection conn = null; private static String createConnectionString() { @@ -28,7 +30,7 @@ public class MysqlConnect { } catch (ClassNotFoundException ex) { System.out.println(ex); //logger? } - conn = DriverManager.getConnection(MysqlConnect.createConnectionString()); + conn = DriverManager.getConnection(createConnectionString()); } catch (SQLException ex) { System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); @@ -43,71 +45,77 @@ public class MysqlConnect { if (conn != null) { conn.close(); } - } catch (SQLException e) { + } catch (final SQLException e) { + log.error(e.toString()); throw new Error("could not close mysql"); } } - private PreparedStatement addParameters(String statement, Object[] args) { + private PreparedStatement addParameters(final String statement, final Object[] args) { try { - PreparedStatement ps = conn.prepareStatement(statement); + final PreparedStatement ps = conn.prepareStatement(statement); if (args != null) { for (int i = 0; i < args.length; i++) { - Object arg = args[i]; + final Object arg = args[i]; setParam(ps, arg, i + 1); } } return ps; } catch (SQLException ex) { + log.error(ex.toString()); System.out.println(ex); } return null; } - public VereinfachtesResultSet issueSelectStatement(String statement, Object... args) { + public VereinfachtesResultSet issueSelectStatement(final String statement, final Object... args) { try { PreparedStatement ps = addParameters(statement, args); ResultSet queryResult = ps.executeQuery(); return new VereinfachtesResultSet(queryResult); } catch (SQLException ex) { + log.error(ex.toString()); System.out.println(ex); } return null; } - public void otherStatements(String statement) { + public void otherStatements(final String statement) { try { - conn.createStatement().execute(statement); + this.conn.createStatement().execute(statement); } catch (SQLException ex) { + log.error(ex.toString()); System.out.println(ex); } } - public Integer issueUpdateStatement(String statement, Object... args) { + public Integer issueUpdateStatement(final String statement, final Object... args) { PreparedStatement ps = addParameters(statement, args); - log.debug("Statement:" + ps.toString()); try { return ps.executeUpdate(); } catch (SQLException ex) { + log.error(ex.toString()); System.out.println(ex); } return null; } - public void issueInsertOrDeleteStatement(String statement, Object... args) { + public void issueInsertOrDeleteStatement(final String statement, final Object... args) { PreparedStatement ps = addParameters(statement, args); try { ps.execute(); } catch (SQLException ex) { + + log.error(ex.toString()); System.out.println(ex); } } - private void setParam(PreparedStatement ps, Object arg, int i) throws SQLException { + private void setParam(final PreparedStatement ps, final Object arg, final int i) throws SQLException { if (arg instanceof String) { ps.setString(i, (String) arg); } else if (arg instanceof Integer) { @@ -127,7 +135,7 @@ public class MysqlConnect { } else if (arg instanceof Character) { ps.setString(i, arg.toString()); } else if (arg instanceof Date) { - java.sql.Date d = new java.sql.Date(((Date) arg).getTime()); + final java.sql.Date d = new java.sql.Date(((Date) arg).getTime()); ps.setDate(i, d); } else if (arg == null) { ps.setNull(i, Types.NULL); diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/Management.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/Management.java index 73c0b1e608c2ea6dc3821ad703904162908d9577..3c238f6be74199530d2e17a37d65ce7244858bab 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/Management.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/Management.java @@ -2,6 +2,7 @@ package unipotsdam.gf.core.management; import unipotsdam.gf.core.management.group.Group; import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.core.management.project.ProjectConfiguration; import unipotsdam.gf.core.management.user.User; import unipotsdam.gf.core.management.user.UserInterests; import unipotsdam.gf.core.management.user.UserProfile; @@ -120,5 +121,9 @@ public interface Management { void deleteGroupMember(User groupMember, int groupId); List<Group> getGroupsByProjectId(String projectId); + + void create(ProjectConfiguration projectConfiguration, Project project); + + ProjectConfiguration getProjectConfiguration(Project project); } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/ManagementImpl.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/ManagementImpl.java index 8d98b2c0dd607ff3b33a62ec367255863a030214..1ee2cf14cbceb21ad8f2222dd3373dd17bb05cfd 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/ManagementImpl.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/ManagementImpl.java @@ -4,9 +4,12 @@ import unipotsdam.gf.core.database.mysql.MysqlConnect; import unipotsdam.gf.core.database.mysql.VereinfachtesResultSet; import unipotsdam.gf.core.management.group.Group; import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.core.management.project.ProjectConfiguration; +import unipotsdam.gf.core.management.project.ProjectConfigurationDAO; import unipotsdam.gf.core.management.user.User; import unipotsdam.gf.core.management.user.UserInterests; import unipotsdam.gf.core.management.user.UserProfile; +import unipotsdam.gf.core.states.ProjectPhase; import unipotsdam.gf.modules.assessment.controller.model.Quiz; import unipotsdam.gf.modules.assessment.controller.model.StudentIdentifier; @@ -56,13 +59,15 @@ public class ManagementImpl implements Management { UUID uuid = UUID.randomUUID(); String token = uuid.toString(); + MysqlConnect connect = new MysqlConnect(); connect.connect(); String mysqlRequest = "INSERT INTO projects (`id`, `password`, `active`, `timecreated`, `author`, " - + "`adminPassword`, `token`) values (?,?,?,?,?,?,?)"; + + "`adminPassword`, `token`, `phase`) values (?,?,?,?,?,?,?,?)"; connect.issueInsertOrDeleteStatement(mysqlRequest, project.getId(), project.getPassword(), project.isActive(), - project.getTimecreated(), project.getAuthor(), project.getAdminPassword(), token); + project.getTimecreated(), project.getAuthor(), project.getAdminPassword(), token, project.getPhase() + == null ? ProjectPhase.CourseCreation : project.getPhase()); connect.close(); } @@ -134,11 +139,15 @@ public class ManagementImpl implements Management { connect.connect(); VereinfachtesResultSet vereinfachtesResultSet = connect.issueSelectStatement(query, project.getId()); while (!vereinfachtesResultSet.isLast()) { - vereinfachtesResultSet.next(); - User user = getUserFromResultSet(vereinfachtesResultSet); - String token = vereinfachtesResultSet.getString("token"); - user.setToken(token); - result.add(user); + Boolean next = vereinfachtesResultSet.next(); + if (next) { + User user = getUserFromResultSet(vereinfachtesResultSet); + String token = vereinfachtesResultSet.getString("token"); + user.setToken(token); + result.add(user); + } else { + break; + } } connect.close(); return result; @@ -162,6 +171,7 @@ public class ManagementImpl implements Management { String author = vereinfachtesResultSet.getString("author"); String adminPassword = vereinfachtesResultSet.getString("adminpassword"); String token = vereinfachtesResultSet.getString("token"); + String phase = vereinfachtesResultSet.getString("phase"); return new Project(id, password, active, timestamp, author, adminPassword, token); } @@ -173,6 +183,7 @@ public class ManagementImpl implements Management { // TODO: determine how to get all User return new Group(id, new ArrayList<>(), projectId, chatRoomId); } + @Override public String getUserToken(User user) { MysqlConnect connect = new MysqlConnect(); @@ -200,6 +211,13 @@ public class ManagementImpl implements Management { return getUserByField("email", email); } + + /** + * TODO @Axel bitte in modules/asessment verschieben + * @param projectId + * @param quizId + * @return + */ public Quiz getQuizByProjectGroupId(String projectId, String quizId){ MysqlConnect connect = new MysqlConnect(); connect.connect(); @@ -310,4 +328,16 @@ public class ManagementImpl implements Management { return groups; } } + + @Override + public void create(ProjectConfiguration projectConfiguration, Project project) { + ProjectConfigurationDAO projectConfigurationDAO = new ProjectConfigurationDAO(); + projectConfigurationDAO.persistProjectConfiguration(projectConfiguration,project); + } + + @Override + public ProjectConfiguration getProjectConfiguration(Project project) { + ProjectConfigurationDAO projectConfigurationDAO = new ProjectConfigurationDAO(); + return projectConfigurationDAO.loadProjectConfiguration(project); + } } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/project/Project.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/project/Project.java index 682b5c40b13472a4bc3369eb7970ddb9bce428fd..06bd24d75edced5f007ff2db5a58b1bbcd6b30ab 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/project/Project.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/project/Project.java @@ -1,5 +1,7 @@ package unipotsdam.gf.core.management.project; +import unipotsdam.gf.core.states.ProjectPhase; + import java.sql.Timestamp; import java.time.LocalDateTime; import java.time.ZoneId; @@ -16,6 +18,8 @@ public class Project { private String author; private String adminPassword; private String token; + // using enum ProjectPhase + private String phase; public Project() { } @@ -26,8 +30,21 @@ public class Project { this.active = active; this.author = author; this.adminPassword = adminPassword; - this.timecreated = Timestamp.valueOf(LocalDateTime.now(ZoneId.of("UTC"))); + // default starting at course creation if new + this.setPhase(ProjectPhase.CourseCreation); + } + + public String getPhase() { + return phase; + } + + /** + * setting phase only with enum + * @param phase + */ + public void setPhase(ProjectPhase phase) { + this.phase = phase.name(); } public Project(String id, String password, Boolean active, String author, String adminPassword, String token) { diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/project/ProjectConfiguration.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/project/ProjectConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..cc66f5634f1f05f969fcd423c24ce9134d21a653 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/project/ProjectConfiguration.java @@ -0,0 +1,66 @@ +package unipotsdam.gf.core.management.project; + +import unipotsdam.gf.core.states.ProjectPhase; +import unipotsdam.gf.modules.assessment.AssessmentMechanism; +import unipotsdam.gf.modules.groupfinding.GroupFormationMechanism; +import unipotsdam.gf.modules.peer2peerfeedback.Category; + +import java.util.HashMap; + +// TODO implement +public class ProjectConfiguration { + + private HashMap<ProjectPhase, Boolean> phasesSelected; + private HashMap<Category, Boolean> criteriaSelected; + private HashMap<AssessmentMechanism, Boolean> assessmentMechanismSelected; + private HashMap<GroupFormationMechanism, Boolean> groupMechanismSelected; + + public ProjectConfiguration( + HashMap<ProjectPhase, Boolean> phasesSelected, + HashMap<Category, Boolean> criteriaSelected, + HashMap<AssessmentMechanism, Boolean> assessmentMechanismSelected, + HashMap<GroupFormationMechanism, Boolean> groupMechanismSelected) { + this.phasesSelected = phasesSelected; + this.criteriaSelected = criteriaSelected; + this.assessmentMechanismSelected = assessmentMechanismSelected; + this.groupMechanismSelected = groupMechanismSelected; + } + + public HashMap<ProjectPhase, Boolean> getPhasesSelected() { + return phasesSelected; + } + + public void setPhasesSelected(HashMap<ProjectPhase, Boolean> phasesSelected) { + this.phasesSelected = phasesSelected; + } + + public HashMap<Category, Boolean> getCriteriaSelected() { + return criteriaSelected; + } + + public void setCriteriaSelected( + HashMap<Category, Boolean> criteriaSelected) { + this.criteriaSelected = criteriaSelected; + } + + public HashMap<AssessmentMechanism, Boolean> getAssessmentMechanismSelected() { + return assessmentMechanismSelected; + } + + public void setAssessmentMechanismSelected( + HashMap<AssessmentMechanism, Boolean> assessmentMechanismSelected) { + this.assessmentMechanismSelected = assessmentMechanismSelected; + } + + + public HashMap<GroupFormationMechanism, Boolean> getGroupMechanismSelected() { + return groupMechanismSelected; + } + + public void setGroupMechanismSelected( + HashMap<GroupFormationMechanism, Boolean> groupMechanismSelected) { + this.groupMechanismSelected = groupMechanismSelected; + } + + +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/project/ProjectConfigurationDAO.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/project/ProjectConfigurationDAO.java new file mode 100644 index 0000000000000000000000000000000000000000..6a9f147857cc89528fa38a08e85c878b8d474cf3 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/project/ProjectConfigurationDAO.java @@ -0,0 +1,128 @@ +package unipotsdam.gf.core.management.project; + +import unipotsdam.gf.core.database.mysql.MysqlConnect; +import unipotsdam.gf.core.database.mysql.VereinfachtesResultSet; +import unipotsdam.gf.core.management.user.User; +import unipotsdam.gf.core.states.ProjectPhase; +import unipotsdam.gf.modules.assessment.AssessmentMechanism; +import unipotsdam.gf.modules.groupfinding.GroupFormationMechanism; +import unipotsdam.gf.modules.peer2peerfeedback.Category; + +import java.util.ArrayList; +import java.util.HashMap; + +public class ProjectConfigurationDAO { + + /** + * @param projectConfiguration + */ + public void persistProjectConfiguration(ProjectConfiguration projectConfiguration, Project project) { + MysqlConnect connect = new MysqlConnect(); + connect.connect(); + + // persist Criteria + HashMap<Category, Boolean> criteriaSelected = projectConfiguration.getCriteriaSelected(); + for (Category category : criteriaSelected.keySet()) { + Boolean criteriumSelected = criteriaSelected.get(category); + if (criteriumSelected != null && criteriumSelected) { + String projectId = project.getId(); + String categoryName = category.name(); + String mysqlRequest = "insert INTO categoriesSelected (`projectId`,`categorySelected`) VALUES (?,?)"; + connect.issueInsertOrDeleteStatement(mysqlRequest, projectId, categoryName ); + } + } + + // persist Phases + HashMap<ProjectPhase, Boolean> phasesSelected = projectConfiguration.getPhasesSelected(); + for (ProjectPhase phase : phasesSelected.keySet()) { + Boolean projectPhaseSelected = phasesSelected.get(phase); + if (projectPhaseSelected != null && projectPhaseSelected) { + String mysqlRequest = "insert INTO phasesSelected (`projectId`,`phaseSelected`) VALUES (?,?)"; + connect.issueInsertOrDeleteStatement(mysqlRequest, project.getId(), phase.name()); + } + } + + // persist GroupFinding + HashMap<GroupFormationMechanism, Boolean> groupFindingMechanism = + projectConfiguration.getGroupMechanismSelected(); + for (GroupFormationMechanism gfm : groupFindingMechanism.keySet()) { + Boolean groupFindingMechanismSelected = groupFindingMechanism.get(gfm); + if (groupFindingMechanismSelected != null && groupFindingMechanismSelected) { + String mysqlRequest = + "insert INTO groupfindingMechanismSelected (`projectId`,`gfmSelected`) VALUES (?,?)"; + connect.issueInsertOrDeleteStatement(mysqlRequest, project.getId(), gfm.name()); + } + } + + + // persist assessmentMechanismSelected + HashMap<AssessmentMechanism, Boolean> assessmentMechanismsSelected = + projectConfiguration.getAssessmentMechanismSelected(); + for (AssessmentMechanism assessmentMechanism : assessmentMechanismsSelected.keySet()) { + Boolean asmSelected = assessmentMechanismsSelected.get(assessmentMechanism); + if (asmSelected != null && asmSelected) { + String mysqlRequest = + "insert INTO assessmentMechanismSelected (`projectId`,`amSelected`) VALUES (?,?)"; + connect.issueInsertOrDeleteStatement(mysqlRequest, project.getId(), assessmentMechanism.name()); + } + } + connect.close(); + } + + public ProjectConfiguration loadProjectConfiguration(Project project) { + MysqlConnect connect = new MysqlConnect(); + connect.connect(); + + + HashMap<ProjectPhase, Boolean> projectPhasesSelected = + getSelectionFromTable(connect, ProjectPhase.class, project, "phasesSelected"); + + HashMap<Category, Boolean> categorySelected = + getSelectionFromTable(connect, Category.class, project, "categoriesSelected"); + + HashMap<AssessmentMechanism, Boolean> asmSelected = + getSelectionFromTable(connect, AssessmentMechanism.class, project, "assessmentMechanismSelected"); + + + HashMap<GroupFormationMechanism, Boolean> gfmSelected = + getSelectionFromTable(connect, GroupFormationMechanism.class, project, "groupfindingMechanismSelected"); + + connect.close(); + + ProjectConfiguration projectConfiguration = new ProjectConfiguration(projectPhasesSelected, categorySelected, + asmSelected,gfmSelected); + return projectConfiguration; + } + + /** + * this looks like magic but it is just a hack loading all the config tables by taking advantage + * of the fact that they all have two columns with the second being the selected attribute and the first being the + * project id + * + * @param connect + * @param selectionclass + * @param project + * @param table + * @param <T> + * @return + */ + private <T extends Enum<T>> HashMap<T, Boolean> getSelectionFromTable( + MysqlConnect connect, Class<T> selectionclass, Project project, String table) { + // get phasesSelected + String id = project.getId(); + String mysqlRequest = "SELECT * FROM " + table + " where projectId = ?"; + VereinfachtesResultSet vereinfachtesResultSet = connect.issueSelectStatement(mysqlRequest, id); + HashMap<T, Boolean> projectPhaseBoolean = new HashMap<>(); + while (!vereinfachtesResultSet.isLast()) { + Boolean next = vereinfachtesResultSet.next(); + if (next) { + String phaseSelected = vereinfachtesResultSet.getObject(2).toString(); + T phaseSelected1 = Enum.valueOf(selectionclass, phaseSelected); + projectPhaseBoolean.put(phaseSelected1, true); + } else { + break; + } + } + return projectPhaseBoolean; + } +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/user/Menu.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/user/Menu.java index f5ccb7490771953ed577159aef335bc032e59f00..16e3f3ffe900a17b77df2719adfc93ee1d5b6053 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/user/Menu.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/user/Menu.java @@ -9,6 +9,8 @@ import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.SimpleTagSupport; import java.io.IOException; + +// TODO: please move this to a view package at the top of the hierarchy as this is not part of the user package public class Menu extends SimpleTagSupport { public void doTag() throws JspException, IOException { PageContext pageContext = (PageContext) getJspContext(); diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/user/UserService.java.orig b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/user/UserService.java.orig deleted file mode 100644 index 73d84e8fa40445fffec6c0a31a5523f9fb5e318f..0000000000000000000000000000000000000000 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/user/UserService.java.orig +++ /dev/null @@ -1,163 +0,0 @@ -package unipotsdam.gf.core.management.user; - -import unipotsdam.gf.core.management.ManagementImpl; -import unipotsdam.gf.interfaces.ICommunication; -import unipotsdam.gf.modules.communication.service.CommunicationDummyService; - -import javax.annotation.ManagedBean; -import javax.inject.Inject; -import javax.ws.rs.FormParam; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.net.URI; -import java.net.URISyntaxException; - -@Path("/user") -@ManagedBean -public class UserService { - - @Inject - private ICommunication communicationService; - - /** - * creates a user with given credentials - * - * @param name - * @param password - * @param email - * @param isStudent - * @return - * @throws URISyntaxException - */ - // This method is called if HTML is request - @POST - @Produces(MediaType.TEXT_HTML) - @Path("/create") - public Response createUser(@FormParam("name") String name, @FormParam("password") String password, - @FormParam("email") String email, @FormParam("isStudent") String isStudent) - throws URISyntaxException { - - ManagementImpl management = new ManagementImpl(); - User user = new User(name, password, email, isStudent == null); - return login(true, user); - - } - - /** - * checks if a user exists in order to log him in - * - * @param name - * @param password - * @param email - * @return - * @throws URISyntaxException - */ - // This method is called if HTML is request - @POST - @Produces(MediaType.TEXT_HTML) - @Path("/exists") - public Response existsUser(@FormParam("name") String name, @FormParam("password") String password, - @FormParam("email") String email) - throws URISyntaxException { - - ManagementImpl management = new ManagementImpl(); - User user = new User(name, password, email, null); - ICommunication iCommunication = new CommunicationDummyService(); - boolean isLoggedIn = iCommunication.loginUser(user); - if (isLoggedIn) { - return login(false, user); - } else { - return loginError(); - } - - - } - - /** - * if create User is true, the user is created and logged in if he does not exist - * - * @param createUser - * @param user - * @return - * @throws URISyntaxException - */ - protected Response login(boolean createUser, User user) throws URISyntaxException { - ManagementImpl management = new ManagementImpl(); - if (management.exists(user)) { - if (!createUser) { -<<<<<<< HEAD - ManagementImpl m = new ManagementImpl(); - String token = m.getUserToken(user); - user = m.getUser(token); -======= - boolean successfulLogin = communicationService.loginUser(user); - management.update(user); - if (!successfulLogin) { - return loginError(); - } ->>>>>>> 9bbae0ff75b2597ab35479a24d47c12e7a4cc0fd - return redirectToProjectPage(user, management); - } - String existsUrl = "../register.jsp?userExists=true"; - return forwardToLocation(existsUrl); - } else { - if (createUser) { - boolean isRegisteredAndLoggedIn = communicationService.registerAndLoginUser(user); - if (!isRegisteredAndLoggedIn) { - return registrationError(); - } - management.create(user, null); - } else { - String existsUrl = "../index.jsp?userExists=false"; - return forwardToLocation(existsUrl); - } - ManagementImpl m = new ManagementImpl(); - String token = m.getUserToken(user); - user = m.getUser(token); //todo: write query to get user isStudent - return redirectToProjectPage(user, management); - } - } - - private Response registrationError() throws URISyntaxException { - String existsUrl = "../register.jsp?registrationError=true"; - return forwardToLocation(existsUrl); - } - - private Response loginError() throws URISyntaxException { - String existsUrl = "../index.jsp?loginError=true"; - return forwardToLocation(existsUrl); - } - - /** - * helper function for redirecting to the right project page - * - * @param user - * @param management - * @return - * @throws URISyntaxException - */ - private Response redirectToProjectPage(User user, ManagementImpl management) throws URISyntaxException { - String successUrl; - if (user.getStudent() != null && user.getStudent()) { - successUrl = "../pages/overview-student.html?token="; - } else { - successUrl = "../pages/overview-docent.html?token="; - } - successUrl += management.getUserToken(user); - return forwardToLocation(successUrl); - } - - /** - * * helper function for redirecting to a new page - * - * @param existsUrl - * @return - * @throws URISyntaxException - */ - private Response forwardToLocation(String existsUrl) throws URISyntaxException { - return Response.seeOther(new URI(existsUrl)).build(); - } -} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/states/PhasesImpl.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/states/PhasesImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..7bcf8a20fdb75120b33e7dae2b5cba48013ec3d7 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/states/PhasesImpl.java @@ -0,0 +1,121 @@ +package unipotsdam.gf.core.states; + +import unipotsdam.gf.core.database.mysql.MysqlConnect; +import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.interfaces.*; +import unipotsdam.gf.view.Messages; + +import javax.annotation.ManagedBean; +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Singleton; + +/** + * Created by dehne on 31.05.2018. + * This class should be used to manage changing the phases in a central location + * it has dependencies to most modules, as they are required to check the constraints + * when changing between phases + */ +@ManagedBean +public class PhasesImpl implements IPhases { + + private IPeerAssessment iPeerAssessment; + + private Feedback feedback; + + private ICommunication iCommunication; + + private IJournal iJournal; + + public PhasesImpl() { + } + + /** + * use this if you don't know how dependency injection works + * @param iPeerAssessment + * @param feedback + * @param iCommunication + * @param iJournal + */ + @Inject + public PhasesImpl(IPeerAssessment iPeerAssessment, Feedback feedback, ICommunication iCommunication, IJournal iJournal) { + this.iPeerAssessment = iPeerAssessment; + this.feedback = feedback; + this.iCommunication = iCommunication; + this.iJournal = iJournal; + } + + @Override + public void endPhase(ProjectPhase currentPhase, Project project) { + switch (currentPhase) { + case CourseCreation: + // saving the state + saveState(project,getNextPhase(currentPhase)); + break; + case GroupFormation: + // inform users about the formed groups, optionally giving them a hint on what happens next + iCommunication.sendMessageToUsers(project, Messages.GroupFormation(project)); + saveState(project,getNextPhase(currentPhase)); + break; + case DossierFeedback: + // check if everybody has uploaded a dossier + Boolean feedbacksGiven = feedback.checkFeedbackConstraints(project); + if (!feedbacksGiven) { + feedback.assigningMissingFeedbackTasks(project); + } else { + // send a message to the users informing them about the start of the new phase + iCommunication.sendMessageToUsers(project, Messages.NewFeedbackTask(project)); + saveState(project,getNextPhase(currentPhase)); + } + break; + case Execution: + // check if the portfolios have been prepared for evaluation (relevant entries selected) + Boolean portfoliosReady = iJournal.getPortfoliosForEvaluationPrepared(project); + if (portfoliosReady) { + // inform users about the end of the phase + iCommunication.sendMessageToUsers(project, Messages.AssessmentPhaseStarted(project)); + saveState(project,getNextPhase(currentPhase)); + } else { + iJournal.assignMissingPortfolioTasks(project); + } + break; + case Assessment: + closeProject(); + break; + } + } + + private void closeProject() { + // TODO implement + } + + ProjectPhase getNextPhase(ProjectPhase projectPhase) { + switch (projectPhase) { + case CourseCreation: + return ProjectPhase.GroupFormation; + case GroupFormation: + return ProjectPhase.DossierFeedback; + case DossierFeedback: + return ProjectPhase.Execution; + case Execution: + return ProjectPhase.Assessment; + case Assessment: + return ProjectPhase.Projectfinished; + } + return null; + } + + private void saveState(Project project, ProjectPhase currentPhase) { + assert project.getId() != null; + MysqlConnect connect = new MysqlConnect(); + connect.connect(); + String mysqlRequest = "UPDATE `projects` SET `phase`=? WHERE id=? LIMIT 1"; + connect.issueUpdateStatement(mysqlRequest, currentPhase.name(), project.getId()); + connect.close(); + } + + + public void setFeedback(Feedback feedback) { + this.feedback = feedback; + } +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/states/PhasesService.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/states/PhasesService.java new file mode 100644 index 0000000000000000000000000000000000000000..e3ad42205b6ae45070ae70f643a9f6e662757a18 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/states/PhasesService.java @@ -0,0 +1,47 @@ +package unipotsdam.gf.core.states; + +import unipotsdam.gf.core.management.Management; +import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.interfaces.IPhases; + +import javax.inject.Inject; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; + +/** + * REST API for switching phases + * In order to look up the possible phases @see unipotsdam.gf.core.states.ProjectPhase + */ +@Path("/phases") +public class PhasesService { + + @Inject + private IPhases phases; + + @Inject + private Management management; + + /** + * end phase + * @param projectPhase + * @param projectId + */ + @Path("/{projectPhase}/projects/{projectId}") + @POST + @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + public void endPhase(@PathParam("projectPhase") String projectPhase, @PathParam("projectId") String projectId) { + phases.endPhase(ProjectPhase.valueOf(projectPhase), management.getProjectById(projectId)); + } + + /** + * get current phase + * @param projectId + * @return + */ + @Path("/{projectPhase}/projects/{projectId}") + @GET + @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + public String getCurrentPhase(@PathParam("projectId") String projectId) { + return management.getProjectById(projectId).getPhase(); + } +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/states/ProjectPhase.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/states/ProjectPhase.java new file mode 100644 index 0000000000000000000000000000000000000000..328b415f28a8379e81258b79eb671e16614e0417 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/states/ProjectPhase.java @@ -0,0 +1,6 @@ +package unipotsdam.gf.core.states; + +public enum ProjectPhase { + CourseCreation, GroupFormation, DossierFeedback, Execution, Assessment, + Projectfinished; +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/testsandbox/TestList.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/testsandbox/TestList.java new file mode 100644 index 0000000000000000000000000000000000000000..b97885acab50b9ecb950a89c16fdf3308b91dd31 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/testsandbox/TestList.java @@ -0,0 +1,6 @@ +package unipotsdam.gf.core.testsandbox; + +import java.util.ArrayList; + +public class TestList extends ArrayList implements TestListInterface { +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/testsandbox/TestListInterface.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/testsandbox/TestListInterface.java new file mode 100644 index 0000000000000000000000000000000000000000..f541c49860e102e89d727c80d21a9831d0ceb8f5 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/core/testsandbox/TestListInterface.java @@ -0,0 +1,4 @@ +package unipotsdam.gf.core.testsandbox; + +public interface TestListInterface extends java.util.List { +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/Feedback.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/Feedback.java index 6ba367ce70e0ce14f2492b9dab298d2d284a405d..5f70b51d18b5b423a9e419294622668040fcee19 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/Feedback.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/Feedback.java @@ -1,7 +1,9 @@ package unipotsdam.gf.interfaces; +import unipotsdam.gf.core.management.project.Project; import unipotsdam.gf.core.management.user.User; import unipotsdam.gf.modules.peer2peerfeedback.Peer2PeerFeedback; -import java.*; +import unipotsdam.gf.modules.researchreport.ResearchReport; + import java.io.File; import java.util.ArrayList; @@ -26,12 +28,12 @@ public interface Feedback { /** * give Peer2PeerFeedback * - * @param feedback: The Peer2PeerFeedback as an Object - * @param document: The selected document + * @param feedback : The Peer2PeerFeedback as an Object + * @param document : The selected document * @return Send feedback with doc and return true, if the feedback is successfully sended */ - Boolean giveFeedback(Peer2PeerFeedback feedback, File document); + Boolean giveFeedback(Peer2PeerFeedback feedback, ResearchReport document); /** * show Feedbackhistory @@ -51,4 +53,28 @@ public interface Feedback { int countFeedback(User student); + /** + * TODO implement check in DB that everybody has given feedback + * @param project + * @return + */ + Boolean checkFeedbackConstraints(Project project); + + /** + * TODO implement a routine that assigns missing feedback tasks if someone drops out of a course + * @param project + */ + void assigningMissingFeedbackTasks(Project project); + + /** + * TODO implement: Assigns each student in a project a feedback target + */ + void assignFeedbackTasks(); + + /** + * TODO implement: Get the research report you have to give feedback to + * @param student + * @return + */ + ResearchReport getFeedbackTask(User student); } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/ICommunication.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/ICommunication.java index 12d3d71183ae34966d1e88a04596095c22eadd42..2705893f7f91d50b0052c22d9171aa74de43681c 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/ICommunication.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/ICommunication.java @@ -1,6 +1,8 @@ package unipotsdam.gf.interfaces; +import unipotsdam.gf.core.management.project.Project; import unipotsdam.gf.core.management.user.User; +import unipotsdam.gf.assignments.NotImplementedLogger; import unipotsdam.gf.modules.communication.model.Message; import unipotsdam.gf.modules.communication.model.chat.ChatMessage; import unipotsdam.gf.modules.communication.model.chat.ChatRoom; @@ -22,7 +24,7 @@ public interface ICommunication { List<ChatMessage> getChatHistory(String roomId); - boolean sendMessageToChat(Message message, String roomId); + boolean sendMessageToChat(Message message, String roomId) ; /** * endpoint: https://rocket.chat/docs/developer-guides/rest-api/groups/create/ @@ -44,7 +46,7 @@ public interface ICommunication { */ boolean addUserToChatRoom(String roomId, User user); - boolean removeUserFromChatRoom(User user, String roomId); + boolean removeUserFromChatRoom(User user, String roomId) ; /** * endpoint: https://rocket.chat/docs/developer-guides/rest-api/groups/settopic/ @@ -85,4 +87,9 @@ public interface ICommunication { String getChatRoomLink(String userToken, String projectToken, String groupToken); + // TODO implement as Email or whatever + void sendSingleMessage(Message message, User user); + + // TODO implement as Email or whatever + void sendMessageToUsers(Project project, String message); } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/ICourseCreation.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/ICourseCreation.java new file mode 100644 index 0000000000000000000000000000000000000000..2d0b0f5a4e34646e177ce3cf5cd044925c2458f9 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/ICourseCreation.java @@ -0,0 +1,4 @@ +package unipotsdam.gf.interfaces; + +public interface ICourseCreation { +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/IGroupFinding.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/IGroupFinding.java new file mode 100644 index 0000000000000000000000000000000000000000..9b7f67050cf2a080cf0b70e191e35c31176c0622 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/IGroupFinding.java @@ -0,0 +1,36 @@ +package unipotsdam.gf.interfaces; + +import unipotsdam.gf.core.management.group.Group; +import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.assignments.NotImplementedLogger; +import unipotsdam.gf.modules.groupfinding.GroupFormationMechanism; +import unipotsdam.gf.modules.groupfinding.GroupfindingCriteria; + +public interface IGroupFinding { + + /** + * Select the groupfinding criteria used + * @param groupfindingCriteria + */ + void selectGroupfindingCriteria(GroupfindingCriteria groupfindingCriteria); + + /** + * Persist the selected manual groups + * @param groupComposition + */ + void persistGroups(java.util.List<Group> groupComposition, Project project); + + /** + * @param project + * @return + */ + java.util.List<Group> getGroups(Project project); + + /** + * + * @param groupFindingMechanism + */ + void formGroups(GroupFormationMechanism groupFindingMechanism); + + +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/IJournal.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/IJournal.java index 4da8b21c8ed3871d6824944e2f90b1a19315724e..6630d9f81ed28bcd5ecb4e3a9aeee9ecf795d37f 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/IJournal.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/IJournal.java @@ -1,7 +1,16 @@ package unipotsdam.gf.interfaces; +import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.core.management.user.User; +import unipotsdam.gf.assignments.NotImplementedLogger; import unipotsdam.gf.modules.assessment.controller.model.StudentIdentifier; +import unipotsdam.gf.modules.journal.model.Journal; +import unipotsdam.gf.modules.researchreport.ResearchReport; + +import javax.swing.text.html.HTML; +import java.io.File; +import java.util.List; /** * Interface for learning journal @@ -14,6 +23,43 @@ public interface IJournal { * @param student StudentIdentifier * @return the journal as String (may change) */ - String exportJournal (StudentIdentifier student); + String exportJournal (StudentIdentifier student) ; + + /** + * check if all students have prepared their portfolios to be evaluated + * @return + * @param project + */ + Boolean getPortfoliosForEvaluationPrepared(Project project) ; + /** + * find out, who hasn't prepared their portfolio for evaluation and send message or highlight in view + * @param project + */ + void assignMissingPortfolioTasks(Project project) ; + + /** + * after user has uploaded a journal entry this function is called + * @param journalEntry + * @param student + */ + void uploadJournalEntry(Journal journalEntry, User student) ; + + /** + * persist final portfolio for assessment + * + * Maybe create a class for the collected portfolio + * @param journalEntries + * @param finalResearchReport + * @param presentation + */ + void uploadFinalPortfolio(Project project, List<Journal> journalEntries, ResearchReport finalResearchReport, File + presentation, User user) ; + + /** + * + * @param project + * @return + */ + HTML getFinalPortfolioForAssessment(Project project, User user) ; } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/IPeerAssessment.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/IPeerAssessment.java index e3b65f1474d62074a4cf33b422a11ebda2d478b0..e204835e7693c672b2073dc9bce3839643cdadc2 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/IPeerAssessment.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/IPeerAssessment.java @@ -1,5 +1,7 @@ package unipotsdam.gf.interfaces; +import unipotsdam.gf.assignments.NotImplementedLogger; +import unipotsdam.gf.modules.assessment.QuizAnswer; import unipotsdam.gf.modules.assessment.controller.model.*; import java.util.ArrayList; @@ -31,7 +33,7 @@ public interface IPeerAssessment { * * @param studentAndQuiz */ - void createQuiz(StudentAndQuiz studentAndQuiz); + void createQuiz(StudentAndQuiz studentAndQuiz) ; /** * calculate grades for everyone in a list. @@ -74,4 +76,11 @@ public interface IPeerAssessment { * @param groupId */ void postPeerRating(ArrayList<PeerRating> peerRatings, String projectId, String groupId); + + /** + * + * @param studentAndQuiz + * @param quizAnswer + */ + void answerQuiz(StudentAndQuiz studentAndQuiz, QuizAnswer quizAnswer); } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/IPhases.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/IPhases.java new file mode 100644 index 0000000000000000000000000000000000000000..976d67d13cdbb82a565b704b9213a8ac6677495e --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/interfaces/IPhases.java @@ -0,0 +1,19 @@ +package unipotsdam.gf.interfaces; + +import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.core.states.ProjectPhase; + +public interface IPhases { + /** + * switch from one phase to the next + * @param projectPhase + * @param project + */ + public void endPhase(ProjectPhase projectPhase, Project project); + + /** + * the dependency to feedback should be settable externally for test reasons + * @param feedback + */ + void setFeedback(Feedback feedback); +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/controller/AnnotationController.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/controller/AnnotationController.java index 27abdc4bcc7f9abed957e39b46369e80ed5f3ba9..ce29362c3f10354b41d3802bd945d638e62b52c9 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/controller/AnnotationController.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/controller/AnnotationController.java @@ -4,6 +4,7 @@ import unipotsdam.gf.core.database.mysql.MysqlConnect; import unipotsdam.gf.core.database.mysql.VereinfachtesResultSet; import unipotsdam.gf.interfaces.IAnnotation; import unipotsdam.gf.modules.annotation.model.Annotation; +import unipotsdam.gf.modules.annotation.model.AnnotationBody; import unipotsdam.gf.modules.annotation.model.AnnotationPatchRequest; import unipotsdam.gf.modules.annotation.model.AnnotationPostRequest; @@ -26,8 +27,8 @@ public class AnnotationController implements IAnnotation { connection.connect(); // build and execute request - String request = "INSERT INTO annotations (`id`, `userId`, `targetId`, `body`, `startCharacter`, `endCharacter`) VALUES (?,?,?,?,?,?);"; - connection.issueInsertOrDeleteStatement(request, uuid, annotationPostRequest.getUserId(), annotationPostRequest.getTargetId(), annotationPostRequest.getBody(), annotationPostRequest.getStartCharacter(), annotationPostRequest.getEndCharacter()); + String request = "INSERT INTO annotations (`id`, `userToken`, `targetId`, `title`, `comment`, `startCharacter`, `endCharacter`) VALUES (?,?,?,?,?,?,?);"; + connection.issueInsertOrDeleteStatement(request, uuid, annotationPostRequest.getUserToken(), annotationPostRequest.getTargetId(), annotationPostRequest.getBody().getTitle(), annotationPostRequest.getBody().getComment(),annotationPostRequest.getBody().getStartCharacter(), annotationPostRequest.getBody().getEndCharacter()); // close connection connection.close(); @@ -47,8 +48,8 @@ public class AnnotationController implements IAnnotation { connection.connect(); // build and execute request - String request = "UPDATE `annotations` SET `body` = ? WHERE `id` = ?"; - connection.issueUpdateStatement(request, annotationPatchRequest.getBody(), annotationId); + String request = "UPDATE `annotations` SET `title` = ?, `comment` = ? WHERE `id` = ?"; + connection.issueUpdateStatement(request, annotationPatchRequest.getTitle(), annotationPatchRequest.getComment(), annotationId); // close connection connection.close(); @@ -159,17 +160,27 @@ public class AnnotationController implements IAnnotation { } + /** + * Build an annotation object from a given result set + * + * @param rs The result set from a database query + * @return A new annotation object + */ private Annotation getAnnotationFromResultSet(VereinfachtesResultSet rs) { String id = rs.getString("id"); long timestamp = rs.getTimestamp(2).getTime(); - int userId = rs.getInt("userId"); + String userToken = rs.getString("userToken"); int targetId = rs.getInt("targetId"); - String body = rs.getString("body"); + + // initialize new annotation body + String title = rs.getString("title"); + String comment = rs.getString("comment"); int startCharacter = rs.getInt("startCharacter"); int endCharacter = rs.getInt("endCharacter"); + AnnotationBody body = new AnnotationBody(title, comment, startCharacter, endCharacter); - return new Annotation(id, timestamp, userId, targetId, body, startCharacter, endCharacter); + return new Annotation(id, timestamp, userToken, targetId, body); } } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/Annotation.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/Annotation.java index 725967353f5685e93c53302b7a8a0e799e4ccc12..699ec3eda8ad469fda08b6688311fabb9a17bc5b 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/Annotation.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/Annotation.java @@ -9,21 +9,17 @@ public class Annotation { // variables private String id; private long timestamp; - private int userId; + private String userToken; private int targetId; - private String body; - private int startCharacter; - private int endCharacter; + private AnnotationBody body; // constructor - public Annotation(String id, long timestamp, int userId, int targetId, String body, int startCharacter, int endCharacter) { + public Annotation(String id, long timestamp, String userToken, int targetId, AnnotationBody body) { this.id = id; this.timestamp = timestamp; - this.userId = userId; + this.userToken = userToken; this.targetId = targetId; this.body = body; - this.startCharacter = startCharacter; - this.endCharacter = endCharacter; } // methods @@ -43,12 +39,12 @@ public class Annotation { this.timestamp = timestamp; } - public int getUserId() { - return userId; + public String getUserToken() { + return userToken; } - public void setUserId(int userId) { - this.userId = userId; + public void setUserToken(String userToken) { + this.userToken = userToken; } public int getTargetId() { @@ -59,40 +55,22 @@ public class Annotation { this.targetId = targetId; } - public String getBody() { + public AnnotationBody getBody() { return body; } - public void setBody(String body) { + public void setBody(AnnotationBody body) { this.body = body; } - public int getStartCharacter() { - return startCharacter; - } - - public void setStartCharacter(int startCharacter) { - this.startCharacter = startCharacter; - } - - public int getEndCharacter() { - return endCharacter; - } - - public void setEndCharacter(int endCharacter) { - this.endCharacter = endCharacter; - } - @Override public String toString() { return "Annotation{" + - "id=" + id + + "id='" + id + '\'' + ", timestamp=" + timestamp + - ", userId=" + userId + + ", userToken='" + userToken + '\'' + ", targetId=" + targetId + - ", body='" + body + '\'' + - ", startCharacter=" + startCharacter + - ", endCharacter=" + endCharacter + + ", body=" + body + '}'; } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationBody.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationBody.java new file mode 100644 index 0000000000000000000000000000000000000000..53c65233d06da04c8792c2f15ee4c39ddebd498b --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationBody.java @@ -0,0 +1,69 @@ +package unipotsdam.gf.modules.annotation.model; + +/** + * @author Sven Kästle + * skaestle@uni-potsdam.de + */ +public class AnnotationBody { + + // variables + private String title; + private String comment; + private int startCharacter; + private int endCharacter; + + // constructors + public AnnotationBody(String title, String comment, int startCharacter, int endCharacter) { + this.title = title; + this.comment = comment; + this.startCharacter = startCharacter; + this.endCharacter = endCharacter; + } + + public AnnotationBody() { + } + + // methods + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public int getStartCharacter() { + return startCharacter; + } + + public void setStartCharacter(int startCharacter) { + this.startCharacter = startCharacter; + } + + public int getEndCharacter() { + return endCharacter; + } + + public void setEndCharacter(int endCharacter) { + this.endCharacter = endCharacter; + } + + @Override + public String toString() { + return "AnnotationBody{" + + "title='" + title + '\'' + + ", comment='" + comment + '\'' + + ", startCharacter=" + startCharacter + + ", endCharacter=" + endCharacter + + '}'; + } + +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationMessage.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..60d895b66b293668f4b505684a46d75ebea88dbe --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationMessage.java @@ -0,0 +1,58 @@ +package unipotsdam.gf.modules.annotation.model; + +public class AnnotationMessage { + // variables + private String from; + private String targetId; + private AnnotationMessageType type; + private String annotationId; + + public enum AnnotationMessageType { + CREATE, + DELETE, + EDIT + } + + // methods + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getTargetId() { + return targetId; + } + + public void setTargetId(String targetId) { + this.targetId = targetId; + } + + public AnnotationMessageType getType() { + return type; + } + + public void setType(AnnotationMessageType type) { + this.type = type; + } + + public String getAnnotationId() { + return annotationId; + } + + public void setAnnotationId(String annotationId) { + this.annotationId = annotationId; + } + + @Override + public String toString() { + return "AnnotationMessage{" + + "from='" + from + '\'' + + ", targetId='" + targetId + '\'' + + ", type=" + type + + ", annotationId='" + annotationId + '\'' + + '}'; + } +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationPatchRequest.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationPatchRequest.java index c41e294afda5094833771b48bef3c18656c1f283..af5be4da6ad8db3f77ff0bf644392042a3626e5b 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationPatchRequest.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationPatchRequest.java @@ -7,28 +7,39 @@ package unipotsdam.gf.modules.annotation.model; public class AnnotationPatchRequest { // variables - private String body; + private String title; + private String comment; // constructors - public AnnotationPatchRequest(String body) { - this.body = body; + public AnnotationPatchRequest(String title, String comment) { + this.title = title; + this.comment = comment; } public AnnotationPatchRequest() {} // methods - public String getBody() { - return body; + public String getTitle() { + return title; } - public void setBody(String body) { - this.body = body; + public void setTitle(String title) { + this.title = title; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; } @Override public String toString() { return "AnnotationPatchRequest{" + - "body='" + body + '\'' + + "title='" + title + '\'' + + ", comment='" + comment + '\'' + '}'; } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationPostRequest.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationPostRequest.java index 5459cb5b567c1aa2224642c2ef304007b954ba7e..5dfe6e206f1f014eb3ce88fbc22e401323b2c422 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationPostRequest.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationPostRequest.java @@ -7,31 +7,27 @@ package unipotsdam.gf.modules.annotation.model; public class AnnotationPostRequest { // variables - private int userId; + private String userToken; private int targetId; - private String body; - private int startCharacter; - private int endCharacter; + private AnnotationBody body; // constructors - public AnnotationPostRequest(int userId, int targetId, String body, int startCharacter, int endCharacter) { - this.userId = userId; + public AnnotationPostRequest(String userToken, int targetId, AnnotationBody body) { + this.userToken = userToken; this.targetId = targetId; this.body = body; - this.startCharacter = startCharacter; - this.endCharacter = endCharacter; } public AnnotationPostRequest() { } // methods - public int getUserId() { - return userId; + public String getUserToken() { + return userToken; } - public void setUserId(int userId) { - this.userId = userId; + public void setUserToken(String userToken) { + this.userToken = userToken; } public int getTargetId() { @@ -42,38 +38,21 @@ public class AnnotationPostRequest { this.targetId = targetId; } - public String getBody() { + public AnnotationBody getBody() { return body; } - public void setBody(String body) { + public void setBody(AnnotationBody body) { this.body = body; } - public int getStartCharacter() { - return startCharacter; - } - - public void setStartCharacter(int startCharacter) { - this.startCharacter = startCharacter; - } - - public int getEndCharacter() { - return endCharacter; - } - - public void setEndCharacter(int endCharacter) { - this.endCharacter = endCharacter; - } - @Override public String toString() { return "AnnotationPostRequest{" + - "userId=" + userId + + "userToken='" + userToken + '\'' + ", targetId=" + targetId + - ", body='" + body + '\'' + - ", startCharacter=" + startCharacter + - ", endCharacter=" + endCharacter + + ", body=" + body.toString() + '}'; } + } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationMessageDecoder.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationMessageDecoder.java new file mode 100644 index 0000000000000000000000000000000000000000..e4b2d83285499611edd4012ec85c8162effa22f5 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationMessageDecoder.java @@ -0,0 +1,34 @@ +package unipotsdam.gf.modules.annotation.websocket; + +import com.google.gson.Gson; +import unipotsdam.gf.modules.annotation.model.AnnotationMessage; + +import javax.websocket.DecodeException; +import javax.websocket.Decoder; +import javax.websocket.EndpointConfig; + +public class AnnotationMessageDecoder implements Decoder.Text<AnnotationMessage> { + + public static Gson gson = new Gson(); + + @Override + public AnnotationMessage decode(String s) throws DecodeException { + AnnotationMessage annotationMessage = gson.fromJson(s, AnnotationMessage.class); + return annotationMessage; + } + + @Override + public boolean willDecode(String s) { + return (null != s); + } + + @Override + public void init(EndpointConfig endpointConfig) { + // todo + } + + @Override + public void destroy() { + // todo + } +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationMessageEncoder.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationMessageEncoder.java new file mode 100644 index 0000000000000000000000000000000000000000..161055827abf16881c241bdfe30bb59b466848b0 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationMessageEncoder.java @@ -0,0 +1,29 @@ +package unipotsdam.gf.modules.annotation.websocket; + +import com.google.gson.Gson; +import unipotsdam.gf.modules.annotation.model.AnnotationMessage; + +import javax.websocket.EncodeException; +import javax.websocket.Encoder; +import javax.websocket.EndpointConfig; + +public class AnnotationMessageEncoder implements Encoder.Text<AnnotationMessage> { + + private static Gson gson = new Gson(); + + @Override + public String encode(AnnotationMessage annotationMessage) throws EncodeException { + String json = gson.toJson(annotationMessage); + return json; + } + + @Override + public void init(EndpointConfig endpointConfig) { + // todo + } + + @Override + public void destroy() { + // todo + } +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationWebSocketEndpoint.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationWebSocketEndpoint.java new file mode 100644 index 0000000000000000000000000000000000000000..29c2d3f61ebc6da8e99be59dfdff206c8e1810b0 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationWebSocketEndpoint.java @@ -0,0 +1,65 @@ +package unipotsdam.gf.modules.annotation.websocket; + +import unipotsdam.gf.modules.annotation.model.AnnotationMessage; + +import javax.websocket.*; +import javax.websocket.server.PathParam; +import javax.websocket.server.ServerEndpoint; +import java.io.IOException; +import java.util.HashMap; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +@ServerEndpoint(value = "/ws/annotation/{targetId}", decoders = AnnotationMessageDecoder.class, encoders = AnnotationMessageEncoder.class) +public class AnnotationWebSocketEndpoint { + + private Session session; + private static final Set<AnnotationWebSocketEndpoint> endpoints = new CopyOnWriteArraySet<>(); + private static HashMap<String, String> targets = new HashMap<>(); + + @OnOpen + public void onOpen(Session session, @PathParam("targetId") String targetId) throws IOException { + // initialize session + this.session = session; + // save endpoint in set of endpoints + endpoints.add(this); + // save mapping of session and target id + targets.put(session.getId(), targetId); + } + + @OnMessage + public void onMessage(Session session, AnnotationMessage annotationMessage) throws IOException, EncodeException { + annotationMessage.setTargetId(targets.get(session.getId())); + annotationMessage.setFrom(session.getId()); + broadcast(annotationMessage); + + } + + @OnClose + public void onClose(Session session) throws IOException { + endpoints.remove(this); + } + + @OnError + public void onError(Session session, Throwable throwable) { + // todo + } + + private void broadcast(AnnotationMessage annotationMessage) throws IOException, EncodeException { + endpoints.forEach(endpoint -> { + synchronized (endpoint) { + try { + if (targets.get(endpoint.session.getId()).equals(annotationMessage.getTargetId()) + && !endpoint.session.getId().equals(annotationMessage.getFrom())) { + System.out.println("Send message to session" + endpoint.session.getId() + " from session " + annotationMessage.getFrom()); + endpoint.session.getBasicRemote().sendObject(annotationMessage); + } + } + catch (IOException | EncodeException e) { + e.printStackTrace(); + } + } + }); + } + +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/AssessmentMechanism.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/AssessmentMechanism.java new file mode 100644 index 0000000000000000000000000000000000000000..b3692469832c184c21d3f983fb6cd87202c96e05 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/AssessmentMechanism.java @@ -0,0 +1,7 @@ +package unipotsdam.gf.modules.assessment; + +public enum AssessmentMechanism { + AXEL_MECHANISM, + CHRISTIAN_MECHANISM, + COMBINATIONXY +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/QuizAnswer.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/QuizAnswer.java new file mode 100644 index 0000000000000000000000000000000000000000..6e94987dbaaa741b8c7da6a15a3c3148743a08f8 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/QuizAnswer.java @@ -0,0 +1,4 @@ +package unipotsdam.gf.modules.assessment; + +public class QuizAnswer { +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/model/StudentAndQuiz.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/model/StudentAndQuiz.java index 4f5f5c0976bffc1bc51602c7c1cc886f294ac1d5..ce8d9bfdff59fbe2edfcf6ec56137cecf1bb1ca1 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/model/StudentAndQuiz.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/model/StudentAndQuiz.java @@ -1,5 +1,9 @@ package unipotsdam.gf.modules.assessment.controller.model; + +/** + * TODO @Axel: Normally a quiz would have a student field property instead of creating a new class + */ public class StudentAndQuiz { @Override public String toString() { diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/service/FBAssessement.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/service/FBAssessement.java index df592667c5c569eaaa9f60dd7f6d75f30bc34789..a00736d6be46da151e31deb2323b3c4c3115eba6 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/service/FBAssessement.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/service/FBAssessement.java @@ -1,5 +1,6 @@ package unipotsdam.gf.modules.assessment.controller.service; +import unipotsdam.gf.modules.assessment.QuizAnswer; import unipotsdam.gf.modules.assessment.controller.model.*; import java.util.ArrayList; @@ -57,4 +58,9 @@ public class FBAssessement extends AssessmentDAO { public void postPeerRating(ArrayList<PeerRating> peerRatings, String projectId, String groupId) { } + + @Override + public void answerQuiz(StudentAndQuiz studentAndQuiz, QuizAnswer quizAnswer) { + + } } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/service/PeerAssessment.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/service/PeerAssessment.java index 9ab276c63b7e61ed7d1fbd121717f3ab1b8f8232..a4ff7b02053678a112a681d5e6cba1866fe0109a 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/service/PeerAssessment.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/service/PeerAssessment.java @@ -1,10 +1,9 @@ package unipotsdam.gf.modules.assessment.controller.service; import unipotsdam.gf.core.management.ManagementImpl; -import unipotsdam.gf.core.management.user.User; import unipotsdam.gf.interfaces.IPeerAssessment; +import unipotsdam.gf.modules.assessment.QuizAnswer; import unipotsdam.gf.modules.assessment.controller.model.*; -import unipotsdam.gf.core.database.mysql.MysqlConnect; import java.util.ArrayList; import java.util.List; @@ -56,4 +55,9 @@ public class PeerAssessment implements IPeerAssessment { public void postPeerRating(ArrayList<PeerRating> peerRatings, String projectId, String groupId) { } + + @Override + public void answerQuiz(StudentAndQuiz studentAndQuiz, QuizAnswer quizAnswer) { + + } } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/service/PeerAssessmentDummy.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/service/PeerAssessmentDummy.java index 35920c8470ac2a075579c14183cbd7fa89818e52..fced4060a23c7b245db8a4c8918913077a8d6b07 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/service/PeerAssessmentDummy.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/service/PeerAssessmentDummy.java @@ -1,6 +1,9 @@ package unipotsdam.gf.modules.assessment.controller.service; +import unipotsdam.gf.assignments.Assignee; +import unipotsdam.gf.assignments.NotImplementedLogger; import unipotsdam.gf.interfaces.IPeerAssessment; +import unipotsdam.gf.modules.assessment.QuizAnswer; import unipotsdam.gf.modules.assessment.controller.model.*; import java.util.ArrayList; @@ -64,6 +67,11 @@ public class PeerAssessmentDummy implements IPeerAssessment { int breakpoint = 0; //todo: print an http-answer for the ajax-request to receive } + @Override + public void answerQuiz(StudentAndQuiz studentAndQuiz, QuizAnswer quizAnswer) { + NotImplementedLogger.logAssignment(Assignee.AXEL, IPeerAssessment.class); + } + @Override public Assessment getAssessmentDataFromDB(StudentIdentifier student) { int[] quizAnswer = {1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1}; @@ -75,6 +83,7 @@ public class PeerAssessmentDummy implements IPeerAssessment { @Override public void createQuiz(StudentAndQuiz studentAndQuiz) { + NotImplementedLogger.logAssignment(Assignee.AXEL, PeerAssessmentDummy.class); } @Override diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/view/QuizView.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/view/QuizView.java index 4ee52595c40fdc7cc9163884de28199e63f1456e..e0b8b99371a91ecad1853d22b855f81b7b9ddd4e 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/view/QuizView.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/assessment/controller/view/QuizView.java @@ -1,8 +1,8 @@ package unipotsdam.gf.modules.assessment.controller.view; import unipotsdam.gf.interfaces.IPeerAssessment; +import unipotsdam.gf.modules.assessment.QuizAnswer; import unipotsdam.gf.modules.assessment.controller.model.*; -import unipotsdam.gf.modules.assessment.controller.service.PeerAssessment; import unipotsdam.gf.modules.assessment.controller.service.PeerAssessmentDummy; import javax.ws.rs.*; @@ -39,6 +39,11 @@ public class QuizView implements IPeerAssessment { //todo: checkout the POST-variable. should be peerRating but its null atm. } + @Override + public void answerQuiz(StudentAndQuiz studentAndQuiz, QuizAnswer quizAnswer) { + + } + @POST @Produces(MediaType.TEXT_PLAIN) @Consumes(MediaType.APPLICATION_JSON) diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/communication/service/CommunicationDummyService.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/communication/service/CommunicationDummyService.java index 3d989429228f1c213263794b0df7c741f87507cb..1aa5c32fee0d669a6956d7822e9b084f294c264f 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/communication/service/CommunicationDummyService.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/communication/service/CommunicationDummyService.java @@ -2,7 +2,10 @@ package unipotsdam.gf.modules.communication.service; import unipotsdam.gf.config.Constants; import unipotsdam.gf.core.management.Management; +import unipotsdam.gf.core.management.project.Project; import unipotsdam.gf.core.management.user.User; +import unipotsdam.gf.assignments.Assignee; +import unipotsdam.gf.assignments.NotImplementedLogger; import unipotsdam.gf.interfaces.ICommunication; import unipotsdam.gf.modules.communication.model.Message; import unipotsdam.gf.modules.communication.model.chat.ChatMessage; @@ -38,7 +41,8 @@ public class CommunicationDummyService implements ICommunication { @Override public boolean sendMessageToChat(Message message, String roomId) { - return true; + NotImplementedLogger.logAssignment(Assignee.MARTIN, CommunicationDummyService.class); + return false; } @Override @@ -51,18 +55,22 @@ public class CommunicationDummyService implements ICommunication { } @Override - public boolean addUserToChatRoom(String roomId, User user) { - return true; + public boolean addUserToChatRoom(String roomId, User user) { + NotImplementedLogger.logAssignment(Assignee.MARTIN, CommunicationDummyService.class, "addUserToChatRoom"); + return false; } @Override - public boolean removeUserFromChatRoom(User user, String roomId) { - return true; + public boolean removeUserFromChatRoom(User user, String roomId) { + NotImplementedLogger.logAssignment(Assignee.MARTIN, CommunicationDummyService.class, "removing user from chat " + + "room"); + return false; } @Override public boolean setChatRoomTopic(String roomId, String topic) { - return true; + NotImplementedLogger.logAssignment(Assignee.MARTIN, CommunicationDummyService.class, "setting chat room topic"); + return false; } @Override @@ -100,6 +108,20 @@ public class CommunicationDummyService implements ICommunication { return Constants.ROCKET_CHAT_URL + "/channel/" + channelName + "?layout=embedded"; } + @Override + public void sendSingleMessage(Message message, User user) { + // TODO implement as email or directed message, popup after login or whatever + String message2 = "sending email with message: "+ message.getMessage() + " to: "+ user.getEmail(); + NotImplementedLogger.logAssignment(Assignee.MARTIN, CommunicationDummyService.class, message2); + } + + @Override + public void sendMessageToUsers(Project project, String message) { + // TODO implement as email or directed message, popup after login or whatever + String message2 = "sending email with message: "+ message + " to: "+ project.getId(); + NotImplementedLogger.logAssignment(Assignee.MARTIN, CommunicationDummyService.class, message2); + } + // TODO: remove after done implementing // just for postman testing public User getUser() { diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/DummyGroupfinding.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/DummyGroupfinding.java new file mode 100644 index 0000000000000000000000000000000000000000..c7f3f4577a605f80f6f2a3109445834140d28ce1 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/DummyGroupfinding.java @@ -0,0 +1,34 @@ +package unipotsdam.gf.modules.groupfinding; + +import unipotsdam.gf.core.management.group.Group; +import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.assignments.Assignee; +import unipotsdam.gf.assignments.NotImplementedLogger; +import unipotsdam.gf.interfaces.IGroupFinding; + +import java.util.ArrayList; +import java.util.List; + +public class DummyGroupfinding implements IGroupFinding { + @Override + public void selectGroupfindingCriteria(GroupfindingCriteria groupfindingCriteria) { + NotImplementedLogger.logAssignment(Assignee.MIRJAM, IGroupFinding.class); + } + + @Override + public void persistGroups( + List<Group> groupComposition, Project project){ + NotImplementedLogger.logAssignment(Assignee.MIRJAM, IGroupFinding.class); + } + + @Override + public List<Group> getGroups(Project project) { + NotImplementedLogger.logAssignment(Assignee.MIRJAM, IGroupFinding.class); + return new ArrayList<>(); + } + + @Override + public void formGroups(GroupFormationMechanism groupFindingMechanism) { + NotImplementedLogger.logAssignment(Assignee.MIRJAM, IGroupFinding.class); + } +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/GroupFormationMechanism.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/GroupFormationMechanism.java new file mode 100644 index 0000000000000000000000000000000000000000..b8addf85f4f9789f9e9d52c705c0308cecbd372f --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/GroupFormationMechanism.java @@ -0,0 +1,7 @@ +package unipotsdam.gf.modules.groupfinding; + +public enum GroupFormationMechanism { + Manual, + LearningGoalStrategy, + UserProfilStrategy +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/GroupfindingCriteria.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/GroupfindingCriteria.java new file mode 100644 index 0000000000000000000000000000000000000000..39c33ca8191322925f08aae951bbc83d3532f485 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/GroupfindingCriteria.java @@ -0,0 +1,10 @@ +package unipotsdam.gf.modules.groupfinding; + +/** + * TODO: implementieren + * - Self efficacy scale + * - Uncertainty tolerance scale + * - Other sources + */ +public class GroupfindingCriteria { +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/GroupfindingImpl.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/GroupfindingImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..8987f63c3863e21673bbf067fccced65dbff08ed --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/GroupfindingImpl.java @@ -0,0 +1,30 @@ +package unipotsdam.gf.modules.groupfinding; + +import unipotsdam.gf.core.management.group.Group; +import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.interfaces.IGroupFinding; + +import java.util.List; + +public class GroupfindingImpl implements IGroupFinding { + @Override + public void selectGroupfindingCriteria(GroupfindingCriteria groupfindingCriteria) { + + } + + @Override + public void persistGroups( + List<Group> groupComposition, Project project) { + + } + + @Override + public List<Group> getGroups(Project project) { + return null; + } + + @Override + public void formGroups(GroupFormationMechanism groupFindingMechanism) { + + } +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupCreation/service/GroupCreationService.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/service/GroupCreationService.java similarity index 98% rename from gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupCreation/service/GroupCreationService.java rename to gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/service/GroupCreationService.java index 23127b12dc29e93f9d76e299c81619229fab16e4..5238e9530cee936020be2d577c172fffaba79e7c 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupCreation/service/GroupCreationService.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/groupfinding/service/GroupCreationService.java @@ -1,4 +1,4 @@ -package unipotsdam.gf.modules.groupCreation.service; +package unipotsdam.gf.modules.groupfinding.service; import unipotsdam.gf.core.management.Management; import unipotsdam.gf.core.management.group.Group; diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/journal/DummyJournalImpl.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/journal/DummyJournalImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..6ea1ea3526226d625dc486eb4d9ca57841c2a519 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/journal/DummyJournalImpl.java @@ -0,0 +1,58 @@ +package unipotsdam.gf.modules.journal; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.core.management.user.User; +import unipotsdam.gf.assignments.Assignee; +import unipotsdam.gf.assignments.NotImplementedLogger; +import unipotsdam.gf.interfaces.IJournal; +import unipotsdam.gf.modules.assessment.controller.model.StudentIdentifier; +import unipotsdam.gf.modules.journal.model.Journal; +import unipotsdam.gf.modules.researchreport.ResearchReport; + +import javax.swing.text.html.HTML; +import java.io.File; +import java.util.List; + +public class DummyJournalImpl implements IJournal { + + + private Logger log = LoggerFactory.getLogger(DummyJournalImpl.class); + + @Override + public String exportJournal(StudentIdentifier student) { + NotImplementedLogger.logAssignment(Assignee.THOMAS, IJournal.class); + return null; + } + + @Override + public Boolean getPortfoliosForEvaluationPrepared(Project project) { + NotImplementedLogger.logAssignment(Assignee.THOMAS, IJournal.class); + return false; + } + + @Override + public void assignMissingPortfolioTasks(Project project) { + NotImplementedLogger.logAssignment(Assignee.THOMAS, IJournal.class); + } + + @Override + public void uploadJournalEntry(Journal journalEntry, User student) { + NotImplementedLogger.logAssignment(Assignee.THOMAS, IJournal.class); + } + + @Override + public void uploadFinalPortfolio( + Project project, List<Journal> journalEntries, ResearchReport finalResearchReport, File presentation, + User user) { + NotImplementedLogger.logAssignment(Assignee.THOMAS, IJournal.class); + } + + @Override + public HTML getFinalPortfolioForAssessment( + Project project, User user) { + NotImplementedLogger.logAssignment(Assignee.THOMAS, IJournal.class); + return null; + } +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/journal/model/ProjectDescription.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/journal/model/ProjectDescription.java index cfcb4f5a66175c2c1efb54af75a5eb9a8bcabbac..85a6e1f08c709000ca95888bcc53faab4bd8f3f1 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/journal/model/ProjectDescription.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/journal/model/ProjectDescription.java @@ -6,7 +6,7 @@ import unipotsdam.gf.modules.assessment.controller.model.StudentIdentifier; import java.util.ArrayList; import java.util.Map; -import static unipotsdam.gf.core.management.utils.MarkdownUtils.convertMarkdownToHtml; +import static unipotsdam.gf.view.MarkdownUtils.convertMarkdownToHtml; /** * Model class for the project descriptionHTML of the e portfolio diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/utils/Category.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/peer2peerfeedback/Category.java similarity index 82% rename from gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/utils/Category.java rename to gemeinsamforschen/src/main/java/unipotsdam/gf/modules/peer2peerfeedback/Category.java index 0929f342834ff143da72c6ebfa74ee911138338e..d371d33983460d0893f9136329b8aea4f36f0379 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/utils/Category.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/peer2peerfeedback/Category.java @@ -1,4 +1,4 @@ -package unipotsdam.gf.core.management.utils; +package unipotsdam.gf.modules.peer2peerfeedback; /** Categories for feedback and documents diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/peer2peerfeedback/DummyFeedback.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/peer2peerfeedback/DummyFeedback.java new file mode 100644 index 0000000000000000000000000000000000000000..b8098bebafa5b556b4403ef1ac256b7ac1450d2b --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/peer2peerfeedback/DummyFeedback.java @@ -0,0 +1,75 @@ +package unipotsdam.gf.modules.peer2peerfeedback; + +import org.mockito.Mockito; +import uk.co.jemos.podam.api.PodamFactory; +import uk.co.jemos.podam.api.PodamFactoryImpl; +import unipotsdam.gf.assignments.Assignee; +import unipotsdam.gf.assignments.NotImplementedLogger; +import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.core.management.user.User; +import unipotsdam.gf.interfaces.Feedback; +import unipotsdam.gf.modules.researchreport.ResearchReport; + +import java.io.File; +import java.util.ArrayList; + +public class DummyFeedback implements Feedback { + + /** + * Utility to creaty dummy data for students + */ + PodamFactory factory = new PodamFactoryImpl(); + + private static Boolean missingTaskAssigned = false; + + + public DummyFeedback() { + + } + + @Override + public Peer2PeerFeedback createPeer2PeerFeedbackmask( + User feedbackuser, User selectedstudent, File document) { + return null; + } + + @Override + public Boolean giveFeedback(Peer2PeerFeedback feedback, ResearchReport document) { + return null; + } + + @Override + public ArrayList<Peer2PeerFeedback> showFeedback(User student) { + return null; + } + + @Override + public int countFeedback(User student) { + return 0; + } + + @Override + public Boolean checkFeedbackConstraints(Project project) { + // TODO implement cornstaints + NotImplementedLogger.logAssignment(Assignee.KATHARINA, Feedback.class, "check Feedback constraints", + "checking feedback constraints "); + return missingTaskAssigned; + } + + @Override + public void assigningMissingFeedbackTasks(Project project) { + NotImplementedLogger.logAssignment(Assignee.KATHARINA, Feedback.class, "assigningMissingFeedbackTasks", + "assigning feedback tasks "); + missingTaskAssigned = true; + } + + @Override + public void assignFeedbackTasks() { + + } + + @Override + public ResearchReport getFeedbackTask(User student) { + return factory.manufacturePojo(ResearchReport.class); + } +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/peer2peerfeedback/ExampleFeedback.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/peer2peerfeedback/ExampleFeedback.java index bc040fad7ccfad8993d3a1f33ca2eebfbefb48a3..9b44f2d2e81a8ca1133da2917cfb47ba69bfdb7d 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/peer2peerfeedback/ExampleFeedback.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/peer2peerfeedback/ExampleFeedback.java @@ -1,7 +1,6 @@ package unipotsdam.gf.modules.peer2peerfeedback; import unipotsdam.gf.core.management.user.User; -import unipotsdam.gf.core.management.utils.Category; import java.io.File; diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/peer2peerfeedback/Peer2PeerFeedback.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/peer2peerfeedback/Peer2PeerFeedback.java index d68e106fb4c8d007e1d5b1a5a8c5e7eef4289487..55bd0e9dad14bc9e1954f223599ebdb4587f0dd6 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/peer2peerfeedback/Peer2PeerFeedback.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/peer2peerfeedback/Peer2PeerFeedback.java @@ -1,7 +1,6 @@ package unipotsdam.gf.modules.peer2peerfeedback; import unipotsdam.gf.core.management.user.User; -import unipotsdam.gf.core.management.utils.Category; import java.io.File; diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/researchreport/DummyResearchReportCounter.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/researchreport/DummyResearchReportCounter.java new file mode 100644 index 0000000000000000000000000000000000000000..b1451156914c3db9a513df29f93da077bf6e4776 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/researchreport/DummyResearchReportCounter.java @@ -0,0 +1,6 @@ +package unipotsdam.gf.modules.researchreport; + +public class DummyResearchReportCounter { + + public static Boolean feedbackTasksNotAssigned = true; +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/researchreport/DummyResearchReportManagement.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/researchreport/DummyResearchReportManagement.java new file mode 100644 index 0000000000000000000000000000000000000000..b383fe36766219dde8c5ebcbef5a5395124d513f --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/researchreport/DummyResearchReportManagement.java @@ -0,0 +1,69 @@ +package unipotsdam.gf.modules.researchreport; + +import uk.co.jemos.podam.api.PodamFactory; +import uk.co.jemos.podam.api.PodamFactoryImpl; +import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.core.management.user.User; +import unipotsdam.gf.assignments.Assignee; +import unipotsdam.gf.assignments.NotImplementedLogger; +import unipotsdam.gf.interfaces.Feedback; + +import javax.inject.Inject; +import java.io.File; + +public class DummyResearchReportManagement implements ResearchReportManagement { + + + + /** + * Utility to creaty dummy data for students + */ + PodamFactory factory = new PodamFactoryImpl(); + + + @Inject + Feedback feedback; + + @Override + public String createResearchReport( + ResearchReport researchReport, Project project, User student) { + + // real implementation should check if all the constraints are ok before starting with feedbacks + // this assumes uploading and giving feedback is in the same phase (no teacher decision to go from + // uploading dossiers to feedback + if (DummyResearchReportCounter.feedbackTasksNotAssigned) { + DummyResearchReportCounter.feedbackTasksNotAssigned = false; + feedback.assignFeedbackTasks(); + } + return factory.manufacturePojo(ResearchReport.class).getId(); + } + + @Override + public boolean updateResearchReport(ResearchReport researchReport) { + NotImplementedLogger.logAssignment(Assignee.QUARK, ResearchReportManagement.class, null, "updateResearchReport"); + return false; + } + + @Override + public boolean deleteReport(ResearchReport researchReport) { + NotImplementedLogger.logAssignment(Assignee.QUARK, ResearchReportManagement.class); + return false; + } + + @Override + public File getResearchReport(ResearchReport researchReport) { + NotImplementedLogger.logAssignment(Assignee.QUARK, ResearchReportManagement.class); + return null; + } + + @Override + public void createFinalResearchReport( + ResearchReport researchReport, Project project, User student) { + NotImplementedLogger.logAssignment(Assignee.QUARK, ResearchReportManagement.class); + } + + @Override + public void setFeedback(Feedback feedback) { + this.feedback = feedback; + } +} diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/researchreport/ResearchReport.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/researchreport/ResearchReport.java index c90d34735321bcdeb5b81ecc16acf509529d9625..31f5d35640bc5c80f7084ace747202fa30c9bdd2 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/researchreport/ResearchReport.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/researchreport/ResearchReport.java @@ -6,6 +6,7 @@ public class ResearchReport { // TODO add properties private String title; private ResearchQuestion researchQuestion; + private String id; private List<String> learningGoals; private String method; private String research; @@ -107,4 +108,12 @@ public class ResearchReport { public void setTimeplan(Timeplanning timeplan) { this.timeplan = timeplan; } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/researchreport/ResearchReportManagement.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/researchreport/ResearchReportManagement.java index 5355ab90768c8eadfc0800c2553dd70a483f5324..c2226c52f436fae65caaa6962cb3b9faaf45b69a 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/researchreport/ResearchReportManagement.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/researchreport/ResearchReportManagement.java @@ -1,6 +1,9 @@ package unipotsdam.gf.modules.researchreport; -import unipotsdam.gf.modules.researchreport.ResearchReport; +import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.core.management.user.User; +import unipotsdam.gf.assignments.NotImplementedLogger; +import unipotsdam.gf.interfaces.Feedback; import java.io.File; @@ -15,9 +18,12 @@ public interface ResearchReportManagement { * Create a File * * @param researchReport Name of the Report + * @param project + * @param student * @return Returns the reportId */ - String createResearchReport(ResearchReport researchReport); + String createResearchReport( + ResearchReport researchReport, Project project, User student); /** @@ -26,14 +32,14 @@ public interface ResearchReportManagement { * @param researchReport Name of the Report * @return Returns if the report is updated */ - boolean updateResearchReport(ResearchReport researchReport); + boolean updateResearchReport(ResearchReport researchReport) ; /** * Delete a File * * @param researchReport Name of the Report */ - boolean deleteReport(ResearchReport researchReport); + boolean deleteReport(ResearchReport researchReport) ; /** @@ -41,8 +47,23 @@ public interface ResearchReportManagement { * @param researchReport Name of the Report * @return Returns the Report */ - File getResearchReport(ResearchReport researchReport); + File getResearchReport(ResearchReport researchReport) ; + /** + * This represents a second version of the research report where the feedback is incorporated + * There is only this second version. Otherwise we could cycle the dossier upload and feedback (would be to + * complicated) + * @param researchReport + * @param project + * @param student + */ + void createFinalResearchReport(ResearchReport researchReport, Project project, User student) + ; + /** + * the dependency to feedback should be settable externally for test reasons + * @param feedback + */ + void setFeedback(Feedback feedback); } diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/utils/MarkdownUtils.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/view/MarkdownUtils.java similarity index 93% rename from gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/utils/MarkdownUtils.java rename to gemeinsamforschen/src/main/java/unipotsdam/gf/view/MarkdownUtils.java index 5d25997fb52658f8d3f209c289677286659ccb59..9f626e2ccbeb9b48b003a00e4ea7dd62b04345a1 100644 --- a/gemeinsamforschen/src/main/java/unipotsdam/gf/core/management/utils/MarkdownUtils.java +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/view/MarkdownUtils.java @@ -1,4 +1,4 @@ -package unipotsdam.gf.core.management.utils; +package unipotsdam.gf.view; import org.commonmark.node.Node; import org.commonmark.parser.Parser; diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/view/Messages.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/view/Messages.java new file mode 100644 index 0000000000000000000000000000000000000000..986c7d741e87d479673663e4afccd5d685bc2249 --- /dev/null +++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/view/Messages.java @@ -0,0 +1,20 @@ +package unipotsdam.gf.view; + +import unipotsdam.gf.core.management.project.Project; + +public class Messages { + public static String GroupFormation(Project project){ + // TODO add link to site + markup + return "Die Gruppen wurden für den Kurs "+ project.getId() + " erstellt"; + } + + public static String NewFeedbackTask(Project project) { + // TODO add link to site + markup + return "Eine neue Feedbackaufgabe wurde für den Kurs "+ project.getId() + " erstellt"; + } + + public static String AssessmentPhaseStarted(Project project) { + // TODO add link to site + markup + return "Die Bewertungsphase hat begonnen. Bitte geht auf ... und macht ...."; + } +} diff --git a/gemeinsamforschen/src/main/resources/log4j2.xml b/gemeinsamforschen/src/main/resources/log4j2.xml index 44a5bde6b293c2233cb735339118c356d16db9dc..0282185a4ed09bdaf570f6c40599a7fc187866ed 100644 --- a/gemeinsamforschen/src/main/resources/log4j2.xml +++ b/gemeinsamforschen/src/main/resources/log4j2.xml @@ -6,7 +6,7 @@ </Console> </Appenders> <Loggers> - <Root level="debug"> + <Root level="INFO"> <AppenderRef ref="Console"/> </Root> </Loggers> diff --git a/gemeinsamforschen/src/main/webapp/assets/css/annotationStyle.css b/gemeinsamforschen/src/main/webapp/assets/css/annotationStyle.css index 74ac1c7a1a6fa585af3de0ca37f55496f13f22e9..3019f60766ac4a5acd7bd342ea5a4ae57e0d6413 100644 --- a/gemeinsamforschen/src/main/webapp/assets/css/annotationStyle.css +++ b/gemeinsamforschen/src/main/webapp/assets/css/annotationStyle.css @@ -85,7 +85,7 @@ ol { color: #e6e6e6; text-decoration: none; } -.annotation-header-title { +.annotation-header-data { display: flex; flex-flow: column; width: calc(100% - 40px); @@ -123,11 +123,11 @@ ol { .annotation-footer span { margin-left: 5px; } -.annotation-footer-delete { +.annotation-footer-edit { margin-right: 5px; cursor: pointer; } -.annotation-footer-date { +.flex-one { flex: 1 } .container-fluid-content { @@ -135,7 +135,7 @@ ol { flex-flow: column; height: 100%; } -.content-header { +.flex { display: flex; } .full-height { @@ -148,4 +148,7 @@ ol { .leftcontent-text { overflow: scroll; } +.resize-vertical { + resize: vertical; +} diff --git a/gemeinsamforschen/src/main/webapp/assets/js/annotationRest.js b/gemeinsamforschen/src/main/webapp/assets/js/annotationRest.js new file mode 100644 index 0000000000000000000000000000000000000000..787ccd96b74c391cd417e4733b5281611012720b --- /dev/null +++ b/gemeinsamforschen/src/main/webapp/assets/js/annotationRest.js @@ -0,0 +1,101 @@ +/** + * POST: Save an annotation in the database + * + * @param annotationPostRequest The post request + * @param responseHandler The response handler + */ +function createAnnotation(annotationPostRequest, responseHandler) { + var url = "../rest/annotations/"; + var json = JSON.stringify(annotationPostRequest); + $.ajax({ + url: url, + type: "POST", + data: json, + contentType: "application/json", + dataType: "json", + success: function (response) { + responseHandler(response); + } + }); +} + +/** + * PATCH: Alter an annotation in database + * + * @param id The annotation id + * @param annotationPatchRequest The patch request + * @param responseHandler The response handler + */ +function alterAnnotation(id, annotationPatchRequest, responseHandler) { + var url = "../rest/annotations/" + id; + var json = JSON.stringify(annotationPatchRequest); + $.ajax({ + url: url, + type: "PATCH", + data: json, + contentType: "application/json", + dataType: "json", + success: function (response) { + responseHandler(response); + } + }); +} + +/** + * DELETE: Delete an annotation from database + * + * @param id The annotation id + */ +function deleteAnnotation(id, responseHandler) { + var url = "../rest/annotations/" + id; + $.ajax({ + url: url, + type: "DELETE", + dataType: "json", + success: function (response) { + responseHandler(response) + } + }); +} + +/** + * GET: Get a specific annotation for a given id + * + * @param id The id of the annotation + * @param responseHandler The response handler + */ +function getAnnotation(id, responseHandler) { + var url = "../rest/annotations/" + id; + $.ajax({ + url: url, + type: "GET", + dataType: "json", + success: function (response) { + // handle the response + responseHandler(response); + } + }) +} + +/** + * GET: Get all annotations from database for a specific target + * + * @param targetId The target id + * @param responseHandler The response handler + */ +function getAnnotations(targetId, responseHandler) { + var url = "../rest/annotations/target/" + targetId; + $.ajax({ + url: url, + type: "GET", + dataType: "json", + success: function (response) { + // sort the responding annotations by timestamp (DESC) + response.sort(function (a, b) { + return a.timestamp - b.timestamp; + }); + // handle the response + responseHandler(response); + } + }); +} \ No newline at end of file diff --git a/gemeinsamforschen/src/main/webapp/assets/js/annotationScript.js b/gemeinsamforschen/src/main/webapp/assets/js/annotationScript.js index beba2528b6e0ece7ca6ba9a2c4ea65d89d9693c1..5150c1f92e7e23ebe6045b9df333dce7667093a9 100644 --- a/gemeinsamforschen/src/main/webapp/assets/js/annotationScript.js +++ b/gemeinsamforschen/src/main/webapp/assets/js/annotationScript.js @@ -1,17 +1,20 @@ -// initialize userId, userColors and targetId -var userId = randomUserId(); +// initialize userToken, userColors and targetId +var userToken = getUserTokenFromUrl(); var userColors = new Map(); var userColorsDark = new Map(); var targetId = 200; -// declare document text -var documentText; +// declare document text, start and end character +var documentText, startCharacter, endCharacter; /** * This function will fire when the DOM is ready */ $(document).ready(function() { + // connect to websocket on page ready + connect(targetId); + /** * Context menu handler */ @@ -19,30 +22,16 @@ $(document).ready(function() { selector: '.context-menu-one', callback: function(key, options) { - // close context menu - window.close; - - // initialize selected body - var body = getSelectedText(); - - // if user selected something - if (body.length > 0) { - // annotationPostRequest - var request = { - userId: userId, - targetId: targetId, - body: body, - startCharacter: window.getSelection().getRangeAt(0).startOffset, - endCharacter: window.getSelection().getRangeAt(0).endOffset - }; - - console.log(request); - - createAnnotation(request, function(response) { - // display the new annotation - displayAnnotation(response); + // action for 'annotation' click + if (key == 'annotation') { + // show modal if something is selected + if (getSelectedText().length > 0) { + startCharacter = window.getSelection().getRangeAt(0).startOffset; + endCharacter = window.getSelection().getRangeAt(0).endOffset; - }); + // display annotation create modal + $('#annotation-create-modal').modal("show"); + } } }, @@ -58,116 +47,181 @@ $(document).ready(function() { location.href="givefeedback.jsp?token=" + getUserTokenFromUrl(); }); - documentText = $('#documentText').html(); + /** + * validation of annotation create form inside the modal + */ + $('#annotation-create-form').validate({ + rules: { + title: { + required: true, + maxlength: 120 + }, + comment: { + required: true, + maxlength: 400 + } + }, + messages: { + title: { + required: "Ein Titel wird benötigt", + maxlength: "Maximal 120 Zeichen erlaubt" + }, + comment: { + required: "Ein Kommentar wird benötigt", + maxlength: "Maximal 400 Zeichen erlaubt" + } + } + }); - // fetch annotations from server on page start - getAnnotations(targetId, function (response) { - // iterate over annotations and display each - $.each(response, function (i, annotation) { - displayAnnotation(annotation); - }) + /** + * validation of annotation edit form inside the modal + */ + $('#annotation-edit-form').validate({ + rules: { + title: { + required: true, + maxlength: 120 + }, + comment: { + required: true, + maxlength: 400 + } + }, + messages: { + title: { + required: "Ein Titel wird benötigt", + maxlength: "Maximal 120 Zeichen erlaubt" + }, + comment: { + required: "Ein Kommentar wird benötigt", + maxlength: "Maximal 400 Zeichen erlaubt" + } + } }); -}); + /** + * Save button of the annotation create modal + * hide modal and build new annotation + */ + $('#btnSave').click(function () { + if ($('#annotation-create-form').valid()) { + // get title and comment from form + var title = $('#annotation-form-title').val(); + var comment = $('#annotation-form-comment').val(); -/** - * POST: Save an annotation in the database - * - * @param annotationPostRequest The post request - * @param responseHandler The response handler - */ -function createAnnotation(annotationPostRequest, responseHandler) { - var url = "http://localhost:8080/rest/annotations/"; - var json = JSON.stringify(annotationPostRequest); - $.ajax({ - url: url, - type: "POST", - data: json, - contentType: "application/json", - dataType: "json", - success: function (response) { - responseHandler(response); + // hide and clear the modal + $('#annotation-create-modal').modal('hide'); + + // save the new annotation in db and display it + saveNewAnnotation(title, comment, startCharacter, endCharacter); } }); -} -/** - * PATCH: Alter an annotation in database - * - * @param id The annotation id - * @param annotationPatchRequest The patch request - * @param responseHandler The response handler - */ -function alterAnnotation(id, annotationPatchRequest, responseHandler) { - var url = "http://localhost:8080/rest/annotations/" + id; - var json = JSON.stringify(annotationPatchRequest); - $.ajax({ - url: url, - type: "PATCH", - data: json, - contentType: "application/json", - dataType: "json", - success: function (response) { - responseHandler(response); + /** + * Edit button of the annotation edit modal + * hide modal and alter the annotation + */ + $('#btnEdit').click(function () { + if ($('#annotation-edit-form').valid()) { + // get title and comment from clicked annotation card + var id = $('#annotation-edit-modal').data('id'); + var card = $('#' + id); + var title = card.find('.annotation-header-data-title').text(); + var comment = card.find('.annotation-body-text').text(); + + // get title and comment from form + var newTitle = $('#annotation-edit-form-title').val(); + var newComment = $('#annotation-edit-form-comment').val(); + + // compare new and old card content + if (title !== newTitle || comment !== newComment) { + + // build patch request + var annotationPatchRequest = { + title: newTitle, + comment: newComment + }; + // send alter request to server + alterAnnotation(id, annotationPatchRequest, function (response) { + // send altered annotation to websocket + send("EDIT", id); + + // alter the annotation card + card.find('.annotation-header-data-title').text(newTitle); + card.find('.annotation-body-text').text(newComment); + + // handle drop down button + showAndHideToggleButton(); + + // hide and clear the modal + $('#annotation-edit-modal').modal('hide'); + }) + } } }); -} -/** - * DELETE: Delete an annotation from database - * - * @param id The annotation id - */ -function deleteAnnotation(id) { - var url = "http://localhost:8080/rest/annotations/" + id; - $.ajax({ - url: url, - type: "DELETE", - dataType: "json", - success: function (response) { - // Nothing to do - } + /** + * Delete an annotation from list and server + */ + $('#btnDelete').click(function () { + // get id from edit modal + var id = $('#annotation-edit-modal').data('id'); + + // delte annotation from server and from list + deleteAnnotation(id, function () { + // send delete request to websocket + send("DELETE", id); + // remove annotation from list + $('#' + id).closest('.listelement').remove() + // remove highlighted text + deleteHighlightedText(); + + // hide and clear the modal + $('#annotation-edit-modal').modal('hide'); + }) }); -} -/** - * GET: Get all annotations from database for a specific target - * - * - * @param targetId The target id - * @param responseHandler The response handler - */ -function getAnnotations(targetId, responseHandler) { - var url = "http://localhost:8080/rest/annotations/target/" + targetId; - $.ajax({ - url: url, - type: "GET", - dataType: "json", - success: function (response) { - // sort the responding annotations by timestamp (DESC) - response.sort(function (a, b) { - return a.timestamp - b.timestamp; - }); - // handle the response - responseHandler(response); - } + /** + * Clear the title and comment input field of the create modal + */ + $('#annotation-create-modal').on('hidden.bs.modal', function(){ + // clear title + $('#annotation-form-title').val(''); + // clear comment + $('#annotation-form-comment').val('') + }); + + /** + * Clear the title and comment input field of the edit modal + */ + $('#annotation-edit-modal').on('hidden.bs.modal', function(e){ + // clear title + $('#annotation-edit-form-title').val(''); + // clear comment + $('#annotation-edit-form-comment').val('') }); -} + + documentText = $('#documentText').html(); + + // fetch annotations from server on page start + getAnnotations(targetId, function (response) { + // iterate over annotations and display each + $.each(response, function (i, annotation) { + displayAnnotation(annotation); + }) + // handle drop down button + showAndHideToggleButton(); + }); + +}); /** - * Delete annotation from list - * - * @param elem The parent li element - * @param id The id of the annotation + * This will be called on page resize */ -function deleteAnnotationHandler(elem, id) { - // remove annotation from list - elem.remove() - // remove highlighted text - deleteHighlightedText(); - // remove annotation from database - deleteAnnotation(id) -} +$( window ).resize(function() { + // handle drop down button for every annotation + showAndHideToggleButton(); +}); /** * Display annotation in the list @@ -178,7 +232,7 @@ function displayAnnotation(annotation) { // fetch list of annotations var list = $('#annotations') - var deleteIcon = "fas fa-trash"; + var editIcon = "fas fa-edit"; var dateIcon = "fas fa-calendar"; if (isTimestampToday(annotation.timestamp)) { dateIcon = "fas fa-clock"; @@ -186,44 +240,52 @@ function displayAnnotation(annotation) { // insert annotation card list.prepend( + // list element $('<li>') .attr('class', 'listelement') .append( + // annotation card $('<div>').attr('class', 'annotation-card') + .attr('id', annotation.id) .mouseenter(function () { - $(this).children('.annotation-header').css('background-color', getDarkUserColor(annotation.userId)); + $(this).children('.annotation-header').css('background-color', getDarkUserColor(annotation.userToken)); }) .mouseleave(function () { - $(this).children('.annotation-header').css('background-color', getUserColor(annotation.userId)); + $(this).children('.annotation-header').css('background-color', getUserColor(annotation.userToken)); }) .append( + // annotation header $('<div>').attr('class', 'annotation-header') - .css('background-color', getUserColor(annotation.userId)) + .css('background-color', getUserColor(annotation.userToken)) .append( - $('<div>').attr('class', 'annotation-header-title') + // header data + $('<div>').attr('class', 'annotation-header-data') .append( + // user $('<div>').attr('class', 'overflow-hidden') .append( $('<i>').attr('class', 'fas fa-user') ) .append( - $('<span>').append(annotation.userId) + $('<span>').append(annotation.userToken) ) ) .append( + // title $('<div>').attr('class', 'overflow-hidden') .append( $('<i>').attr('class', 'fas fa-bookmark') ) .append( - $('<span>').append('title' + annotation.userId) + $('<span>').attr('class', 'annotation-header-data-title').append(annotation.body.title) ) ) ) .append( + // unfold button $('<div>').attr('class', 'annotation-header-toggle') .click(function () { - toggleButtonHandler($(this)); + toggleButtonHandler(annotation.id); }) .append( $('<i>').attr('class', 'fas fa-chevron-down') @@ -231,28 +293,32 @@ function displayAnnotation(annotation) { ) ) .append( + // annotation body $('<div>').attr('class', 'annotation-body') .append( - $('<p>').attr('class', 'overflow-hidden').append(annotation.body) + $('<p>').attr('class', 'overflow-hidden annotation-body-text').append(annotation.body.comment) ) ) .append( + // annotation footer $('<div>').attr('class', 'annotation-footer') .append( + // edit function () { - if (userId == annotation.userId) { - return $('<div>').attr('class', 'annotation-footer-delete') + if (userToken == annotation.userToken) { + return $('<div>').attr('class', 'annotation-footer-edit') .append( - $('<i>').attr('class', deleteIcon) + $('<i>').attr('class', editIcon) ) .click(function () { - deleteAnnotationHandler($(this).closest('li'), annotation.id) + editAnnotationHandler(annotation.id) }) } } ) .append( - $('<div>').attr('class', 'annotation-footer-date overflow-hidden') + // timestamp + $('<div>').attr('class', 'flex-one overflow-hidden') .append( $('<i>').attr('class', dateIcon) ) @@ -266,7 +332,7 @@ function displayAnnotation(annotation) { ) .data('annotation', annotation) .mouseenter(function () { - addHighlightedText(annotation.startCharacter, annotation.endCharacter, annotation.userId); + addHighlightedText(annotation.body.startCharacter, annotation.body.endCharacter, annotation.userToken); }) .mouseleave(function () { deleteHighlightedText(); @@ -284,11 +350,11 @@ function displayAnnotation(annotation) { * * @param startCharacter The offset of the start character * @param endCharacter The offset of the end character - * @param userId The user id + * @param userToken The user token */ -function addHighlightedText(startCharacter, endCharacter, userId) { +function addHighlightedText(startCharacter, endCharacter, userToken) { // create <span> tag with the annotated text - var replacement = $('<span></span>').css('background-color', getUserColor(userId)).html(documentText.slice(startCharacter, endCharacter)); + var replacement = $('<span></span>').css('background-color', getUserColor(userToken)).html(documentText.slice(startCharacter, endCharacter)); // wrap an <p> tag around the replacement, get its parent (the <p>) and ask for the html var replacementHtml = replacement.wrap('<p/>').parent().html(); @@ -327,39 +393,39 @@ function getSelectedText() { /** * Get color based on user id * - * @param userId The id of the user + * @param userToken The id of the user * @returns {string} The user color */ -function getUserColor(userId) { - // insert new color if there is no userId key - if (userColors.get(userId) == null) { - generateRandomColor(userId); +function getUserColor(userToken) { + // insert new color if there is no userToken key + if (userColors.get(userToken) == null) { + generateRandomColor(userToken); } // return the color - return userColors.get(userId); + return userColors.get(userToken); } /** * Get dark color based on user id * - * @param userId The id of the user + * @param userToken The token of the user * @returns {string} The dark user color */ -function getDarkUserColor(userId) { - // insert new color if there is no userId key - if (userColorsDark.get(userId) == null) { - generateRandomColor(userId); +function getDarkUserColor(userToken) { + // insert new color if there is no userToken key + if (userColorsDark.get(userToken) == null) { + generateRandomColor(userToken); } // return the color - return userColorsDark.get(userId); + return userColorsDark.get(userToken); } /** * Generate a random color of the format 'rgb(r, g, b)' * - * @param userId The given user id + * @param userToken The given user token */ -function generateRandomColor(userId) { +function generateRandomColor(userToken) { var r = Math.floor(Math.random()*56)+170; var g = Math.floor(Math.random()*56)+170; var b = Math.floor(Math.random()*56)+170; @@ -370,8 +436,8 @@ function generateRandomColor(userId) { var color = 'rgb(' + r + ',' + g + ',' + b + ')'; var colorDark = 'rgb(' + r_d + ',' + g_d + ',' + b_d + ')'; - userColors.set(userId, color); - userColorsDark.set(userId, colorDark); + userColors.set(userToken, color); + userColorsDark.set(userToken, colorDark); } /** @@ -386,29 +452,27 @@ function timestampToReadableTime(timestamp) { // declare response var responseTimestamp; + // get hours from date + var hours = "0" + annotationDate.getHours(); + // get minutes from date + var minutes = "0" + annotationDate.getMinutes(); + // if annotation is from today if (isTimestampToday(timestamp)) { - // get hours from date - var hours = annotationDate.getHours(); - // get minutes from date - var minutes = "0" + annotationDate.getMinutes(); - // get seconds from date - // var seconds = "0" + annotationDate.getSeconds(); - - // build readable timestamp - responseTimestamp = hours + ":" + minutes.substr(-2); + // build readable timestamp in format HH:mm + responseTimestamp = hours.substr(-2) + ":" + minutes.substr(-2); } // else annotation is not from today else { // get date - var date = annotationDate.getDate(); + var date = "0" + annotationDate.getDate(); // get month - var month = annotationDate.getMonth(); + var month = "0" + annotationDate.getMonth(); // get year - var year = annotationDate.getFullYear(); + var year = "" + annotationDate.getFullYear(); - // build readable timestamp - responseTimestamp = date + "." + month + "." + year; + // build readable timestamp dd.MM.yy HH:mm + responseTimestamp = date.substr(-2) + "." + month.substr(-2) + "." + year.substr(-2) + " " + hours.substr(-2) + ":" + minutes.substr(-2); } return responseTimestamp; @@ -438,19 +502,141 @@ function isTimestampToday(timestamp) { /** * Toggle between the toggle button status * - * @param element The given toggle button + * @param id The id of the clicked annotation */ -function toggleButtonHandler(element) { +function toggleButtonHandler(id) { + // the clicked annotation card + var card = $('#' + id); // open and close annotation text - element.parent().siblings(".annotation-body").children("p").toggleClass("overflow-hidden"); + card.find(".annotation-body").children("p").toggleClass("overflow-hidden"); // toggle between up and down button - element.children("i").toggleClass("fa-chevron-down fa-chevron-up") + card.find('.annotation-header-toggle').children("i").toggleClass("fa-chevron-down fa-chevron-up") } -/* - MOCKUP FUNCTIONS +/** + * Save a new annotation in database and list + * + * @param title The title of the new annotation + * @param comment The comment of the new annotation + * @param startCharacter The startCharacter based on the annotated text + * @param endCharacter The endCharacter based on the annotated text */ -function randomUserId() { - return Math.floor((Math.random() * 12) + 1);; +function saveNewAnnotation(title, comment, startCharacter, endCharacter) { + // build annotationPostRequest + var annotationPostRequest = { + userToken: userToken, + targetId: targetId, + body: { + title: title, + comment: comment, + startCharacter: startCharacter, + endCharacter: endCharacter + } + }; + + // send new annotation to back-end and display it in list + createAnnotation(annotationPostRequest, function(response) { + // send new annotation to websocket + send("CREATE", response.id); + // display the new annotation + displayAnnotation(response); + + }); +} + +/** + * Open edit modal with title and comment from given card + * + * @param id The id of the clicked annotation + */ +function editAnnotationHandler(id) { + // the clicked annotation card + var card = $('#' + id); + // get title and comment + var title = card.find('.annotation-header-data-title').text(); + var comment = card.find('.annotation-body-text').text(); + + // set title and comment + $('#annotation-edit-form-title').val(title); + $('#annotation-edit-form-comment').val(comment); + + // display annotation edit modal and pass id + $('#annotation-edit-modal').data('id', id).modal("show"); +} + +/** + * Change title and comment from annotation by given annotation + * + * @param annotation The given altered annotation + */ +function editAnnotationValues(annotation) { + // find annotation + var annotationElement = $('#' + annotation.id); + + // set title and comment + annotationElement.find('.annotation-header-data-title').text(annotation.body.title); + annotationElement.find('.annotation-body-text').text(annotation.body.comment); + + // handle drop down button + showAndHideToggleButtonById(annotation.id); +} + +/** + * Show or hide the drop down button for every annotation card. + * Call this on page resize and after annotations GET + */ +function showAndHideToggleButton() { + // iterate over each annotation card + $('#annotations').find('li').each(function () { + + // find the comment element, clone and hide it + var comment = $(this).find('.annotation-body').children('p'); + var clone = comment.clone() + .css({display: 'inline', width: 'auto', visibility: 'hidden'}) + .appendTo('body'); + var cloneWidth = clone.width(); + + // remove the element from the page + clone.remove(); + + // show drop down button only if text was truncated + if(cloneWidth > comment.width()) { + $(this).find('.annotation-header-toggle').show(); + $(this).find('.annotation-header-data').css('width', 'calc(100% - 40px)'); + } + else { + $(this).find('.annotation-header-toggle').hide(); + $(this).find('.annotation-header-data').css('width', '100%'); + } + + }) } +/** + * Show or hide the drop down button for a given annotation card. + * + * @param id The id of the annotation + */ +function showAndHideToggleButtonById(id) { + // find annotation + var annotationElement = $('#' + id); + // find the comment element, clone and hide it + var comment = annotationElement.find('.annotation-body').children('p'); + var clone = comment.clone() + .css({display: 'inline', width: 'auto', visibility: 'hidden'}) + .appendTo('body'); + var cloneWidth = clone.width(); + + // remove the element from the page + clone.remove(); + + // show drop down button only if text was truncated + if(cloneWidth > comment.width()) { + annotationElement.find('.annotation-header-toggle').show(); + annotationElement.find('.annotation-header-data').css('width', 'calc(100% - 40px)'); + } + else { + annotationElement.find('.annotation-header-toggle').hide(); + annotationElement.find('.annotation-header-data').css('width', '100%'); + } +} diff --git a/gemeinsamforschen/src/main/webapp/assets/js/annotationWebsocket.js b/gemeinsamforschen/src/main/webapp/assets/js/annotationWebsocket.js new file mode 100644 index 0000000000000000000000000000000000000000..62bbd2f33c69daada2c18e08614c9ab718ad6c00 --- /dev/null +++ b/gemeinsamforschen/src/main/webapp/assets/js/annotationWebsocket.js @@ -0,0 +1,39 @@ +var ws; + +function connect(targetId) { + var host = document.location.host; + var pathname = document.location.pathname; + + ws = new WebSocket("ws://" + host + "/ws/annotation/" + targetId); + + ws.onmessage = function (e) { + var message = JSON.parse(e.data); + console.log(message.from) + + if (message.type === "CREATE") { + // get annotation from server + getAnnotation(message.annotationId, function (response) { + // display annotation + displayAnnotation(response) + }) + } + else if (message.type === "DELETE") { + // remove annotation from list + $('#' + message.annotationId).closest('.listelement').remove() + } + else if (message.type === "EDIT") { + getAnnotation(message.annotationId, function (response) { + editAnnotationValues(response); + }) + } + }; +} + +function send(type, annotationId) { + var json = JSON.stringify({ + "type":type, + "annotationId":annotationId + }) + + ws.send(json); +} \ No newline at end of file diff --git a/gemeinsamforschen/src/main/webapp/pages/annotation-document.jsp b/gemeinsamforschen/src/main/webapp/pages/annotation-document.jsp index 9f2969275d66042918a5d32cd44d1f8044d3d735..de317f500d73c07fc90840a63303ec3c5c36889e 100644 --- a/gemeinsamforschen/src/main/webapp/pages/annotation-document.jsp +++ b/gemeinsamforschen/src/main/webapp/pages/annotation-document.jsp @@ -24,6 +24,8 @@ <!-- js - jQuery --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> + <!-- js - jQuery validation plugin --> + <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.14.0/jquery.validate.min.js"></script> <!-- js - bootstrap --> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <!-- js - jQuery ui position --> @@ -32,6 +34,10 @@ <script src="https://swisnl.github.io/jQuery-contextMenu/dist/jquery.contextMenu.js" type="text/javascript"></script> <!-- js - utility script --> <script src="../assets/js/utility.js"></script> + <!-- js - annotation websocket script --> + <script src="../assets/js/annotationWebsocket.js"></script> + <!-- js - annotation REST script --> + <script src="../assets/js/annotationRest.js"></script> <!-- js - annotationScript --> <script src="../assets/js/annotationScript.js"></script> @@ -43,7 +49,7 @@ <div class="page-content-wrapper full-height"> <div class="container-fluid full-height"> <div class="container-fluid-content"> - <div class="content-header"> + <div class="flex"> <h1>gemeinsam Forschen <a href="#"> <span class="glyphicon glyphicon-envelope" @@ -78,7 +84,71 @@ </div> </div> </div> + <!-- annotation create modal --> + <div id="annotation-create-modal" class="modal fade" role="dialog"> + <div class="modal-dialog modal-dialog-centered modal-sm"> + <div class="modal-content"> + + <!-- modal header --> + <div class="modal-header flex"> + <h4 class="modal-title flex-one">Annotation</h4> + <button type="button" class="close" data-dismiss="modal">×</button> + </div> + + <!-- modal body --> + <div class="modal-body"> + <form id="annotation-create-form"> + <div class="form-group"> + <label for="annotation-form-title" class="col-form-label">Titel:</label> + <input type="text" class="form-control" id="annotation-form-title" name="title"> + </div> + <div class="form-group"> + <label for="annotation-form-comment" class="col-form-label">Kommentar:</label> + <textarea class="form-control resize-vertical" id="annotation-form-comment" name="comment"></textarea> + </div> + </form> + <!-- modal footer --> + <div class="modal-footer"> + <button id="btnSave" type="button" class="btn btn-success">Speichern</button> + </div> + </div> + </div> + </div> + </div> + + <!-- annotation edit modal --> + <div id="annotation-edit-modal" class="modal fade" role="dialog"> + <div class="modal-dialog modal-dialog-centered modal-sm"> + <div class="modal-content"> + + <!-- modal header --> + <div class="modal-header flex"> + <h4 class="modal-title flex-one">Annotation bearbeiten</h4> + <button type="button" class="close" data-dismiss="modal">×</button> + </div> + + <!-- modal body --> + <div class="modal-body"> + <form id="annotation-edit-form"> + <div class="form-group"> + <label for="annotation-form-title" class="col-form-label">Titel:</label> + <input type="text" class="form-control" id="annotation-edit-form-title" name="title"> + </div> + <div class="form-group"> + <label for="annotation-form-comment" class="col-form-label">Kommentar:</label> + <textarea class="form-control resize-vertical" id="annotation-edit-form-comment" name="comment"></textarea> + </div> + </form> + <!-- modal footer --> + <div class="modal-footer"> + <button id="btnDelete" type="button" class="btn btn-danger">Löschen</button> + <button id="btnEdit" type="button" class="btn btn-success">Bearbeiten</button> + </div> + </div> + </div> + </div> + </div> </div> </body> -</html> \ No newline at end of file +</html> diff --git a/gemeinsamforschen/src/scripts/dbschema/fltrail.sql b/gemeinsamforschen/src/scripts/dbschema/fltrail.sql index e0de36c8ad91abac6c99ba248635c87a0919a898..28f6d3080403bec40088fd1440913b88c6b2610c 100644 --- a/gemeinsamforschen/src/scripts/dbschema/fltrail.sql +++ b/gemeinsamforschen/src/scripts/dbschema/fltrail.sql @@ -8,19 +8,22 @@ USE `fltrail`; CREATE TABLE if not exists `projects` ( - `id` varchar(400) NOT NULL, + `id` varchar(100) NOT NULL, `password` varchar(400) NOT NULL, - `active` tinyint(1) NOT NULL, + `active` tinyint(1) NOT NULL, - `timecreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `timecreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP + ON UPDATE CURRENT_TIMESTAMP, `author` varchar(400) NOT NULL, `adminPassword` varchar(400) NOT NULL, - `token` varchar(400) NOT NULL + `token` varchar(400) NOT NULL, + + `phase` varchar(400) NOT NULL ) @@ -60,7 +63,7 @@ CREATE TABLE if not exists groupuser CREATE TABLE if not exists `tags` ( - `projectId` varchar(400) NOT NULL, + `projectId` varchar(100) NOT NULL, `tag` varchar(400) NOT NULL @@ -72,7 +75,7 @@ CREATE TABLE if not exists `tags` ( CREATE TABLE if not exists `users` ( - `name` varchar(400) NOT NULL, + `name` varchar(100) NOT NULL, `password` varchar(200) NOT NULL, @@ -96,53 +99,101 @@ CREATE TABLE if not exists projectuser ( - projectId varchar(400) NOT NULL, + projectId varchar(100) NOT NULL, - userId varchar(400) NOT NULL + userId varchar(100) NOT NULL ) ENGINE = InnoDB - DEFAULT CHARSET = utf8;CREATE TABLE if not exists `annotations` ( + DEFAULT CHARSET = utf8; +CREATE TABLE if not exists `annotations` ( `id` varchar(120) NOT NULL, - `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - `userId` int(11) DEFAULT NULL, - + `userToken` varchar(120) DEFAULT NULL, `targetId` int(11) DEFAULT NULL, - - `body` varchar(280) DEFAULT NULL, - + `title` varchar(120) DEFAULT NULL, + `comment` varchar(400) DEFAULT NULL, `startCharacter` int(11) DEFAULT NULL, - `endCharacter` int(11) DEFAULT NULL, - PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; -) ENGINE=InnoDB DEFAULT CHARSET=utf8;alter table users +alter table users add isStudent tinyint(1) default '1' null; + CREATE TABLE if not exists quiz ( - author varchar(400) NOT NULL, + author varchar(400) NOT NULL, + + projectId varchar(400) NOT NULL, + + question varchar(400) NOT NULL, + + mcType varchar(400) NOT NULL, + + answer varchar(400) NOT NULL, + + correct tinyint(1) NOT NULL + +) + + ENGINE = InnoDB + + DEFAULT CHARSET = utf8; + +CREATE TABLE if not exists tasks + +( + + userId varchar(400) NOT NULL, projectId varchar(400) NOT NULL, - question varchar(400) NOT NULL, + taskUrl varchar(400) NOT NULL +) - mcType varchar(400) NOT NULL, + ENGINE = InnoDB - answer varchar(400) NOT NULL, + DEFAULT CHARSET = utf8; - correct tinyint(1) NOT NULL +CREATE TABLE if not exists phasesSelected ( + `projectId` varchar(100) NOT NULL, + phaseSelected varchar(200) NOT NULL ) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; +CREATE TABLE if not exists categoriesSelected ( + `projectId` varchar(100) NOT NULL, + categorySelected varchar(200) NOT NULL +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +CREATE TABLE if not exists groupfindingMechanismSelected ( + `projectId` varchar(100) NOT NULL, + gfmSelected varchar(200) NOT NULL +) ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +CREATE TABLE if not exists assessmentMechanismSelected ( + `projectId` varchar(100) NOT NULL, + amSelected varchar(200) NOT NULL +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; - DEFAULT CHARSET = utf8; \ No newline at end of file +ALTER TABLE `projectuser` + ADD INDEX (`projectId`, `userId`); +ALTER TABLE `projectuser` + ADD UNIQUE (`projectId`, `userId`); +ALTER TABLE `projects` + ADD UNIQUE (`id`); \ No newline at end of file diff --git a/gemeinsamforschen/src/test/java/unipotsdam/gf/interfaces/ActivityFlowTest.java b/gemeinsamforschen/src/test/java/unipotsdam/gf/interfaces/ActivityFlowTest.java new file mode 100644 index 0000000000000000000000000000000000000000..65248217c3fa9ed816fe96ffe1e6ca88ebed0ddf --- /dev/null +++ b/gemeinsamforschen/src/test/java/unipotsdam/gf/interfaces/ActivityFlowTest.java @@ -0,0 +1,263 @@ +package unipotsdam.gf.interfaces; + +import org.glassfish.hk2.api.ServiceLocator; +import org.glassfish.hk2.utilities.ServiceLocatorUtilities; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.MockitoRule; +import uk.co.jemos.podam.api.PodamFactory; +import uk.co.jemos.podam.api.PodamFactoryImpl; +import unipotsdam.gf.config.GFApplicationBinder; +import unipotsdam.gf.core.management.Management; +import unipotsdam.gf.core.management.group.Group; +import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.core.management.project.ProjectConfiguration; +import unipotsdam.gf.core.management.user.User; +import unipotsdam.gf.core.states.ProjectPhase; +import unipotsdam.gf.modules.assessment.QuizAnswer; +import unipotsdam.gf.modules.assessment.controller.model.StudentAndQuiz; +import unipotsdam.gf.modules.groupfinding.GroupFormationMechanism; +import unipotsdam.gf.modules.groupfinding.GroupfindingCriteria; +import unipotsdam.gf.modules.journal.model.Journal; +import unipotsdam.gf.modules.peer2peerfeedback.Category; +import unipotsdam.gf.modules.peer2peerfeedback.Peer2PeerFeedback; +import unipotsdam.gf.modules.researchreport.ResearchReport; +import unipotsdam.gf.modules.researchreport.ResearchReportManagement; +import javax.inject.Inject; +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + + +@RunWith(MockitoJUnitRunner.class) +public class ActivityFlowTest { + + /** + * Utility to creaty dummy data for students + */ + PodamFactory factory = new PodamFactoryImpl(); + + @Inject + Management management; + + @Inject + ResearchReportManagement researchReportManagement; + + + @Inject + Feedback feedback; + + @Inject + IPhases phases; + + @Inject + IGroupFinding groupFinding; + + @Inject + ICommunication iCommunication; + + @Inject + IJournal iJournal; + + @Inject + IPeerAssessment iPeerAssessment; + + + private final Project project = factory.manufacturePojo(Project.class); + private final ArrayList<User> students = new ArrayList<>(); + private final User teacher = factory.manufacturePojo(User.class); + + @Rule + public MockitoRule mockitoRule = MockitoJUnit.rule(); + + + + @Before + public void setUp() { + final ServiceLocator locator = ServiceLocatorUtilities.bind(new GFApplicationBinder()); + locator.inject(this); + + feedback = Mockito.spy(feedback); + researchReportManagement = Mockito.spy(researchReportManagement); + phases = Mockito.spy(phases); + iCommunication = Mockito.spy(iCommunication); + + // TODO @Julian: Find out more elegant way of doing this + researchReportManagement.setFeedback(feedback); + phases.setFeedback(feedback); + + } + + @Test + public void activityPlayer() { + // register teacher + loginTeacher(); + + // create course + createCourse(); + + // register students + loginStudents(); + + // form groups + formGroups(); + + // end first phase + phases.endPhase(ProjectPhase.CourseCreation, project); + + // upload dossiers + uploadDossiers(); + + // end first phase + phases.endPhase(ProjectPhase.DossierFeedback, project); + + // update reflections + uploadReflections(); + + // end execution phase + phases.endPhase(ProjectPhase.Execution, project); + } + + + + public void formGroups() { + + // form groups based on user profil + groupFinding.formGroups(GroupFormationMechanism.UserProfilStrategy); + + // update groups manually + groupFinding.formGroups(GroupFormationMechanism.Manual); + + } + + + public void loginTeacher() { + teacher.setStudent(false); + management.create(teacher, null); + } + + + public void loginStudents() { + for (int i=0;i<100;i++) { + User student = factory.manufacturePojo(User.class); + student.setStudent(true); + students.add(student); + management.create(student, null); + } + } + + public void uploadReflections() { + // update single reflection + Journal journalEntry = factory.manufacturePojo(Journal.class); + + for (User student : students) { + iJournal.uploadJournalEntry(journalEntry, student); + } + + + // create quiz TODO@Axel this should be a quiz dependend on the student for easier initialization and + // de-coupling + StudentAndQuiz studentAndQuiz = factory.manufacturePojo(StudentAndQuiz.class); + QuizAnswer quizAnswer = factory.manufacturePojo(QuizAnswer.class); + iPeerAssessment.createQuiz(studentAndQuiz); + iPeerAssessment.answerQuiz(studentAndQuiz, quizAnswer); + + // finales Portfolio zusammenstellen + java.util.List<Journal> journalEntries = new ArrayList<Journal>(); + journalEntries.add(journalEntry); + + ResearchReport finalResearchReport = factory.manufacturePojo(ResearchReport.class); + File presentation = new File("dummy.pptx"); + + for (User student : students) { + iJournal.uploadFinalPortfolio(project,journalEntries, finalResearchReport, presentation, student); + } + assertNotNull(true); + + } + + public void uploadDossiers() { + + + for (User student : students) { + // persist dossiers + ResearchReport researchReport = factory.manufacturePojo(ResearchReport.class); + researchReportManagement.createResearchReport(researchReport, project, student); + } + + + // assert that after the last report has been submitted, the feedback tasks were assigned automatically + verify(feedback).assignFeedbackTasks(); + + // students give feedback + for (User student : students) { + ResearchReport feedbackTask = feedback.getFeedbackTask(student); + ProjectConfiguration projectConfiguration = management.getProjectConfiguration(project); + HashMap<Category, Boolean> criteriaSelected = projectConfiguration.getCriteriaSelected(); + for (Category category : criteriaSelected.keySet()) { + if (criteriaSelected.get(category)) { + Peer2PeerFeedback peer2PeerFeedback = factory.manufacturePojo(Peer2PeerFeedback.class); + peer2PeerFeedback.setFeedbackcategory(category); + feedback.giveFeedback(peer2PeerFeedback, feedbackTask); + } + } + } + + // students upload updated dossier + ArrayList<User> students2 = students; + students2.remove(2); + Iterator<User> students2Iterator = students2.iterator(); + while (students2Iterator.hasNext()) { + User student = students2Iterator.next(); + // persist final dossiers -- assuming this function is intended + // if only one time upload is intended and feedback is not incorporated into a final dossier + // you should change this test to reflect only one time upload + // i.e. removing one student above to reflect no compliance + ResearchReport researchReport = factory.manufacturePojo(ResearchReport.class); + researchReportManagement.createFinalResearchReport(researchReport, project, student); + } + + // docent finishes phase + phases.endPhase(ProjectPhase.DossierFeedback, project); + + // student misses mockfeedback -> reassignment + // assert that while reports are still missing mockfeedback tasks are reassigned + verify(feedback).assigningMissingFeedbackTasks(project); + + // assert that everybody has given and received mockfeedback + assertTrue(feedback.checkFeedbackConstraints(project)); + + // docent finishes phase + phases.endPhase(ProjectPhase.DossierFeedback, project); + + } + + + public void createCourse() { + // add Titel + Project project = factory.manufacturePojo(Project.class); + management.create(project); + + ProjectConfiguration projectConfiguration = factory.manufacturePojo(ProjectConfiguration.class); + management.create(projectConfiguration, project); + + GroupfindingCriteria groupfindingCriteria = factory.manufacturePojo(GroupfindingCriteria.class); + groupFinding.selectGroupfindingCriteria(groupfindingCriteria); + + } + +} diff --git a/gemeinsamforschen/src/test/java/unipotsdam/gf/interfaces/AnnotationTest.java b/gemeinsamforschen/src/test/java/unipotsdam/gf/interfaces/AnnotationTest.java index 6c64c0be2de3d76d89849450bb797ab921876b79..d0fde6c5871fd1533cc8e37308ec2e3068343327 100644 --- a/gemeinsamforschen/src/test/java/unipotsdam/gf/interfaces/AnnotationTest.java +++ b/gemeinsamforschen/src/test/java/unipotsdam/gf/interfaces/AnnotationTest.java @@ -4,6 +4,7 @@ import org.junit.Before; import org.junit.Test; import unipotsdam.gf.modules.annotation.controller.AnnotationController; import unipotsdam.gf.modules.annotation.model.Annotation; +import unipotsdam.gf.modules.annotation.model.AnnotationBody; import unipotsdam.gf.modules.annotation.model.AnnotationPatchRequest; import unipotsdam.gf.modules.annotation.model.AnnotationPostRequest; @@ -31,11 +32,12 @@ public class AnnotationTest { @Test public void testAddAnnotation() { - // initialize body - String body = "body_testAddAnnotation"; + // initialize title and comment of body + String title = "title_testAddAnnotation"; + String comment = "comment_testAddAnnotation"; // prepare and execute request - AnnotationPostRequest annotationPostRequest = new AnnotationPostRequest(1, 2, body, 4, 5); + AnnotationPostRequest annotationPostRequest = new AnnotationPostRequest("userToken", 1, new AnnotationBody(title, comment, 1, 2)); Annotation response = controller.addAnnotation(annotationPostRequest); // the new annotation should be found in the database @@ -49,44 +51,52 @@ public class AnnotationTest { @Test public void testAlterAnnotation() { - // initialize old and new body - String oldBody = "bodyOld_testAlterAnnotation"; - String newBody = "bodyNew_testAlterAnnotation"; + // initialize old and new title and comment of body + String titleOld = "titleOld_testAlterAnnotation"; + String commentOld = "commentOld_testAlterAnnotation"; + String titleNew = "titleNew_testAlterAnnotation"; + String commentNew = "commentNew_testAlterAnnotation"; // save new annotation in database - AnnotationPostRequest annotationPostRequest = new AnnotationPostRequest(0, 0, oldBody, 0, 0); + AnnotationPostRequest annotationPostRequest = new AnnotationPostRequest("userToken", 0, new AnnotationBody(titleOld, commentOld, 1, 2)); Annotation response = controller.addAnnotation(annotationPostRequest); // the new annotation should be found in the database assertTrue("Can't find annotation with the id " + response.getId(), controller.existsAnnotationId(response.getId())); - // the annotation's body should be "testAlterAnnotation_oldBody" - assertEquals("The body of the annotation should be " + oldBody + " but was " + response.getBody(), oldBody, response.getBody()); + // the annotation's title should be "titleOld_testAlterAnnotation" + assertEquals("The title of the annotation should be " + titleOld + " but was " + response.getBody().getTitle(), titleOld, response.getBody().getTitle()); + + // the annotation's comment should be "commentOld_testAlterAnnotation" + assertEquals("The comment of the annotation should be " + commentOld + " but was " + response.getBody().getComment(), commentOld, response.getBody().getComment()); // alter the annotation and update the database - AnnotationPatchRequest annotationPatchRequest = new AnnotationPatchRequest(newBody); + AnnotationPatchRequest annotationPatchRequest = new AnnotationPatchRequest(titleNew, commentNew); controller.alterAnnotation(response.getId(), annotationPatchRequest); // receive the new annotation Annotation newResponse = controller.getAnnotation(response.getId()); - // the annotation's body should be "testAlterAnnotation_newBody" - assertEquals("The body of the annotation should be " + newBody + " but was " + newResponse.getBody(), newBody, newResponse.getBody()); + // the annotation's title should be "titleNew_testAlterAnnotation" + assertEquals("The title of the annotation should be " + titleNew + " but was " + newResponse.getBody().getTitle(), titleNew, newResponse.getBody().getTitle()); + + // the annotation's comment should be "commentNew_testAlterAnnotation" + assertEquals("The comment of the annotation should be " + commentNew + " but was " + newResponse.getBody().getComment(), commentNew, newResponse.getBody().getComment()); // delete the annotation controller.deleteAnnotation(response.getId()); - } @Test public void testDeleteAnnotation() { - // initialize old and new body - String body = "body_testDeleteAnnotation"; + // initialize title and comment of body + String title = "title_testDeleteAnnotation"; + String comment = "comment_testDeleteAnnotation"; - // save new annotation in database - AnnotationPostRequest annotationPostRequest = new AnnotationPostRequest(0, 0, body, 0, 0); + // prepare and execute request + AnnotationPostRequest annotationPostRequest = new AnnotationPostRequest("userToken", 1, new AnnotationBody(title, comment, 1, 2)); Annotation response = controller.addAnnotation(annotationPostRequest); // the new annotation should be found in the database @@ -103,18 +113,22 @@ public class AnnotationTest { @Test public void testGetAnnotation() { - // initialize body - String body = "body_testGetAnnotation"; + // initialize title and comment of body + String title = "title_testGetAnnotation"; + String comment = "comment_testGetAnnotation"; - // save new annotation in database - AnnotationPostRequest annotationPostRequest = new AnnotationPostRequest(0, 0, body, 0, 0); + // prepare and execute request + AnnotationPostRequest annotationPostRequest = new AnnotationPostRequest("userToken", 1, new AnnotationBody(title, comment, 1, 2)); Annotation response = controller.addAnnotation(annotationPostRequest); // receive the new annotation Annotation getResponse = controller.getAnnotation(response.getId()); - // the annotation's body should be "testAlterAnnotation_newBody" - assertEquals("The body of the annotation should be " + body + " but was " + getResponse.getBody(), body, getResponse.getBody()); + // the annotation's title should be "title_testAlterAnnotation" + assertEquals("The title of the annotation should be " + title + " but was " + response.getBody().getTitle(), title, response.getBody().getTitle()); + + // the annotation's comment should be "comment_testAlterAnnotation" + assertEquals("The comment of the annotation should be " + comment + " but was " + response.getBody().getComment(), comment, response.getBody().getComment()); // delete the new annotation controller.deleteAnnotation(response.getId()); @@ -124,10 +138,9 @@ public class AnnotationTest { @Test public void testGetAnnotations() { - // initialize bodys - String body1 = "body1_testGetAnnotations"; - String body2 = "body2_testGetAnnotations"; - String body3 = "body3_testGetAnnotations"; + // initialize title and comment of bodys + String title = "title_testGetAnnotations"; + String comment = "comment_testGetAnnotations"; // initialize targetIds ArrayList<Integer> targetIds = new ArrayList<>(); @@ -135,23 +148,23 @@ public class AnnotationTest { targetIds.add(-2); // save new annotations in database - AnnotationPostRequest request1 = new AnnotationPostRequest(0, targetIds.get(0), body1, 0, 0); - AnnotationPostRequest request2 = new AnnotationPostRequest(0, targetIds.get(1), body2, 0, 0); - AnnotationPostRequest request3 = new AnnotationPostRequest(0, targetIds.get(1), body3, 0, 0); + AnnotationPostRequest request1 = new AnnotationPostRequest("userToken", targetIds.get(0), new AnnotationBody(title, comment, 1, 2)); + AnnotationPostRequest request2 = new AnnotationPostRequest("userToken", targetIds.get(1), new AnnotationBody(title, comment, 1, 2)); + AnnotationPostRequest request3 = new AnnotationPostRequest("userToken", targetIds.get(1), new AnnotationBody(title, comment, 1, 2)); controller.addAnnotation(request1); controller.addAnnotation(request2); controller.addAnnotation(request3); - // receive the new annotations + // receive the new annotations with targetId = -2 ArrayList<Annotation> getResponse = controller.getAnnotations(targetIds.get(1)); - // the size of the getResponse should be 2 + // the size of the getResponse should be 2 assertEquals("The size of the response should be 2 but was " + getResponse.size(), 2, getResponse.size()); - // receive the new annotations + // receive the new annotations with targetId = -1 ArrayList<Annotation> getResponseNew = controller.getAnnotations(targetIds.get(0)); - // the size of the getResponse should be 2 + // the size of the getResponse should be 1 assertEquals("The size of the response should be 1 but was " + getResponseNew.size(), 1, getResponseNew.size()); // delete annotations from database @@ -164,12 +177,13 @@ public class AnnotationTest { @Test public void testExistsAnnotationId() { - // initialize body and bad id - String body = "body_testExistsAnnotationId"; + // initialize title and comment of body and bad id + String title = "title_testExistsAnnotationId"; + String comment = "comment_testExistsAnnotationId"; String badId = "badId"; // save new annotation in database - AnnotationPostRequest annotationPostRequest = new AnnotationPostRequest(0, 0, body, 0, 0); + AnnotationPostRequest annotationPostRequest = new AnnotationPostRequest("userToken", 0, new AnnotationBody(title, comment, 1, 2)); Annotation response = controller.addAnnotation(annotationPostRequest); // the annotation shouldn't be found in the database diff --git a/gemeinsamforschen/src/test/java/unipotsdam/gf/interfaces/ManagementTest.java b/gemeinsamforschen/src/test/java/unipotsdam/gf/interfaces/ManagementTest.java index 8e71c0dcba017d321a6af5540fb843ea8ff7352c..9fbce54234111c240d671b9fb5e6ea7443201dda 100644 --- a/gemeinsamforschen/src/test/java/unipotsdam/gf/interfaces/ManagementTest.java +++ b/gemeinsamforschen/src/test/java/unipotsdam/gf/interfaces/ManagementTest.java @@ -1,20 +1,40 @@ package unipotsdam.gf.interfaces; +import javafx.application.Application; +import org.glassfish.hk2.api.ServiceLocator; +import org.glassfish.hk2.utilities.Binder; +import org.glassfish.hk2.utilities.ServiceLocatorUtilities; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Before; import org.junit.Test; +import uk.co.jemos.podam.api.PodamFactory; +import uk.co.jemos.podam.api.PodamFactoryImpl; +import unipotsdam.gf.config.GFApplicationBinder; +import unipotsdam.gf.config.GFResourceConfig; import unipotsdam.gf.core.management.ManagementImpl; import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.core.management.project.ProjectConfiguration; import unipotsdam.gf.core.management.user.User; import unipotsdam.gf.core.management.user.UserProfile; import java.util.List; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; /** * Created by dehne on 01.06.2018. */ -public class ManagementTest { + + +public class ManagementTest { + + + /** + * Utility to creaty dummy data for students + */ + PodamFactory factory = new PodamFactoryImpl(); + @Test public void testDelete() { @@ -90,6 +110,8 @@ public class ManagementTest { management.create(project); management.register(user, project, null); + assertTrue(management.exists(project)); + User user2 = new User("julian2", "12345", "from2@stuff.com", true); management.create(user2, new UserProfile()); assert management.exists(user2); @@ -99,4 +121,20 @@ public class ManagementTest { assert !users.isEmpty(); } + + @Test + public void testProjectConfiguration() { + ProjectConfiguration projectConfiguration = factory.manufacturePojo(ProjectConfiguration.class); + Project project = factory.manufacturePojo(Project.class); + + ManagementImpl management = new ManagementImpl(); + management.create(projectConfiguration, project); + + ProjectConfiguration projectConfiguration1 = management.getProjectConfiguration(project); + assertNotNull(projectConfiguration1.getCriteriaSelected()); + assertNotNull(projectConfiguration1.getAssessmentMechanismSelected()); + assertNotNull(projectConfiguration1.getGroupMechanismSelected()); + assertNotNull(projectConfiguration1.getPhasesSelected()); + + } } \ No newline at end of file diff --git a/gemeinsamforschen/src/test/java/unipotsdam/gf/interfaces/PhaseTest.java b/gemeinsamforschen/src/test/java/unipotsdam/gf/interfaces/PhaseTest.java new file mode 100644 index 0000000000000000000000000000000000000000..9d59d39a89bade2431dee22455ef1bcc457c1f2a --- /dev/null +++ b/gemeinsamforschen/src/test/java/unipotsdam/gf/interfaces/PhaseTest.java @@ -0,0 +1,74 @@ +package unipotsdam.gf.interfaces; + +import org.glassfish.hk2.api.ServiceLocator; +import org.glassfish.hk2.utilities.ServiceLocatorUtilities; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import unipotsdam.gf.config.GFApplicationBinder; +import unipotsdam.gf.core.management.ManagementImpl; +import unipotsdam.gf.core.management.project.Project; +import unipotsdam.gf.core.management.user.User; +import unipotsdam.gf.core.management.user.UserProfile; +import unipotsdam.gf.core.states.ProjectPhase; +import javax.inject.Inject; + +public class PhaseTest { + + @Inject + private IPhases phases; + + + @Before + public void setUp() { + final ServiceLocator locator = ServiceLocatorUtilities.bind(new GFApplicationBinder()); + locator.inject(this); + } + + @BeforeClass + public static void prepareProject() { + ManagementImpl management = new ManagementImpl(); + User user = new User("julian", "1234", "from@stuff.com", false); + management.create(user, new UserProfile()); + assert management.exists(user); + + Project project = new Project("Gemainsam Forschen", "1235", true, "me", "keins"); + management.create(project); + management.register(user, project, null); + } + + @Test + public void phase1() { + Project project = new Project(); + project.setId("Gemainsam Forschen"); + phases.endPhase(ProjectPhase.CourseCreation, project); + } + + @Test + public void phase2() { + Project project = new Project(); + project.setId("Gemainsam Forschen"); + phases.endPhase(ProjectPhase.GroupFormation, project); + } + + @Test + public void phase3() { + Project project = new Project(); + project.setId("Gemainsam Forschen"); + phases.endPhase(ProjectPhase.DossierFeedback, project); + } + + @Test + public void phase4() { + Project project = new Project(); + project.setId("Gemainsam Forschen"); + phases.endPhase(ProjectPhase.Execution, project); + } + + @Test + public void phase5() { + Project project = new Project(); + project.setId("Gemainsam Forschen"); + phases.endPhase(ProjectPhase.Assessment, project); + } +} diff --git a/gemeinsamforschen/src/test/java/unipotsdam/gf/testsandbox/SpiedListHolder.java b/gemeinsamforschen/src/test/java/unipotsdam/gf/testsandbox/SpiedListHolder.java new file mode 100644 index 0000000000000000000000000000000000000000..de9f94dff4e159f7cfc9076f9ee89092356a65ca --- /dev/null +++ b/gemeinsamforschen/src/test/java/unipotsdam/gf/testsandbox/SpiedListHolder.java @@ -0,0 +1,20 @@ +package unipotsdam.gf.testsandbox; + +import unipotsdam.gf.core.testsandbox.TestListInterface; +import unipotsdam.gf.interfaces.Feedback; + +import javax.inject.Inject; + +public class SpiedListHolder { + private TestListInterface spiedList; + + + @Inject + public SpiedListHolder(TestListInterface spiedList) { + this.spiedList = spiedList; + } + + public TestListInterface getSpiedList() { + return spiedList; + } +} diff --git a/gemeinsamforschen/src/test/java/unipotsdam/gf/testsandbox/TestTestTest.java b/gemeinsamforschen/src/test/java/unipotsdam/gf/testsandbox/TestTestTest.java new file mode 100644 index 0000000000000000000000000000000000000000..74a6a1f5839925856c853efda71829164cb164ba --- /dev/null +++ b/gemeinsamforschen/src/test/java/unipotsdam/gf/testsandbox/TestTestTest.java @@ -0,0 +1,118 @@ +package unipotsdam.gf.testsandbox; + + +import org.glassfish.hk2.api.ServiceLocator; +import org.glassfish.hk2.utilities.ServiceLocatorUtilities; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; +import unipotsdam.gf.config.GFApplicationBinder; +import unipotsdam.gf.core.testsandbox.TestListInterface; + +import javax.inject.Inject; +import java.util.ArrayList; + +import static junit.framework.Assert.assertEquals; + +@RunWith(MockitoJUnitRunner.class) +public class TestTestTest { + + + @Spy + java.util.List<String> spiedList = new ArrayList<String>(); + + + @Inject + TestListInterface spiedList2; + + @Inject + @Spy + TestListInterface spiedList3; + + + @Inject + SpiedListHolder spiedListHolder; + + + @Before + public void setUp() { + final ServiceLocator locator = ServiceLocatorUtilities.bind(new GFApplicationBinder()); + locator.inject(this); + } + + + // GEHT + @Test + public void howSpiesWork() { + java.util.List<String> spiedList = Mockito.spy(new ArrayList<String>()); + Mockito.spy(spiedList); + + spiedList.add("one"); + spiedList.add("two"); + + Mockito.verify(spiedList).add("one"); + Mockito.verify(spiedList).add("two"); + + assertEquals(2, spiedList.size()); + } + + + // GEHT + @Test + public void howSpiesWorkWithAnnotation() { + + spiedList.add("one"); + spiedList.add("two"); + + Mockito.verify(spiedList).add("one"); + Mockito.verify(spiedList).add("two"); + + assertEquals(2, spiedList.size()); + } + + // GEHT + @Test + public void howSpiesWorkWithInjection() { + + java.util.List<String> spiedList = Mockito.spy(spiedList2); + + spiedList.add("one"); + spiedList.add("two"); + + Mockito.verify(spiedList).add("one"); + Mockito.verify(spiedList).add("two"); + + assertEquals(2, spiedList.size()); + } + + // GEHT NICHT! + @Test + public void howSpiesWorkWithInjectionAndAnnotation() { + + spiedList3.add("one"); + spiedList3.add("two"); + + Mockito.verify(spiedList3).add("one"); + Mockito.verify(spiedList3).add("two"); + + assertEquals(2, spiedList3.size()); + } + + /* // + @Test + public void howSpiesWorkWithConstructorInjection() { + + java.util.List<String> spiedList4 = Mockito.spy(spiedListHolder.getSpiedList()); + + spiedList4.add("one"); + spiedList4.add("two"); + + Mockito.verify(spiedList4).add("one"); + Mockito.verify(spiedList4).add("two"); + + assertEquals(2, spiedList4.size()); + }*/ +}