Newer
Older
marking / src / main / java / ui / MarkingFrame.java
package ui;

import dao.MarkingProperties;
import dao.ResultDAO;
import jakarta.mail.AuthenticationFailedException;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.ConnectException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import model.Criterion;
import model.Student;
import model.Submission;
import report.FeedbackReportGenerator;
import report.SendReport;

/**
 *
 * @author Mark George <mark.george@otago.ac.nz>
 */
public class MarkingFrame extends JDialog {

	private Student student;
	private Submission submission;

	private final JPanel schedulePane;
	private final ResultDAO resultDao = new ResultDAO();

	private final JLabel lblStudent;
	private final JLabel lblAssessment;
	private final SubmissionFrame parent;
	private final String assessment;
	private final JCheckBox cbExpandable;
	
	private boolean isComplete = false;

	@SuppressWarnings("Convert2Lambda")
	public MarkingFrame(SubmissionFrame parent, String assessment) {
		this.setModal(true);
		this.parent = parent;

		this.assessment = assessment;

		// add scroll pane to the root
		JScrollPane scrollPane = new JScrollPane();
		JPanel contentPane = new JPanel();
		JPanel titlePane = new JPanel();
		cbExpandable = new JCheckBox("Expand Text Areas?", false);

		scrollPane.setViewportView(contentPane);
		scrollPane.getVerticalScrollBar().setUnitIncrement(16);

		getContentPane().add(titlePane, java.awt.BorderLayout.NORTH);
		getContentPane().add(scrollPane, java.awt.BorderLayout.CENTER);

		titlePane.setLayout(new BorderLayout());
		lblStudent = new JLabel("Student");
		Font newFont = lblStudent.getFont().deriveFont(Font.BOLD, 15);
		lblStudent.setFont(newFont);
		lblAssessment = new JLabel("Assessment");
		lblAssessment.setFont(newFont);

		titlePane.add(BorderLayout.WEST, lblStudent);
		titlePane.add(BorderLayout.EAST, lblAssessment);

		// add other panes
		schedulePane = new JPanel();
		JPanel buttonPane = new JPanel();

		contentPane.setLayout(new BorderLayout());
		contentPane.add(schedulePane, BorderLayout.CENTER);
		contentPane.add(buttonPane, BorderLayout.SOUTH);

		schedulePane.setLayout(new BoxLayout(schedulePane, BoxLayout.Y_AXIS));

		// add buttons
		JButton btnSave = new JButton("Save");
		btnSave.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent ae) {
				save();
			}
		});

		// add buttons
		JButton btnCancel = new JButton("Cancel");
		btnCancel.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent ae) {
				dispose();
			}
		});

		JButton btnMin = new JButton("Min");
		btnMin.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent ae) {
				min();
			}
		});

		JButton btnMax = new JButton("Max");
		btnMax.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent ae) {
				max();
			}
		});

		JButton btnEmail = new JButton("Save & Email");
		btnEmail.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent ae) {
				saveAndEmail();
			}
		});

		buttonPane.add(btnMin);
		buttonPane.add(btnMax);
		buttonPane.add(btnCancel);

		if (MarkingProperties.isEmailEnabled()) {
			buttonPane.add(btnEmail);
		}

		buttonPane.add(btnSave);
		buttonPane.add(cbExpandable);

	}

	public void addCategory(String category, List<Criterion> criteria) {
		schedulePane.add(new CategoryPanel(category, criteria));
	}

	private void save() {

		if (!resultDao.isComplete()) {
			this.isComplete = false;
			int res = JOptionPane.showConfirmDialog(MarkingFrame.this, "You haven't entered values for all criteria.  Are you sure you want save?", "Incomplete", JOptionPane.OK_CANCEL_OPTION);
			if (JOptionPane.OK_OPTION == res) {
				resultDao.save(student.getSubmissionId());
				parent.refresh();
				dispose();
			}
		} else {
			this.isComplete = true;
			resultDao.save(submission.getSubmissionId());
			parent.refresh();
			Collection<Map<String, ?>> result = resultDao.getResult(submission.getSubmissionId());
			if (result.isEmpty()) {
				// marking is incomplete, so don't try to show a mark
				dispose();
				return;
			}

			Map<String, ?> mark = result.iterator().next();

			JOptionPane.showMessageDialog(this, "Mark:    " + mark.get("MARK") + "\n" + "Bonus:  " + mark.get("SPECIAL"));
			dispose();
		}
	}

	private void min() {
		Component[] components = schedulePane.getComponents();
		for (Component component : components) {
			if (component instanceof CategoryPanel) {
				CategoryPanel cp = (CategoryPanel) component;
				Component[] categories = cp.getComponents();
				for (Component criterion : categories) {
					if (criterion instanceof CriterionPanel) {
						CriterionPanel c = (CriterionPanel) criterion;
						c.setZero();
					}
				}
			}
		}
	}

	private void max() {
		Component[] components = schedulePane.getComponents();
		for (Component component : components) {
			if (component instanceof CategoryPanel) {
				CategoryPanel cp = (CategoryPanel) component;
				Component[] categories = cp.getComponents();
				for (Component criterion : categories) {
					if (criterion instanceof CriterionPanel) {
						CriterionPanel c = (CriterionPanel) criterion;
						if (c.getCriterion().isNormal()) {
							c.setMax();
						} else {
							c.setZero();
						}
					}
				}
			}
		}
	}

	public void load(String submissionId) {
		submission = new ResultDAO().findSubmission(submissionId);

		lblStudent.setText(submissionId + " (" + submission.getName()+")");
		lblAssessment.setText(assessment);
		resultDao.load(submissionId);
	}

	public void display() {
		this.setPreferredSize(new Dimension(600, 980));
		this.pack();
		this.setVisible(true);
	}

	public void createReport() {
		try {
			new FeedbackReportGenerator(new ResultDAO().getResult(student.getId()), MarkingProperties.reportPath(), MarkingProperties.attachmentFilePrefix(), MarkingProperties.reportTitle(), MarkingProperties.reportFooter()).generate(student);
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	}

	public void emailReport() {

		String report = MarkingProperties.reportPath() + "/" + MarkingProperties.attachmentFilePrefix() + "-" + student.getId() + ".pdf";

		try {
			new SendReport(this).sendReport(student, report, false);
			JOptionPane.showMessageDialog(this, "Email sent.");
		} catch (AuthenticationFailedException ex) {
			setVisible(true);
		} catch (ConnectException ex) {
			// ignored
		}
	}

	@SuppressWarnings("Convert2Lambda")
	private void saveAndEmail() {
		save();

		// only send email if the marking is complete
		if (isComplete) {

			CompletableFuture.runAsync(() -> {
				createReport();
				emailReport();
			});

		}

	}

	public boolean getExpandable() {
		return this.cbExpandable.isSelected();
	}

}