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