diff --git a/src/main/java/nl/andrewlalis/Main.java b/src/main/java/nl/andrewlalis/Main.java index faac15d..834af58 100644 --- a/src/main/java/nl/andrewlalis/Main.java +++ b/src/main/java/nl/andrewlalis/Main.java @@ -4,6 +4,7 @@ import nl.andrewlalis.command.CommandExecutor; import nl.andrewlalis.command.executables.*; import nl.andrewlalis.git_api.GithubManager; import nl.andrewlalis.ui.view.InitializerApp; +import nl.andrewlalis.ui.view.ManagementView; import nl.andrewlalis.ui.view.StartView; import nl.andrewlalis.util.CommandLine; import nl.andrewlalis.util.Logging; @@ -18,6 +19,11 @@ public class Main { private static final Logger logger = Logger.getGlobal(); + /** + * The main application's view, which should be able to be referenced in many places. + */ + private static ManagementView managementView; + public static void main(String[] args) { // Parsed command line arguments. @@ -50,7 +56,7 @@ public class Main { "Program initialized."); GithubManager manager = new GithubManager(); - StartView startView = new StartView(manager, "InitializerTesting", userOptions.get("token")); + managementView = new ManagementView(manager); // SessionFactory factory = DbUtil.getSessionFactory(); // Session session = factory.openSession(); @@ -58,6 +64,15 @@ public class Main { // System.out.println(session.save(new Student(1, "a", "a@e.com", "git", null))); // session.getTransaction().commit(); // session.close(); + + StartView startView = new StartView(manager, "InitializerTesting", userOptions.get("token")); + } + + /** + * @return The management view used for the application. + */ + public static ManagementView getManagementView() { + return managementView; } } diff --git a/src/main/java/nl/andrewlalis/model/Student.java b/src/main/java/nl/andrewlalis/model/Student.java index f68df82..dbf9360 100644 --- a/src/main/java/nl/andrewlalis/model/Student.java +++ b/src/main/java/nl/andrewlalis/model/Student.java @@ -28,6 +28,13 @@ public class Student extends Person { ) private List preferredPartners; + /** + * The team that this student is assigned to. + */ + @ManyToOne + @JoinColumn(name = "team_id") + private StudentTeam team; + /** * Constructs an empty student object. */ @@ -73,4 +80,19 @@ public class Student extends Person { t.addMember(this); return t; } + + /** + * Assigns this student to the given team, from the student's perspective. + * @param team The team to set as the assigned team. + */ + public void assignToTeam(StudentTeam team) { + this.team = team; + } + + /** + * @return The team that this student is assigned to. May return null if the student is unassigned. + */ + public StudentTeam getAssignedTeam() { + return this.team; + } } diff --git a/src/main/java/nl/andrewlalis/model/database/DbHelper.java b/src/main/java/nl/andrewlalis/model/database/DbHelper.java new file mode 100644 index 0000000..fde57e2 --- /dev/null +++ b/src/main/java/nl/andrewlalis/model/database/DbHelper.java @@ -0,0 +1,26 @@ +package nl.andrewlalis.model.database; + +import nl.andrewlalis.model.Student; +import org.hibernate.Session; +import org.hibernate.SessionFactory; + +import java.util.List; + +/** + * This class will contain some static methods to help in the retrieval of commonly used information. + */ +public class DbHelper { + + /** + * Gets a list of students in the database. + * @return A list of students. + */ + public static List getStudents() { + SessionFactory sessionFactory = DbUtil.getSessionFactory(); + Session session = sessionFactory.openSession(); + List students = (List) session.createQuery("from Student").list(); + session.close(); + return students; + } + +} diff --git a/src/main/java/nl/andrewlalis/ui/control/listeners/input_students_file_view/DoneListener.java b/src/main/java/nl/andrewlalis/ui/control/listeners/input_students_file_view/DoneListener.java new file mode 100644 index 0000000..f98c11f --- /dev/null +++ b/src/main/java/nl/andrewlalis/ui/control/listeners/input_students_file_view/DoneListener.java @@ -0,0 +1,15 @@ +package nl.andrewlalis.ui.control.listeners.input_students_file_view; + +import nl.andrewlalis.ui.control.listeners.ViewChangeListener; +import nl.andrewlalis.ui.view.AbstractView; + +/** + * Listens for when the user clicks 'Done' after selecting a file to input. + */ +public class DoneListener extends ViewChangeListener { + + public DoneListener(AbstractView previousView, AbstractView newView) { + super(previousView, newView); + } + +} diff --git a/src/main/java/nl/andrewlalis/ui/control/listeners/input_students_file_view/FileSelectListener.java b/src/main/java/nl/andrewlalis/ui/control/listeners/input_students_file_view/FileSelectListener.java index 664fe44..afc053b 100644 --- a/src/main/java/nl/andrewlalis/ui/control/listeners/input_students_file_view/FileSelectListener.java +++ b/src/main/java/nl/andrewlalis/ui/control/listeners/input_students_file_view/FileSelectListener.java @@ -1,8 +1,13 @@ package nl.andrewlalis.ui.control.listeners.input_students_file_view; +import nl.andrewlalis.Main; +import nl.andrewlalis.model.Student; import nl.andrewlalis.model.StudentTeam; +import nl.andrewlalis.model.database.DbUtil; import nl.andrewlalis.ui.view.InputStudentsFileView; import nl.andrewlalis.util.TeamGenerator; +import org.hibernate.Session; +import org.hibernate.Transaction; import javax.swing.*; import javax.swing.filechooser.FileFilter; @@ -54,7 +59,20 @@ public class FileSelectListener implements ActionListener { int teamSize = this.fileView.getStudentsPerTeam(); try { List teams = TeamGenerator.generateFromCSV(chooser.getSelectedFile().getAbsolutePath(), teamSize); - System.out.println(teams); + Session session = DbUtil.getSessionFactory().openSession(); + Transaction tx = session.beginTransaction(); + + for (StudentTeam team : teams) { + for (Student s : team.getStudents()) { + session.save(s); + } + session.save(team); + } + + tx.commit(); + session.close(); + + Main.getManagementView().updateModels(); } catch (IOException e) { e.printStackTrace(); } diff --git a/src/main/java/nl/andrewlalis/ui/view/AbstractView.java b/src/main/java/nl/andrewlalis/ui/view/AbstractView.java index 5480cc1..0d29dfe 100644 --- a/src/main/java/nl/andrewlalis/ui/view/AbstractView.java +++ b/src/main/java/nl/andrewlalis/ui/view/AbstractView.java @@ -23,6 +23,11 @@ public abstract class AbstractView extends JFrame { */ private List childViews; + /** + * A list of views which lead to this one. + */ + private List parentViews; + /** * Initializes the view by packing the content pane as it is defined by any child, and setting some generic swing * values. @@ -30,11 +35,13 @@ public abstract class AbstractView extends JFrame { * @param startVisible Whether or not to start the view as visible. * @param defaultCloseOperation What to do when the user closes the window. * @param preferredSize The preferred size of the view. + * @param githubManager The manager used for this view. */ AbstractView(String title, boolean startVisible, int defaultCloseOperation, Dimension preferredSize, GithubManager githubManager) { super(title); this.githubManager = githubManager; this.childViews = new ArrayList<>(); + this.parentViews = new ArrayList<>(); this.setContentPane(this.buildContentPane()); this.setDefaultCloseOperation(defaultCloseOperation); if (preferredSize != null) { @@ -95,4 +102,33 @@ public abstract class AbstractView extends JFrame { protected final void addChildView(AbstractView view) { this.childViews.add(view); } + + /** + * @return The list of children of this view. + */ + protected final List getChildViews() { + return this.childViews; + } + + /** + * Adds a view as linked to this one as a parent. + * @param view The parent view. + */ + protected final void addParentView(AbstractView view) { + this.parentViews.add(view); + } + + /** + * @return The list of parents of this view. + */ + protected final List getParentViews() { + return this.parentViews; + } + + /** + * Removes all parents registered to this view. + */ + protected final void removeParents() { + this.parentViews.clear(); + } } diff --git a/src/main/java/nl/andrewlalis/ui/view/CreateAssignmentsView.java b/src/main/java/nl/andrewlalis/ui/view/CreateAssignmentsView.java index 22d5418..a85880e 100644 --- a/src/main/java/nl/andrewlalis/ui/view/CreateAssignmentsView.java +++ b/src/main/java/nl/andrewlalis/ui/view/CreateAssignmentsView.java @@ -44,6 +44,7 @@ public class CreateAssignmentsView extends AbstractView { JButton nextButton = new JButton("Next"); InputStudentsFileView inputStudentsFileView = new InputStudentsFileView(this.getGithubManager()); this.addChildView(inputStudentsFileView); + inputStudentsFileView.addParentView(this); nextButton.addActionListener(new NextListener(this, inputStudentsFileView)); contentPane.add(nextButton, BorderLayout.SOUTH); diff --git a/src/main/java/nl/andrewlalis/ui/view/InputStudentsFileView.java b/src/main/java/nl/andrewlalis/ui/view/InputStudentsFileView.java index 10a77b6..18324c6 100644 --- a/src/main/java/nl/andrewlalis/ui/view/InputStudentsFileView.java +++ b/src/main/java/nl/andrewlalis/ui/view/InputStudentsFileView.java @@ -1,6 +1,8 @@ package nl.andrewlalis.ui.view; +import nl.andrewlalis.Main; import nl.andrewlalis.git_api.GithubManager; +import nl.andrewlalis.ui.control.listeners.input_students_file_view.DoneListener; import nl.andrewlalis.ui.control.listeners.input_students_file_view.FileSelectListener; import javax.swing.*; @@ -34,7 +36,7 @@ public class InputStudentsFileView extends AbstractView { JPanel inputPanel = new JPanel(); inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.PAGE_AXIS)); - + // Button to select a file. JButton selectFileButton = new JButton("Select File"); this.studentsPerTeamField = new JTextField("2"); inputPanel.add(this.generateTextFieldPanel("How many students per team?", this.studentsPerTeamField)); @@ -43,7 +45,10 @@ public class InputStudentsFileView extends AbstractView { contentPane.add(inputPanel, BorderLayout.CENTER); + // Button to confirm and move to the next view. JButton doneButton = new JButton("Done"); + Main.getManagementView().addParentView(this); + doneButton.addActionListener(new DoneListener(this, Main.getManagementView())); contentPane.add(doneButton, BorderLayout.SOUTH); return contentPane; diff --git a/src/main/java/nl/andrewlalis/ui/view/ManagementView.java b/src/main/java/nl/andrewlalis/ui/view/ManagementView.java new file mode 100644 index 0000000..e0462a8 --- /dev/null +++ b/src/main/java/nl/andrewlalis/ui/view/ManagementView.java @@ -0,0 +1,114 @@ +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.view.table_models.StudentTableModel; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * The view in which the user manages a course. + */ +public class ManagementView extends AbstractView { + + /** + * The model for the students table. + */ + private StudentTableModel studentsModel; + + public ManagementView(GithubManager githubManager) { + super( + "Course Management", + false, + DISPOSE_ON_CLOSE, + null, + githubManager + ); + this.setExtendedState(this.getExtendedState() | JFrame.MAXIMIZED_BOTH); + + // Dispose of all parents when this window closes. + this.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent windowEvent) { + for (AbstractView parent : getParentViews()) { + parent.dispose(); + } + DbUtil.tearDown(); + } + }); + } + + @Override + protected JPanel buildContentPane() { + JPanel contentPane = new JPanel(new BorderLayout()); + + contentPane.add(this.buildCommandPanel(), BorderLayout.WEST); + contentPane.add(this.buildDetailPanel(), BorderLayout.EAST); + contentPane.add(this.buildOverviewPanel(), BorderLayout.CENTER); + + return contentPane; + } + + /** + * @return A JPanel for the command prompt interface. + */ + private JPanel buildCommandPanel() { + JPanel commandPanel = new JPanel(new BorderLayout()); + + commandPanel.add(new JLabel("Commands", SwingConstants.CENTER), BorderLayout.NORTH); + commandPanel.add(new JTextArea("Command prompt area goes here."), BorderLayout.CENTER); + + // Construct the sub-panel for commands at the bottom of the panel. + JPanel inputPanel = new JPanel(new BorderLayout()); + JTextField commandTextField = new JTextField(); + inputPanel.add(commandTextField, BorderLayout.CENTER); + + commandPanel.add(inputPanel, BorderLayout.SOUTH); + + return commandPanel; + } + + /** + * @return A JPanel for the entity details section. + */ + private JPanel buildDetailPanel() { + JPanel detailPanel = new JPanel(new BorderLayout()); + + detailPanel.add(new JLabel("Details", SwingConstants.CENTER), BorderLayout.NORTH); + + return detailPanel; + } + + /** + * @return Builds the overview panel, containing a listing of entities. + */ + private JPanel buildOverviewPanel() { + JPanel overviewPanel = new JPanel(new BorderLayout()); + + overviewPanel.add(new JLabel("Overview"), BorderLayout.NORTH); + + // The real container for all the data views. + JTabbedPane tabbedPane = new JTabbedPane(); + + this.studentsModel = new StudentTableModel(DbHelper.getStudents()); + JTable studentsTable = new JTable(this.studentsModel); + JScrollPane studentsScrollPane = new JScrollPane(studentsTable); + tabbedPane.addTab("Students", studentsScrollPane); + + overviewPanel.add(tabbedPane, BorderLayout.CENTER); + + return overviewPanel; + } + + /** + * Updates all models in the management view in accordance with the database. + */ + public void updateModels() { + this.studentsModel.setStudentsList(DbHelper.getStudents()); + + } +} diff --git a/src/main/java/nl/andrewlalis/ui/view/StartView.java b/src/main/java/nl/andrewlalis/ui/view/StartView.java index c53ebc8..a90efc1 100644 --- a/src/main/java/nl/andrewlalis/ui/view/StartView.java +++ b/src/main/java/nl/andrewlalis/ui/view/StartView.java @@ -1,6 +1,8 @@ package nl.andrewlalis.ui.view; +import nl.andrewlalis.Main; import nl.andrewlalis.git_api.GithubManager; +import nl.andrewlalis.ui.control.listeners.ViewChangeListener; import nl.andrewlalis.ui.control.listeners.start_view.CreateAssignmentsRepoListener; import javax.swing.*; @@ -61,11 +63,18 @@ public class StartView extends AbstractView { infoInputPanel.add(this.generateTextFieldPanel("Access token:", this.accessTokenField)); JPanel buttonsPanel = new JPanel(); + // Create the button for going to the Create assignments repository view. JButton assignmentsViewButton = new JButton("Start New Course"); CreateAssignmentsView assignmentsView = new CreateAssignmentsView(this.getGithubManager()); this.addChildView(assignmentsView); + assignmentsView.addParentView(this); assignmentsViewButton.addActionListener(new CreateAssignmentsRepoListener(this, assignmentsView)); + + // Create the button for going straight to the management view. JButton managementViewButton = new JButton("Manage Existing Course"); + this.addChildView(Main.getManagementView()); + Main.getManagementView().addParentView(this); + managementViewButton.addActionListener(new ViewChangeListener(this, Main.getManagementView())); buttonsPanel.add(assignmentsViewButton); buttonsPanel.add(managementViewButton); diff --git a/src/main/java/nl/andrewlalis/ui/view/table_models/StudentTableModel.java b/src/main/java/nl/andrewlalis/ui/view/table_models/StudentTableModel.java new file mode 100644 index 0000000..03fb2a3 --- /dev/null +++ b/src/main/java/nl/andrewlalis/ui/view/table_models/StudentTableModel.java @@ -0,0 +1,74 @@ +package nl.andrewlalis.ui.view.table_models; + +import nl.andrewlalis.model.Student; + +import javax.swing.table.AbstractTableModel; +import java.util.List; + +/** + * This table model is used for the representation of a list of persons, with their basic information. + */ +public class StudentTableModel extends AbstractTableModel { + + /** + * The list of data that is used in the table. + */ + private List studentsList; + + /** + * A default list of column headers for this table. + */ + private String[] columns = {"Number", "Name", "Email", "Github", "Team"}; + + /** + * Constructs a new model based on the given list of students. + * @param studentsList A list of students to display in the table model. + */ + public StudentTableModel(List studentsList) { + this.studentsList = studentsList; + } + + /** + * Sets a new list of students as the data for this list model. + * @param newList The new list of students to use. + */ + public void setStudentsList(List newList) { + this.studentsList = newList; + this.fireTableDataChanged(); + } + + @Override + public int getRowCount() { + return studentsList.size(); + } + + @Override + public int getColumnCount() { + return this.columns.length; + } + + @Override + public String getColumnName(int i) { + return this.columns[i]; + } + + @Override + public Object getValueAt(int row, int col) { + Student student = studentsList.get(row); + + switch(col) { + case 0: + return student.getNumber(); + case 1: + return student.getName(); + case 2: + return student.getEmailAddress(); + case 3: + return student.getGithubUsername(); + case 4: + return student.getAssignedTeam().getId(); + default: + return null; + } + } +} diff --git a/src/main/java/nl/andrewlalis/util/TeamGenerator.java b/src/main/java/nl/andrewlalis/util/TeamGenerator.java index aa7b426..15f6fe9 100644 --- a/src/main/java/nl/andrewlalis/util/TeamGenerator.java +++ b/src/main/java/nl/andrewlalis/util/TeamGenerator.java @@ -98,7 +98,7 @@ public class TeamGenerator { // Once we know this team is completely valid, we remove all the students in it from the list of singles. newTeam.setNumber(teamCount++); singleStudents.removeAll(Arrays.asList(newTeam.getStudents())); - studentTeams.add(newTeam); + assignStudentsToTeam(newTeam); logger.fine("Created team:\n" + newTeam); } } @@ -128,6 +128,7 @@ public class TeamGenerator { t.addMember(s); } studentTeams.add(t); + assignStudentsToTeam(t); logger.fine("Created team:\n" + t); } return studentTeams; @@ -187,4 +188,15 @@ public class TeamGenerator { return students; } + /** + * Assigns all students in the given team to that team, such that all students then have a reference to the team + * they are in. + * @param team The team to assign students for. + */ + private static void assignStudentsToTeam(StudentTeam team) { + for (Student student : team.getStudents()) { + student.assignToTeam(team); + } + } + }