diff --git a/pom.xml b/pom.xml index 18af176..a6b89a7 100644 --- a/pom.xml +++ b/pom.xml @@ -30,12 +30,12 @@ commons-cli commons-cli - RELEASE + 1.4 - commons-email + org.apache.commons commons-email - RELEASE + 1.5 org.jetbrains @@ -46,7 +46,7 @@ org.apache.httpcomponents httpclient - RELEASE + 4.5.6 diff --git a/src/main/java/nl/andrewlalis/git_api/GithubManager.java b/src/main/java/nl/andrewlalis/git_api/GithubManager.java index 1f7c2a3..fe15ce7 100644 --- a/src/main/java/nl/andrewlalis/git_api/GithubManager.java +++ b/src/main/java/nl/andrewlalis/git_api/GithubManager.java @@ -251,7 +251,7 @@ public class GithubManager { return; } - team.setRepository(repo); + team.setRepositoryName(repo.getName()); team.setTaTeam(taTeam); this.protectMasterBranch(repo, taTeam.getGithubTeam()); @@ -339,7 +339,7 @@ public class GithubManager { GHUser user = this.github.getUser(student.getGithubUsername()); this.addCollaboratorToRepo(user, assignmentsRepo); - this.addCollaboratorToRepo(user, team.getRepository()); + this.addCollaboratorToRepo(user, this.organization.getRepository(team.getRepositoryName())); } } catch (IOException e) { logger.severe("Could not add students as collaborators to assignments or their repo.\n" + team); diff --git a/src/main/java/nl/andrewlalis/model/Person.java b/src/main/java/nl/andrewlalis/model/Person.java index 10b2488..d374761 100644 --- a/src/main/java/nl/andrewlalis/model/Person.java +++ b/src/main/java/nl/andrewlalis/model/Person.java @@ -21,25 +21,25 @@ public abstract class Person extends BaseEntity implements Detailable { /** * The unique identification number for this person. (P- or S-Number) */ - @Column(name="number") + @Column(name="number", nullable = false) protected int number; /** * The person's first and last name. */ - @Column(name="name") + @Column(name="name", nullable = false) protected String name; /** * The person's email address. */ - @Column(name="email_address") + @Column(name="email_address", nullable = false) protected String emailAddress; /** * The person's github username. */ - @Column(name="github_username") + @Column(name="github_username", nullable = false) protected String githubUsername; /** diff --git a/src/main/java/nl/andrewlalis/model/StudentTeam.java b/src/main/java/nl/andrewlalis/model/StudentTeam.java index 232cd0b..c545771 100644 --- a/src/main/java/nl/andrewlalis/model/StudentTeam.java +++ b/src/main/java/nl/andrewlalis/model/StudentTeam.java @@ -1,12 +1,13 @@ package nl.andrewlalis.model; -import org.kohsuke.github.GHRepository; +import nl.andrewlalis.util.Pair; +import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.ManyToOne; import javax.persistence.Table; -import javax.persistence.Transient; import java.util.Arrays; +import java.util.List; /** * Represents one or more students' collective information. @@ -18,8 +19,8 @@ public class StudentTeam extends Team { /** * The repository belonging to this team. */ - @Transient - private GHRepository repository; + @Column(name = "repository_name", unique = true) + private String repositoryName; /** * The TATeam responsible for this student team. @@ -97,12 +98,12 @@ public class StudentTeam extends Team { return sb.toString(); } - public GHRepository getRepository() { - return this.repository; + public String getRepositoryName() { + return this.repositoryName; } - public void setRepository(GHRepository repo) { - this.repository = repo; + public void setRepositoryName(String repositoryName) { + this.repositoryName = repositoryName; } public TATeam getTaTeam() { @@ -117,4 +118,17 @@ public class StudentTeam extends Team { public String getDetailName() { return this.generateRepoDescription(); } + + @Override + public List> getDetailPairs() { + List> pairs = super.getDetailPairs(); + pairs.add(new Pair<>("Repository Name", this.getRepositoryName())); + String taTeamName = "None"; + if (this.getTaTeam() != null) { + taTeamName = this.getTaTeam().getDetailName(); + } + pairs.add(new Pair<>("TA Team", taTeamName)); + + return pairs; + } } diff --git a/src/main/java/nl/andrewlalis/ui/control/listeners/management_view/PopupSelector.java b/src/main/java/nl/andrewlalis/ui/control/listeners/management_view/PopupSelector.java new file mode 100644 index 0000000..28e5f18 --- /dev/null +++ b/src/main/java/nl/andrewlalis/ui/control/listeners/management_view/PopupSelector.java @@ -0,0 +1,42 @@ +package nl.andrewlalis.ui.control.listeners.management_view; + +import javax.swing.*; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import java.awt.*; + +/** + * This listener, when added to a JPopupMenu, will select the clicked row when a user right-clicks on the table. + */ +public class PopupSelector implements PopupMenuListener { + + /** + * The table on which to select rows. + */ + private JTable table; + + public PopupSelector(JTable table) { + this.table = table; + } + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent popupMenuEvent) { + JPopupMenu popupMenu = (JPopupMenu) popupMenuEvent.getSource(); + SwingUtilities.invokeLater(() -> { + int rowAtPoint = table.rowAtPoint(SwingUtilities.convertPoint(popupMenu, new Point(0, 0), table)); + if (rowAtPoint > -1) { + table.setRowSelectionInterval(rowAtPoint, rowAtPoint); + } + }); + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent popupMenuEvent) { + + } + + @Override + public void popupMenuCanceled(PopupMenuEvent popupMenuEvent) { + + } +} diff --git a/src/main/java/nl/andrewlalis/ui/control/listeners/management_view/TableRowListener.java b/src/main/java/nl/andrewlalis/ui/control/listeners/management_view/TableRowListener.java new file mode 100644 index 0000000..4904d5a --- /dev/null +++ b/src/main/java/nl/andrewlalis/ui/control/listeners/management_view/TableRowListener.java @@ -0,0 +1,39 @@ +package nl.andrewlalis.ui.control.listeners.management_view; + +import javax.swing.*; +import java.awt.event.ActionListener; + +/** + * This abstract class defines listeners which listen to tables, that is, a table row is clicked on in the table, and + * that is passed to children. + */ +public abstract class TableRowListener implements ActionListener { + + /** + * The table of which to get the row. + */ + private JTable table; + + /** + * Constructs a table row listener. + * @param table The table on which to get selected rows. + */ + public TableRowListener(JTable table) { + this.table = table; + } + + /** + * @return The selected row. + */ + protected final int getSelectedRow() { + return this.table.getSelectedRow(); + } + + /** + * @return The table that this listener is attached to. + */ + protected final JTable getTable() { + return this.table; + } + +} diff --git a/src/main/java/nl/andrewlalis/ui/control/listeners/management_view/student_actions/RemoveFromCourseListener.java b/src/main/java/nl/andrewlalis/ui/control/listeners/management_view/student_actions/RemoveFromCourseListener.java new file mode 100644 index 0000000..c0c9c3b --- /dev/null +++ b/src/main/java/nl/andrewlalis/ui/control/listeners/management_view/student_actions/RemoveFromCourseListener.java @@ -0,0 +1,28 @@ +package nl.andrewlalis.ui.control.listeners.management_view.student_actions; + +import nl.andrewlalis.ui.control.listeners.management_view.TableRowListener; +import nl.andrewlalis.ui.view.table_models.StudentTableModel; + +import javax.swing.*; +import java.awt.event.ActionEvent; + +/** + * Listens for when the user intends to remove a selected student from the course entirely. This entails a few things: + * 1. Remove them from any team they are in. + * 2. Archive any repository that is empty as a result of removing them. + * 3. Remove the student from the list of students. + * (This should not actually remove the record, just set it as removed.) + */ +public class RemoveFromCourseListener extends TableRowListener { + + public RemoveFromCourseListener(JTable table) { + super(table); + } + + @Override + public void actionPerformed(ActionEvent actionEvent) { + StudentTableModel model = (StudentTableModel) this.getTable().getModel(); + + System.out.println(model.getStudentAt(this.getSelectedRow())); + } +} diff --git a/src/main/java/nl/andrewlalis/ui/control/listeners/management_view/student_actions/SetTeamListener.java b/src/main/java/nl/andrewlalis/ui/control/listeners/management_view/student_actions/SetTeamListener.java new file mode 100644 index 0000000..0456f61 --- /dev/null +++ b/src/main/java/nl/andrewlalis/ui/control/listeners/management_view/student_actions/SetTeamListener.java @@ -0,0 +1,31 @@ +package nl.andrewlalis.ui.control.listeners.management_view.student_actions; + +import nl.andrewlalis.model.Student; +import nl.andrewlalis.model.StudentTeam; +import nl.andrewlalis.ui.control.listeners.management_view.TableRowListener; +import nl.andrewlalis.ui.view.dialogs.TeamChooserDialog; +import nl.andrewlalis.ui.view.table_models.StudentTableModel; + +import javax.swing.*; +import java.awt.event.ActionEvent; + +/** + * Listens for when the user wishes to set the team of a certain student. This should do the following: + * 1. User selects team to set student to, or chooses to create a new team. + * 2. StudentTeam object is created or modified. + * 3. The repository is updated automatically. + */ +public class SetTeamListener extends TableRowListener { + + public SetTeamListener(JTable table) { + super(table); + } + + @Override + public void actionPerformed(ActionEvent actionEvent) { + StudentTableModel model = (StudentTableModel) this.getTable().getModel(); + Student student = model.getStudentAt(this.getSelectedRow()); + + StudentTeam chosenTeam = (StudentTeam) new TeamChooserDialog(SwingUtilities.getWindowAncestor(this.getTable())).getSelectedTeam(); + } +} diff --git a/src/main/java/nl/andrewlalis/ui/view/AbstractView.java b/src/main/java/nl/andrewlalis/ui/view/AbstractView.java index 0d29dfe..7499af4 100644 --- a/src/main/java/nl/andrewlalis/ui/view/AbstractView.java +++ b/src/main/java/nl/andrewlalis/ui/view/AbstractView.java @@ -28,6 +28,11 @@ public abstract class AbstractView extends JFrame { */ private List parentViews; + /** + * The image icon for all abstract views. + */ + private static final ImageIcon imageIcon = new ImageIcon(AbstractView.class.getResource("/image/icon.png")); + /** * Initializes the view by packing the content pane as it is defined by any child, and setting some generic swing * values. @@ -42,6 +47,7 @@ public abstract class AbstractView extends JFrame { this.githubManager = githubManager; this.childViews = new ArrayList<>(); this.parentViews = new ArrayList<>(); + this.setIconImage(imageIcon.getImage()); this.setContentPane(this.buildContentPane()); this.setDefaultCloseOperation(defaultCloseOperation); if (preferredSize != null) { diff --git a/src/main/java/nl/andrewlalis/ui/view/ManagementView.java b/src/main/java/nl/andrewlalis/ui/view/ManagementView.java index 669a65f..5e890f1 100644 --- a/src/main/java/nl/andrewlalis/ui/view/ManagementView.java +++ b/src/main/java/nl/andrewlalis/ui/view/ManagementView.java @@ -3,6 +3,8 @@ package nl.andrewlalis.ui.view; import nl.andrewlalis.git_api.GithubManager; import nl.andrewlalis.model.database.DbHelper; import nl.andrewlalis.model.database.DbUtil; +import nl.andrewlalis.ui.control.listeners.management_view.PopupSelector; +import nl.andrewlalis.ui.control.listeners.management_view.student_actions.RemoveFromCourseListener; import nl.andrewlalis.ui.view.components.DetailPanel; import nl.andrewlalis.ui.view.table_models.StudentTableModel; import nl.andrewlalis.ui.view.table_models.StudentTeamTableModel; @@ -145,6 +147,13 @@ public class ManagementView extends AbstractView { table.getSelectionModel().addListSelectionListener(listSelectionEvent -> { detailPanel.setDetailableEntity(studentsModel.getStudentAt(table.getSelectedRow())); }); + JPopupMenu menu = new JPopupMenu("Menu"); + JMenuItem removeItem = new JMenuItem("Remove from course"); + removeItem.addActionListener(new RemoveFromCourseListener(table)); + menu.add(removeItem); + menu.addPopupMenuListener(new PopupSelector(table)); + table.setComponentPopupMenu(menu); + return this.buildGenericTablePanel(table); } diff --git a/src/main/java/nl/andrewlalis/ui/view/dialogs/TeamChooserDialog.java b/src/main/java/nl/andrewlalis/ui/view/dialogs/TeamChooserDialog.java new file mode 100644 index 0000000..3431df4 --- /dev/null +++ b/src/main/java/nl/andrewlalis/ui/view/dialogs/TeamChooserDialog.java @@ -0,0 +1,18 @@ +package nl.andrewlalis.ui.view.dialogs; + +import nl.andrewlalis.model.Team; + +import javax.swing.*; +import java.awt.*; + +public class TeamChooserDialog extends JDialog { + + public TeamChooserDialog(Window parent) { + super(parent); + } + + public Team getSelectedTeam() { + return null; + } + +} diff --git a/src/main/java/nl/andrewlalis/ui/view/table_models/StudentTeamTableModel.java b/src/main/java/nl/andrewlalis/ui/view/table_models/StudentTeamTableModel.java index c88ae14..a6300af 100644 --- a/src/main/java/nl/andrewlalis/ui/view/table_models/StudentTeamTableModel.java +++ b/src/main/java/nl/andrewlalis/ui/view/table_models/StudentTeamTableModel.java @@ -21,7 +21,7 @@ public class StudentTeamTableModel extends AbstractTableModel { * The column headers for this model. In addition to these headers, this model will dynamically create headers for * each additional student to be listed in the table. */ - private final String[] staticColumns = {"Number", "Member Count"}; + private final String[] staticColumns = {"Number", "Repository Name", "TA Team"}; /** * Dynamic columns which are generated depending on the teams. @@ -90,7 +90,9 @@ public class StudentTeamTableModel extends AbstractTableModel { case 0: return team.getId(); case 1: - return team.memberCount(); + return (team.getRepositoryName() == null) ? "None" : team.getRepositoryName(); + case 2: + return (team.getTaTeam() == null) ? "None" : team.getTaTeam().getDetailName(); default: return this.getMemberInColumn(team, i1); } @@ -135,8 +137,9 @@ public class StudentTeamTableModel extends AbstractTableModel { this.columns = new String[this.staticColumns.length + maxMembers]; this.columns[0] = this.staticColumns[0]; this.columns[1] = this.staticColumns[1]; + this.columns[2] = this.staticColumns[2]; for (int i = 0; i < maxMembers; i++) { - this.columns[i + 2] = "Member " + (i + 1); + this.columns[i + this.staticColumns.length] = "Member " + (i + 1); } } }