Coverage Report - org.kuali.student.lum.program.client.major.view.MajorViewController
 
Classes in this File Line Coverage Branch Coverage Complexity
MajorViewController
0%
0/87
0%
0/24
2.273
MajorViewController$1
0%
0/7
0%
0/4
2.273
MajorViewController$10
0%
0/4
0%
0/2
2.273
MajorViewController$2
0%
0/3
N/A
2.273
MajorViewController$3
0%
0/12
0%
0/4
2.273
MajorViewController$4
0%
0/8
0%
0/4
2.273
MajorViewController$5
0%
0/3
N/A
2.273
MajorViewController$6
0%
0/5
0%
0/2
2.273
MajorViewController$7
0%
0/4
0%
0/2
2.273
MajorViewController$8
0%
0/12
0%
0/8
2.273
MajorViewController$9
0%
0/6
0%
0/2
2.273
MajorViewController$9$1
0%
0/5
0%
0/2
2.273
 
 1  
 package org.kuali.student.lum.program.client.major.view;
 2  
 
 3  
 
 4  
 
 5  
 import org.kuali.student.common.assembly.data.Data;
 6  
 import org.kuali.student.common.assembly.data.Data.Property;
 7  
 import org.kuali.student.common.ui.client.application.Application;
 8  
 import org.kuali.student.common.ui.client.application.KSAsyncCallback;
 9  
 import org.kuali.student.common.ui.client.application.ViewContext;
 10  
 import org.kuali.student.common.ui.client.mvc.Callback;
 11  
 import org.kuali.student.common.ui.client.mvc.DataModel;
 12  
 import org.kuali.student.common.ui.client.mvc.history.HistoryManager;
 13  
 import org.kuali.student.common.ui.client.security.SecurityContext;
 14  
 import org.kuali.student.common.ui.client.widgets.KSButton;
 15  
 import org.kuali.student.common.ui.client.widgets.KSCheckBox;
 16  
 import org.kuali.student.common.ui.client.widgets.KSLabel;
 17  
 import org.kuali.student.common.ui.client.widgets.KSLightBox;
 18  
 import org.kuali.student.common.ui.client.widgets.KSRadioButton;
 19  
 import org.kuali.student.common.ui.shared.IdAttributes;
 20  
 import org.kuali.student.common.ui.shared.IdAttributes.IdType;
 21  
 import org.kuali.student.lum.common.client.widgets.AppLocations;
 22  
 import org.kuali.student.lum.common.client.widgets.DropdownList;
 23  
 import org.kuali.student.lum.program.client.ProgramConstants;
 24  
 import org.kuali.student.lum.program.client.ProgramRegistry;
 25  
 import org.kuali.student.lum.program.client.ProgramSections;
 26  
 import org.kuali.student.lum.program.client.ProgramStatus;
 27  
 import org.kuali.student.lum.program.client.events.ModelLoadedEvent;
 28  
 import org.kuali.student.lum.program.client.events.ProgramViewEvent;
 29  
 import org.kuali.student.lum.program.client.major.ActionType;
 30  
 import org.kuali.student.lum.program.client.major.MajorController;
 31  
 
 32  
 import com.google.gwt.core.client.GWT;
 33  
 import com.google.gwt.event.dom.client.ChangeEvent;
 34  
 import com.google.gwt.event.dom.client.ChangeHandler;
 35  
 import com.google.gwt.event.dom.client.ClickEvent;
 36  
 import com.google.gwt.event.dom.client.ClickHandler;
 37  
 import com.google.gwt.event.logical.shared.ValueChangeEvent;
 38  
 import com.google.gwt.event.logical.shared.ValueChangeHandler;
 39  
 import com.google.gwt.event.shared.HandlerManager;
 40  
 import com.google.gwt.user.client.ui.Anchor;
 41  
 import com.google.gwt.user.client.ui.HorizontalPanel;
 42  
 import com.google.gwt.user.client.ui.VerticalPanel;
 43  
 
 44  
 
 45  0
 public class MajorViewController extends MajorController {
 46  
 
 47  
     // TODO: Change to program and copy msgs
 48  
     private static final String MSG_GROUP = "program";
 49  
     
 50  
     /**
 51  
      * Initialize the action drop-down with a list of values.  Note that these values
 52  
      * will be changed further down in the code depending on if we are working with the latest 
 53  
      * version of the program.
 54  
      */
 55  0
     private final DropdownList actionBox = new DropdownList(ActionType.getValuesForMajorDiscipline(false));
 56  
  
 57  
     // Used to pass flag if this is the latest version of the program from
 58  
     // an async call to the light box so we can conditionally decided
 59  
     // to display the use curriculum review process checkbox
 60  
     private boolean isCurrentVersion;
 61  
     
 62  
     /**
 63  
      * Constructor.
 64  
      *
 65  
      * @param programModel
 66  
      */
 67  
     public MajorViewController(DataModel programModel, ViewContext viewContext, HandlerManager eventBus) {
 68  0
         super(programModel, viewContext, eventBus);
 69  0
         configurer = GWT.create(MajorViewConfigurer.class);  
 70  
         
 71  
         // Initialize handlers and action drop-down
 72  0
         initHandlers();
 73  0
      }
 74  
  
 75  
     private void initHandlers() {
 76  
         
 77  
         /*
 78  
          * Action drop-down box on-change
 79  
          */
 80  0
         actionBox.addChangeHandler(new ChangeHandler() {
 81  
             @Override
 82  
             public void onChange(ChangeEvent event) {
 83  
                 
 84  
                 // Get the action selected in the drop-down
 85  0
                 ActionType actionType = ActionType.of(actionBox.getSelectedValue());
 86  0
                 ViewContext viewContext = getViewContext();
 87  
                 
 88  
                 // If modify is selected
 89  0
                 if (actionType == ActionType.MODIFY) {
 90  0
                     processModifyActionType(viewContext);
 91  
                 }
 92  
                 // If retire is selected
 93  0
                 else if (actionType == ActionType.RETIRE) {
 94  
                     // TODO: retire is not implemented yet for program
 95  
                 }
 96  0
             }
 97  
         });
 98  
         /*
 99  
          * Initial value selected in action drop-down
 100  
          */
 101  0
         eventBus.addHandler(ProgramViewEvent.TYPE, new ProgramViewEvent.Handler() {
 102  
             @Override
 103  
             public void onEvent(ProgramViewEvent event) {
 104  0
                 actionBox.setSelectedIndex(0);
 105  0
             }
 106  
         });
 107  
         
 108  
         /* 
 109  
          * Code executed right after model is loaded from service
 110  
          */
 111  0
         eventBus.addHandler(ModelLoadedEvent.TYPE, new ModelLoadedEvent.Handler() {
 112  
             @Override
 113  
             public void onEvent(ModelLoadedEvent event) {
 114  
                 
 115  
                 /*
 116  
                  * Reload values in the drop-down if the data model changes
 117  
                  * since we may have loaded a different version
 118  
                  */
 119  0
                 resetActionList();
 120  
                  
 121  0
                 String type = context.getAttributes().get(ProgramConstants.TYPE);
 122  0
                 if (type != null) {
 123  0
                     context.getAttributes().remove(ProgramConstants.TYPE);
 124  0
                     if (type.equals(ProgramConstants.VARIATION_TYPE_KEY)) {
 125  0
                         showVariationView();
 126  
                     } else {
 127  
                             //Take out the vairationId if it exists for cleaner navigation
 128  0
                             context.getAttributes().remove(ProgramConstants.VARIATION_ID);
 129  0
                         showView(ProgramSections.VIEW_ALL);
 130  
                     }
 131  
                 } else {
 132  0
                         context.getAttributes().remove(ProgramConstants.VARIATION_ID);
 133  0
                     showView(ProgramSections.VIEW_ALL);
 134  
                 }
 135  0
             }
 136  
         });
 137  0
     }
 138  
 
 139  
     /**
 140  
      * 
 141  
      * This method process the modify a program action that was selected. A permission
 142  
      * check is done to see if the modify program lightbox shoudl be presented to the
 143  
      * user.
 144  
      * 
 145  
      * The modify programl lightbox is only shown to the admin role.
 146  
      * 
 147  
      * @param viewContext
 148  
      */
 149  
     private void processModifyActionType(final ViewContext viewContext) {
 150  0
             SecurityContext securityContext = Application.getApplicationContext().getSecurityContext(); 
 151  
             
 152  0
             securityContext.checkPermission("useCurriculumReview", new Callback<Boolean>() {
 153  
             @Override
 154  
             public void exec(Boolean result) {
 155  0
                 final boolean isAuthorized = result;
 156  
 
 157  
                 // Show the modify program light box only for admin role.
 158  0
                 if (isAuthorized) {
 159  0
                     buildModifyDialog(viewContext, "/HOME/CURRICULUM_HOME/COURSE_PROPOSAL", programModel);
 160  
                 } else {
 161  0
                     if (isProgramStatusValidForProposal()) {
 162  0
                         showModifyProgramWithNewVersionCurriculumReviewView();
 163  
                     } else {
 164  0
                         showModifyProgramWithoutVersionView(viewContext);
 165  
                     }
 166  
                 }
 167  0
             }
 168  
         });
 169  0
     }
 170  
 
 171  
     /**
 172  
      * 
 173  
      * This method builds the light box that appears when you choose to modify a program.
 174  
      * 
 175  
      * @param viewContext
 176  
      * @param modifyPath
 177  
      * @param model
 178  
      */
 179  
     private void buildModifyDialog(final ViewContext viewContext, final String modifyPath, final DataModel model){
 180  0
         final KSLightBox modifyDialog = new KSLightBox();
 181  
         
 182  
         //Create a dialog for course selection
 183  0
         modifyDialog.setTitle((getMessage("modifyProgramSubTitle")));
 184  
 
 185  0
         final VerticalPanel layout = new VerticalPanel();
 186  0
         layout.addStyleName("ks-form-module-fields");
 187  
                 
 188  0
         final KSButton continueButton = new KSButton(getMessage("continue"));
 189  
         
 190  0
         modifyDialog.addButton(continueButton);
 191  0
         Anchor cancelLink = new Anchor("Cancel");
 192  
        
 193  
         // Cancel should just close the dialog
 194  0
         cancelLink.addClickHandler(new ClickHandler(){
 195  
             public void onClick(ClickEvent event) {
 196  0
                 modifyDialog.hide();
 197  0
             }
 198  
         });
 199  0
         modifyDialog.addButton(cancelLink);
 200  
         
 201  
         //HorizontalPanel titlePanel = new HorizontalPanel();
 202  0
         KSLabel titleLabel = new KSLabel(getMessage("modifyProgramSubTitle"));
 203  0
         titleLabel.addStyleName("bold");
 204  0
         modifyDialog.setNonCaptionHeader(titleLabel);
 205  
         //titlePanel.add(titleLabel);
 206  
         
 207  
         //layout.add(titlePanel);
 208  
         
 209  0
         final KSRadioButton radioOptionModifyNoVersion = new KSRadioButton("modifyCreditProgramButtonGroup", getMessage("modifyProgramNoVersion"));
 210  0
         final KSRadioButton radioOptionModifyWithVersion = new KSRadioButton("modifyCreditProgramButtonGroup", getMessage("modifyProgramWithVersion"));
 211  0
         final KSCheckBox curriculumReviewOption = new KSCheckBox(getMessage("useCurriculumReview"));
 212  
         
 213  
         
 214  0
         radioOptionModifyNoVersion.addValueChangeHandler(new ValueChangeHandler<Boolean>(){
 215  
             public void onValueChange(ValueChangeEvent<Boolean> event) {
 216  0
                 if(event.getValue()){
 217  0
                     curriculumReviewOption.setEnabled(false);
 218  0
                     curriculumReviewOption.setValue(false);
 219  
                 }
 220  0
             }
 221  
         });
 222  0
         radioOptionModifyNoVersion.setValue(true);
 223  
         
 224  
 
 225  0
         curriculumReviewOption.setEnabled(false);
 226  
         
 227  0
         radioOptionModifyWithVersion.addValueChangeHandler(new ValueChangeHandler<Boolean>(){
 228  
             public void onValueChange(ValueChangeEvent<Boolean> event) {
 229  0
                 if(event.getValue()){
 230  0
                     curriculumReviewOption.setEnabled(true);
 231  
                 }
 232  0
             }
 233  
         });
 234  
         
 235  
         /*
 236  
          * Continue button clicked.
 237  
          */
 238  0
         continueButton.addClickHandler(new ClickHandler(){
 239  
             @Override
 240  
             public void onClick(ClickEvent event) {
 241  0
                  if (radioOptionModifyNoVersion.getValue()){
 242  
                     // If modify w/out version radio button is chosen 
 243  
                     // we just edit the program.  We do not create a copy.
 244  
                     // We navigate to the edit program controller
 245  0
                      showModifyProgramWithoutVersionView(viewContext);
 246  0
                  } else if (radioOptionModifyWithVersion.getValue() && curriculumReviewOption.getValue()){
 247  
                     // If the curriculum review option IS checked and the modify with version radio button IS selected
 248  
                     // We need to create a copy of the program (by passing in COPY_OF_OBJECT_ID)
 249  
                     // and then transfer control to the proposal controller (the proposal controller has
 250  
                     // extra section for entering proposal related data
 251  0
                     showModifyProgramWithNewVersionCurriculumReviewView();
 252  0
                  } else if (radioOptionModifyWithVersion.getValue()){
 253  
                     // If we are just choosing to modify a program but want to create a new version
 254  
                     // AND we are not using the proposal process
 255  
                     // We make a copy of the data model and transfer control
 256  
                     // to the edit program screen
 257  
                      
 258  
                      // Pass the ID and the type to the proposal controller
 259  
                      // using the view context.  We then read it in the
 260  
                      // setViewContext method and use it to initialize the
 261  
                      // work flow utilities
 262  
     
 263  0
                      String versionIndId = getStringProperty(ProgramConstants.VERSION_IND_ID);
 264  0
                      viewContext.setId(versionIndId);
 265  0
                      viewContext.setIdType(IdType.COPY_OF_OBJECT_ID);
 266  
           
 267  
                      //ProgramRegistry.setSection(ProgramSections.getEditSection(getCurrentViewEnum()));
 268  0
                      HistoryManager.navigate(AppLocations.Locations.EDIT_PROGRAM.getLocation(), viewContext);
 269  
                 }   
 270  
                 
 271  
                 // Hide dialog after clicking
 272  0
                 modifyDialog.hide();
 273  0
             }           
 274  
         });
 275  
         
 276  
         //Check that this is the latest version with an async call and only show modify with version options if it is the latest
 277  
        
 278  0
         layout.add(radioOptionModifyNoVersion);
 279  
  
 280  
         // the curriculum review check box implements "modify by proposal"
 281  
         // a user can only check the box when the program state is active, retired, or approved (it must be the latest version when in these states)
 282  
         // See https://wiki.kuali.org/display/KULSTG/Course%2C+Proposal%2C+and+Program+Action+Dropdown+Items
 283  0
         if (isProgramStatusValidForProposal()) {
 284  0
             layout.add(radioOptionModifyWithVersion);
 285  0
             layout.add(curriculumReviewOption);
 286  
         }
 287  
         
 288  0
         modifyDialog.setWidget(layout);
 289  0
         modifyDialog.show();
 290  0
     } 
 291  
  
 292  
     /**
 293  
      * 
 294  
      * This method checks if the program state is active, retired, or approved (it must be
 295  
      * the latest version when in these states)
 296  
      * 
 297  
      * @return
 298  
      */
 299  
     private boolean isProgramStatusValidForProposal() {
 300  0
         ProgramStatus status = ProgramStatus.of(programModel);
 301  
 
 302  0
         if (isCurrentVersion
 303  
                 && (status == ProgramStatus.ACTIVE || status == ProgramStatus.APPROVED || status == ProgramStatus.ACTIVE)) {
 304  0
             return true;
 305  
         }
 306  
 
 307  0
         return false;
 308  
     }
 309  
     
 310  
     /**
 311  
      * 
 312  
      * This method will grab a message based on a key.
 313  
      * 
 314  
      * @param courseMessageKey
 315  
      * @return
 316  
      */
 317  
     public String getMessage(String programMessageKey) {
 318  0
         String msg = Application.getApplicationContext().getMessage(MSG_GROUP, programMessageKey);
 319  0
         if (msg == null) {
 320  0
             msg = programMessageKey;
 321  
         }
 322  0
         return msg;
 323  
     }   
 324  
     
 325  
     /**
 326  
      * 
 327  
      * This method will set the values in the action list drop-down.
 328  
      *
 329  
      */
 330  
     protected void resetActionList() {
 331  
             
 332  
         // Get the current state of the program (SUPERSEDED, ACTIVE, APPROVED, DRAFT)
 333  0
             ProgramStatus status = ProgramStatus.of(programModel);
 334  
             
 335  
             // Get the version independent indicator
 336  0
         String versionIndId = getStringProperty(ProgramConstants.VERSION_IND_ID);
 337  
         
 338  
         // The the version sequence number
 339  0
         Long sequenceNumber = programModel.get(ProgramConstants.VERSION_SEQUENCE_NUMBER);
 340  
                
 341  
         // Clear the drop-down list and prepare to populate it with values
 342  0
         actionBox.clear();
 343  
   
 344  
         // Call the server to see if this is the latest version of the program
 345  
         // and update the drop-down accordingly
 346  0
             programRemoteService.isLatestVersion(versionIndId, sequenceNumber, new KSAsyncCallback<Boolean>(){
 347  
                         public void onSuccess(Boolean isLatest) {
 348  
                          
 349  
                             // TODO PLEASE REVIEW.  Should we be passing values from async calls to light boxes
 350  
                             // using instance variables like this? (we are doing this in course as well)
 351  0
                             isCurrentVersion = isLatest;
 352  
                             
 353  
                             // Populate the action box drop-down with different values depending 
 354  
                             // on if we are working with the latest version of the program 
 355  
                             // or a historical version
 356  0
                 actionBox.setList(ActionType.getValuesForMajorDiscipline(isLatest));
 357  
 
 358  0
                 if (!isCurrentVersion) {
 359  0
                     Application.getApplicationContext().getSecurityContext().checkPermission("useCurriculumReview", new Callback<Boolean>() {
 360  
                         @Override
 361  
                         public void exec(Boolean result) {
 362  0
                             final boolean isAuthorized = result;
 363  
 
 364  0
                             if (!isAuthorized) {
 365  0
                                 actionBox.removeItem(ActionType.MODIFY.getValue());
 366  
                             }
 367  0
                         }
 368  
                     });
 369  
                 }
 370  
 
 371  0
                          }                
 372  
         });
 373  
             
 374  
            
 375  
             // Get the reference ID of the proposal from the XML model
 376  
             // Note: the filter puts in in the model, see ProposalWorkflowFilter.applyOutboundDataFilter
 377  0
             String referenceId = programModel.getRoot().get("id");
 378  
             
 379  
             // When the program being viewed is in DRAFT state, check to see if it exists as part of program proposal instead of admin modify. 
 380  
             // If its part of a program proposal then we don't want to display the program actions drop down since user is not allowed to take
 381  
             // any actions on a DRAFT program proposal outside of proposal process.
 382  
             // TODO PLEASE REVIEW.  If this async call runs slow, will the box remain visible? Is this an issue?
 383  
             //      Answer: Yes, it might be an issue, possible solution might to block user action w/progress bar until finished.            
 384  0
         if (status == ProgramStatus.DRAFT){
 385  0
                     programRemoteService.isProposal( "kuali.proposal.referenceType.clu", referenceId,  new KSAsyncCallback<Boolean>(){
 386  
                     public void onSuccess(Boolean isProposal) {
 387  
                      
 388  
                         // If this is a proposal then we cannot take any actions on it
 389  
                         // So hide the action box
 390  0
                         if (isProposal){
 391  0
                             actionBox.setVisible(false);
 392  
                         }
 393  
                       
 394  0
                     }           
 395  
                 });
 396  
         }
 397  0
     } 
 398  
   
 399  
     private void showVariationView() {
 400  0
         String variationId = context.getAttributes().get(ProgramConstants.VARIATION_ID);
 401  0
         if (variationId != null) {
 402  0
             final Data variationMap = getDataProperty(ProgramConstants.VARIATIONS);
 403  0
             if (variationMap != null) {
 404  0
                 int row = 0;
 405  0
                 for (Property p : variationMap) {
 406  0
                     final Data variationData = p.getValue();
 407  0
                     if (variationData != null) {
 408  0
                         if (variationData.get(ProgramConstants.ID).equals(variationId)) {
 409  
                             //FIXME: Find a better way to do this.
 410  
                             // We shouldn't be maintaining two separate datamodels for progs and variations
 411  0
                             Data credData = getDataProperty(ProgramConstants.CREDENTIAL_PROGRAM);
 412  0
                             variationData.set(ProgramConstants.CREDENTIAL_PROGRAM, credData);
 413  0
                             ProgramRegistry.setData(variationData);
 414  0
                             ProgramRegistry.setRow(row);
 415  
                         }
 416  0
                         row++;
 417  
                     }
 418  0
                 }
 419  0
                 HistoryManager.navigate(AppLocations.Locations.VIEW_VARIATION.getLocation(), context);
 420  
             }
 421  
         }
 422  0
     }
 423  
 
 424  
     @Override
 425  
     protected void configureView() {
 426  0
         super.configureView();
 427  0
         addContentWidget(actionBox);
 428  0
         initialized = true;
 429  0
     }
 430  
 
 431  
     /**
 432  
      * 
 433  
      * This method navigates to the edit program controller.
 434  
      * 
 435  
      * @param viewContext
 436  
      */
 437  
     private void showModifyProgramWithoutVersionView(final ViewContext viewContext) {
 438  0
         ProgramRegistry.setSection(ProgramSections.getEditSection(getCurrentViewEnum()));
 439  0
          HistoryManager.navigate(AppLocations.Locations.EDIT_PROGRAM.getLocation(), viewContext);
 440  0
     }
 441  
 
 442  
     /**
 443  
      * 
 444  
      * This method transfers control to the proposal controller.
 445  
      * 
 446  
      */
 447  
     private void showModifyProgramWithNewVersionCurriculumReviewView() {
 448  0
         String versionIndId = getStringProperty(ProgramConstants.VERSION_IND_ID);
 449  
  
 450  
         // Pass the ID and the type to the proposal controller
 451  
         // using the view context.  We then read it in the
 452  
         // setViewContext method and use it to initialize the
 453  
         // work flow utilities
 454  0
         final ViewContext viewContext = new ViewContext();
 455  0
         viewContext.setId(versionIndId);
 456  0
         viewContext.setIdType(IdAttributes.IdType.COPY_OF_OBJECT_ID); 
 457  0
         Application.navigate(AppLocations.Locations.PROGRAM_PROPOSAL.getLocation(), viewContext);
 458  0
     }
 459  
 }