/**
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
* site: http://www.fsf.org.
*/
package org.ut.biolab.medsavant.client.project;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import com.jidesoft.pane.CollapsiblePane;
import com.jidesoft.pane.CollapsiblePanes;
import net.miginfocom.swing.MigLayout;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.ut.biolab.medsavant.MedSavantClient;
import org.ut.biolab.medsavant.client.api.Listener;
import org.ut.biolab.medsavant.client.view.login.LoginController;
import org.ut.biolab.medsavant.shared.model.ProjectDetails;
import org.ut.biolab.medsavant.client.util.ClientMiscUtils;
import org.ut.biolab.medsavant.client.util.MedSavantWorker;
import org.ut.biolab.medsavant.client.view.MedSavantFrame;
import org.ut.biolab.medsavant.client.view.list.DetailedListEditor;
import org.ut.biolab.medsavant.client.view.list.DetailedView;
import org.ut.biolab.medsavant.client.view.list.SimpleDetailedListModel;
import org.ut.biolab.medsavant.client.view.list.SplitScreenView;
import org.ut.biolab.medsavant.client.view.app.MultiSectionApp;
import org.ut.biolab.medsavant.client.view.app.AppSubSection;
import org.ut.biolab.medsavant.client.view.component.BlockingPanel;
import org.ut.biolab.medsavant.client.view.util.DialogUtils;
import org.ut.biolab.medsavant.client.view.util.StandardFixableWidthAppPanel;
import org.ut.biolab.medsavant.client.view.util.ViewUtil;
/**
*
* @author mfiume
*/
public class ProjectManagementPage extends AppSubSection {
private static final Log LOG = LogFactory.getLog(ProjectManagementPage.class);
private ProjectController controller = ProjectController.getInstance();
private SplitScreenView view;
public ProjectManagementPage(MultiSectionApp parent) {
super(parent, "Projects");
controller.addListener(new Listener<ProjectEvent>() {
@Override
public void handleEvent(ProjectEvent event) {
if (view != null) {
view.refresh();
}
}
});
}
@Override
public JPanel getView() {
if (view == null) {
view = new SplitScreenView(
new SimpleDetailedListModel<String>("Projects") {
@Override
public String[] getData() throws Exception {
return ProjectController.getInstance().getProjectNames();
}
},
new ProjectsDetailedView(),
new ProjectDetailedListEditor());
}
return view;
}
@Override
public Component[] getSubSectionMenuComponents() {
Component[] result = new Component[0];
return result;
}
private class ProjectDetailedListEditor extends DetailedListEditor {
@Override
public boolean doesImplementAdding() {
return true;
}
@Override
public boolean doesImplementDeleting() {
return true;
}
@Override
public boolean doesImplementEditing() {
return true;
}
@Override
public void addItems() {
try {
new ProjectWizard().setVisible(true);
} catch (Exception ex) {
ClientMiscUtils.reportError("Unable to launch project wizard: %s", ex);
}
}
@Override
public void editItem(Object[] items) {
try {
String projName = (String) items[0];
String sessionID = LoginController.getSessionID();
int projID = MedSavantClient.ProjectManager.getProjectID(sessionID, projName);
// Check for existing unpublished changes to this project.
if (ProjectController.getInstance().promptForUnpublished()) {
if (!MedSavantClient.SettingsManager.isProjectLockedForChanges(sessionID, ProjectController.getInstance().getCurrentProjectID())) {
ProjectWizard wiz = new ProjectWizard(projID, projName,
MedSavantClient.PatientManager.getCustomPatientFields(sessionID, projID),
MedSavantClient.ProjectManager.getProjectDetails(sessionID, projID));
wiz.setVisible(true);
} else {
DialogUtils.displayMessage("Cannot Modify Project", "This project is currently locked for changes.\nTo unlock, see the Projects page in the Administration section.");
}
}
} catch (Exception ex) {
ClientMiscUtils.reportError("Error checking for changes: %s", ex);
}
}
@Override
public void deleteItems(List<Object[]> items) {
int nameIndex = 0;
int keyIndex = 0;
int result;
if (items.size() == 1) {
String name = (String) items.get(0)[nameIndex];
result = DialogUtils.askYesNo("Confirm", "<html>Are you sure you want to remove <i>%s</i>?<br>This cannot be undone.</html>", name);
} else {
result = DialogUtils.askYesNo("Confirm", "<html>Are you sure you want to remove these %d projects?<br>This cannot be undone.</html>", items.size());
}
if (result == DialogUtils.YES) {
boolean didRequestToRemoveCurrentProject = false;
for (Object[] v : items) {
String projectName = (String) v[keyIndex];
if (projectName.equals(ProjectController.getInstance().getCurrentProjectName())) {
didRequestToRemoveCurrentProject = true;
}
controller.removeProject(projectName);
}
try {
if (didRequestToRemoveCurrentProject) {
DialogUtils.displayMessage("Successfully removed " + items.size() + " project(s).\n\n"
+ "The current project was removed.\nYou'll now be logged out.");
MedSavantFrame.getInstance().forceRestart();
} else {
DialogUtils.displayMessage("Successfully removed " + items.size() + " project(s)");
}
} catch (Exception ex) {
ClientMiscUtils.reportError("Unable to get updated project list: %s.", ex);
}
}
}
}
private class ProjectsDetailedView extends DetailedView {
private String projectName;
private DetailsWorker detailsWorker;
private JPanel details;
private final BlockingPanel blockingPanel;
private final StandardFixableWidthAppPanel canvas;
public ProjectsDetailedView() {
super(pageName);
canvas = new StandardFixableWidthAppPanel();
blockingPanel = new BlockingPanel("No project selected",canvas);
details = canvas.addBlock("Basic Information");
blockingPanel.block();
this.setLayout(new BorderLayout());
this.add(blockingPanel,BorderLayout.CENTER);
}
@Override
public void setSelectedItem(Object[] item) {
if (item.length == 0) {
blockingPanel.block();
return;
}
projectName = (String) item[0];
refreshSelectedProject();
}
private void refreshSelectedProject() {
canvas.setTitle(projectName);
details.removeAll();
details.updateUI();
if (detailsWorker != null) {
detailsWorker.cancel(true);
}
detailsWorker = new DetailsWorker(projectName);
detailsWorker.execute();
}
private class DetailsWorker extends MedSavantWorker<ProjectDetails[]> {
private String projectName;
Dimension buttonDim = new Dimension(100, 23);
public DetailsWorker(String projectName) {
super(pageName);
this.projectName = projectName;
}
@Override
protected ProjectDetails[] doInBackground() throws Exception {
int projectId = ProjectController.getInstance().getProjectID(projectName);
return MedSavantClient.ProjectManager.getProjectDetails(LoginController.getSessionID(), projectId);
}
@Override
protected void showProgress(double fraction) {
//
}
@Override
protected void showSuccess(ProjectDetails[] result) {
setDetailsList(result);
}
}
private synchronized void setDetailsList(ProjectDetails[] projectDetails) {
details.removeAll();
ViewUtil.setBoxYLayout(details);
String[][] values = new String[projectDetails.length][2];
for (int i = 0; i < projectDetails.length; i++) {
values[i][0] = projectDetails[i].getReferenceName();
values[i][1] = projectDetails[i].getNumAnnotations() + " annotation(s) applied";
}
details.add(ViewUtil.getKeyValuePairList(values));
int projectID = projectDetails[0].getProjectID();
if (projectID == ProjectController.getInstance().getCurrentProjectID()) {
JPanel p = ViewUtil.getClearPanel();
ViewUtil.applyHorizontalBoxLayout(p);
p.add(ViewUtil.getGrayItalicizedLabel("This is the current project."));
p.add(Box.createHorizontalGlue());
details.add(Box.createVerticalStrut(10));
details.add(p);
}
String sessionID = LoginController.getSessionID();
try {
if (MedSavantClient.SettingsManager.isProjectLockedForChanges(sessionID, projectID)) {
JPanel p = ViewUtil.getClearPanel();
ViewUtil.applyHorizontalBoxLayout(p);
p.add(ViewUtil.getGrayItalicizedLabel("This project is locked. Administrators cannot make further changes."));
JButton b = new JButton("Unlock");
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
try {
int result = DialogUtils.askYesNo("Warning", "Unlocking the database while another administrator is making changes can\n"
+ "cause permanent damage. Only unlock if you are sure no one is in the process of\n"
+ "making changes. Are you sure you want to proceed?");
if (result == DialogUtils.YES) {
MedSavantClient.SettingsManager.forceReleaseLockForProject(LoginController.getSessionID(), ProjectController.getInstance().getCurrentProjectID());
refreshSelectedProject();
}
} catch (Exception ex) {
LOG.error(ex);
}
}
});
JButton refreshButton = ViewUtil.getRefreshButton();
p.add(b);
p.add(Box.createHorizontalGlue());
details.add(Box.createVerticalStrut(10));
details.add(p);
} else {
JPanel p = ViewUtil.getClearPanel();
ViewUtil.applyHorizontalBoxLayout(p);
p.add(ViewUtil.alignLeft(ViewUtil.getGrayItalicizedLabel("This project is unlocked. Administrators can make changes.")));
details.add(Box.createVerticalStrut(10));
details.add(p);
}
} catch (Exception ex) {
}
details.updateUI();
blockingPanel.unblock();
}
@Override
public void setMultipleSelections(List<Object[]> items) {
if (items.isEmpty()) {
canvas.setTitle("");
} else {
canvas.setTitle("Multiple projects (" + items.size() + ")");
}
details.removeAll();
details.updateUI();
blockingPanel.unblock();
}
}
}