Coverage Report - org.kuali.student.lum.lu.ui.course.client.widgets.CourseWorkflowActionList
 
Classes in this File Line Coverage Branch Coverage Complexity
CourseWorkflowActionList
0%
0/182
0%
0/58
1.917
CourseWorkflowActionList$1
0%
0/3
N/A
1.917
CourseWorkflowActionList$10
0%
0/4
0%
0/2
1.917
CourseWorkflowActionList$11
0%
0/9
0%
0/4
1.917
CourseWorkflowActionList$12
0%
0/3
N/A
1.917
CourseWorkflowActionList$13
0%
0/9
0%
0/4
1.917
CourseWorkflowActionList$14
0%
0/15
0%
0/6
1.917
CourseWorkflowActionList$15
0%
0/5
N/A
1.917
CourseWorkflowActionList$16
0%
0/10
0%
0/2
1.917
CourseWorkflowActionList$17
0%
0/6
N/A
1.917
CourseWorkflowActionList$18
0%
0/9
0%
0/4
1.917
CourseWorkflowActionList$19
0%
0/6
0%
0/2
1.917
CourseWorkflowActionList$2
0%
0/7
0%
0/2
1.917
CourseWorkflowActionList$20
0%
0/6
0%
0/2
1.917
CourseWorkflowActionList$3
0%
0/3
N/A
1.917
CourseWorkflowActionList$4
0%
0/2
N/A
1.917
CourseWorkflowActionList$5
0%
0/7
0%
0/2
1.917
CourseWorkflowActionList$6
0%
0/4
N/A
1.917
CourseWorkflowActionList$7
0%
0/3
N/A
1.917
CourseWorkflowActionList$8
0%
0/3
N/A
1.917
CourseWorkflowActionList$9
0%
0/5
0%
0/2
1.917
 
 1  
 package org.kuali.student.lum.lu.ui.course.client.widgets;
 2  
 
 3  
 import java.util.ArrayList;
 4  
 import java.util.List;
 5  
 
 6  
 import org.kuali.student.common.assembly.data.QueryPath;
 7  
 import org.kuali.student.common.dto.DtoConstants;
 8  
 import org.kuali.student.common.dto.StatusInfo;
 9  
 import org.kuali.student.common.rice.StudentIdentityConstants;
 10  
 import org.kuali.student.common.ui.client.application.Application;
 11  
 import org.kuali.student.common.ui.client.application.KSAsyncCallback;
 12  
 import org.kuali.student.common.ui.client.application.ViewContext;
 13  
 import org.kuali.student.common.ui.client.configurable.mvc.SectionTitle;
 14  
 import org.kuali.student.common.ui.client.configurable.mvc.sections.VerticalSection;
 15  
 import org.kuali.student.common.ui.client.mvc.Callback;
 16  
 import org.kuali.student.common.ui.client.mvc.DataModel;
 17  
 import org.kuali.student.common.ui.client.mvc.history.HistoryManager;
 18  
 import org.kuali.student.common.ui.client.widgets.KSButton;
 19  
 import org.kuali.student.common.ui.client.widgets.KSCheckBox;
 20  
 import org.kuali.student.common.ui.client.widgets.KSLabel;
 21  
 import org.kuali.student.common.ui.client.widgets.KSLightBox;
 22  
 import org.kuali.student.common.ui.client.widgets.KSRadioButton;
 23  
 import org.kuali.student.common.ui.client.widgets.StylishDropDown;
 24  
 import org.kuali.student.common.ui.client.widgets.KSButtonAbstract.ButtonStyle;
 25  
 import org.kuali.student.common.ui.client.widgets.menus.KSMenuItemData;
 26  
 import org.kuali.student.common.ui.client.widgets.notification.KSNotification;
 27  
 import org.kuali.student.common.ui.client.widgets.notification.KSNotifier;
 28  
 import org.kuali.student.common.ui.client.widgets.progress.BlockingTask;
 29  
 import org.kuali.student.common.ui.client.widgets.progress.KSBlockingProgressIndicator;
 30  
 import org.kuali.student.common.ui.shared.IdAttributes.IdType;
 31  
 import org.kuali.student.lum.common.client.widgets.AppLocations;
 32  
 import org.kuali.student.lum.lu.LUConstants;
 33  
 import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseConstants;
 34  
 import org.kuali.student.lum.lu.ui.course.client.service.CourseRpcService;
 35  
 import org.kuali.student.lum.lu.ui.course.client.service.CourseRpcServiceAsync;
 36  
 
 37  
 import com.google.gwt.core.client.GWT;
 38  
 import com.google.gwt.event.dom.client.ClickEvent;
 39  
 import com.google.gwt.event.dom.client.ClickHandler;
 40  
 import com.google.gwt.event.logical.shared.ValueChangeEvent;
 41  
 import com.google.gwt.event.logical.shared.ValueChangeHandler;
 42  
 import com.google.gwt.user.client.Window;
 43  
 import com.google.gwt.user.client.rpc.AsyncCallback;
 44  
 import com.google.gwt.user.client.ui.Anchor;
 45  
 import com.google.gwt.user.client.ui.FlowPanel;
 46  
 import com.google.gwt.user.client.ui.HorizontalPanel;
 47  
 import com.google.gwt.user.client.ui.VerticalPanel;
 48  
 import com.google.gwt.user.client.ui.Widget;
 49  
 
 50  0
 public class CourseWorkflowActionList extends StylishDropDown {
 51  
     private static final String MSG_GROUP = "course";
 52  
     
 53  0
         private static final BlockingTask processingTask = new BlockingTask("Processing State Change....");
 54  0
         private static final CourseRpcServiceAsync courseServiceAsync = GWT.create(CourseRpcService.class);    
 55  
 
 56  
     private KSMenuItemData modifyCourseActionItem;
 57  
         private KSMenuItemData activateCourseActionItem;
 58  
         private KSMenuItemData inactivateCourseActionItem;
 59  
         private KSMenuItemData retireCourseActionItem;
 60  
         private KSMenuItemData copyCourseActionItem;
 61  
         // private KSMenuItemData retireProposalCourseActionItem;
 62  
         
 63  0
         private final KSLightBox activateDialog = new KSLightBox();
 64  0
         private VerticalSection activateSection = new VerticalSection();
 65  
     
 66  
     private boolean isCurrentVersion;
 67  0
     private Boolean isInitialized = false;
 68  
     private String courseId;
 69  
     
 70  0
     private boolean hasAdminAccess = false;
 71  
        
 72  
     
 73  
     // Storing this list at multiple layers: here and in StylishDropDown.menu.items.  We need it here to test for empty
 74  0
     private final List<KSMenuItemData> items = new ArrayList<KSMenuItemData>();
 75  
     
 76  
     public CourseWorkflowActionList(String label) {
 77  0
             super(label);
 78  
             
 79  0
             this.setVisible(false);
 80  0
         this.addStyleName("KS-Workflow-DropDown");
 81  
             
 82  0
     }
 83  
 
 84  
         public CourseWorkflowActionList(String label, final ViewContext viewContext, final String modifyPath, DataModel model, final Callback<String> stateChangeCallback) {
 85  0
             super(label);
 86  
         
 87  0
             this.setVisible(false);
 88  0
         this.addStyleName("KS-Workflow-DropDown");
 89  
         
 90  0
         init(viewContext, modifyPath, model, stateChangeCallback);
 91  0
         }
 92  
         
 93  
         public void init (final ViewContext viewContext, final String modifyPath, final DataModel model, final Callback<String> stateChangeCallback) {
 94  
 
 95  0
                 if (!this.isInitialized) {
 96  0
                     buildActivateDialog(stateChangeCallback);
 97  
                     
 98  0
                     this.isCurrentVersion = true;
 99  
                     
 100  
                     // TODO: use messages
 101  0
                    modifyCourseActionItem = new KSMenuItemData(this.getMessage("cluModifyItem"), new ClickHandler(){
 102  
         
 103  
                                 @Override
 104  
                                 public void onClick(ClickEvent event) {
 105  
                                         
 106  0
                                         setupModifyCourseDialog(viewContext, modifyPath, model);
 107  0
                                 }
 108  
                         });
 109  
             
 110  0
                     copyCourseActionItem = new KSMenuItemData(this.getMessage("cluCopyItem"), new ClickHandler(){
 111  
                                 @Override
 112  
                                 public void onClick(ClickEvent event) {
 113  0
                                     if(hasCourseId(viewContext)){
 114  0
                                             viewContext.setId((String)model.get(CreditCourseConstants.ID));
 115  0
                                                 viewContext.setIdType(IdType.COPY_OF_OBJECT_ID);
 116  0
                                                 viewContext.getAttributes().remove(StudentIdentityConstants.DOCUMENT_TYPE_NAME);
 117  
                                 }
 118  0
                                         HistoryManager.navigate(modifyPath, viewContext);
 119  0
                                 }
 120  
                         });
 121  
 
 122  
                     // This is likely not being used anymore, as we no longer have an approved state
 123  
                     // so this should be removed at some point.
 124  0
                     activateCourseActionItem = new KSMenuItemData(this.getMessage("cluActivateItem"), new ClickHandler(){
 125  
         
 126  
                                 @Override
 127  
                                 public void onClick(ClickEvent event) {
 128  0
                                         showStateDialog(DtoConstants.STATE_ACTIVE);
 129  0
                                 }
 130  
                         });
 131  
                     
 132  0
                     inactivateCourseActionItem = new KSMenuItemData(this.getMessage("cluInactivateItem") + " (Not Yet Implemented)", new ClickHandler(){
 133  
         
 134  
                                 @Override
 135  
                                 public void onClick(ClickEvent event) {
 136  
                                                 // TODO: Inactivate
 137  0
                                 }
 138  
                         });
 139  
         
 140  0
                     retireCourseActionItem = new KSMenuItemData(this.getMessage("cluRetireItem"), new ClickHandler(){
 141  
         
 142  
                                 @Override
 143  
                                 public void onClick(ClickEvent event) {
 144  0
                                     if(hasCourseId(viewContext)){
 145  0
                                                 viewContext.setId((String)model.get(CreditCourseConstants.ID));
 146  0
                                                 viewContext.setIdType(IdType.COPY_OF_OBJECT_ID);
 147  0
                                                 viewContext.getAttributes().remove(StudentIdentityConstants.DOCUMENT_TYPE_NAME);
 148  
                                                                                         
 149  
                                 }
 150  
                                     // KSCM-983 setup lightbox for Admins to pick proper retire screen
 151  
                                     // non admins will automatically goto course_retire_by_proposoal
 152  0
                                     setupRetireCourseDialog(viewContext, AppLocations.Locations.COURSE_RETIRE_BY_PROPOSAL.getLocation(), model);
 153  
 
 154  0
                                 }
 155  
                         });        
 156  
                 }
 157  
                 
 158  0
                 this.isInitialized = true;
 159  0
     }
 160  
     
 161  
     private void doModifyActionItem(ViewContext viewContext, String modifyPath, DataModel model){
 162  0
             if(hasCourseId(viewContext)){
 163  0
                         viewContext.setId(getCourseVersionIndId(model));
 164  0
                         viewContext.setIdType(IdType.COPY_OF_OBJECT_ID);
 165  0
             viewContext.setAttribute(StudentIdentityConstants.DOCUMENT_TYPE_NAME, LUConstants.PROPOSAL_TYPE_COURSE_MODIFY);
 166  
         }
 167  
 
 168  0
                 HistoryManager.navigate(modifyPath, viewContext);
 169  0
     }
 170  
    
 171  
     private void doRetireActionItem(ViewContext viewContext, String retirePath, DataModel model){
 172  0
             if(hasCourseId(viewContext)){
 173  0
                         viewContext.setId((String)model.get(CreditCourseConstants.ID));
 174  0
                         viewContext.setIdType(IdType.COPY_OF_OBJECT_ID);
 175  0
             viewContext.setAttribute(StudentIdentityConstants.DOCUMENT_TYPE_NAME, LUConstants.PROPOSAL_TYPE_COURSE_RETIRE);
 176  
         }
 177  
 
 178  0
                 HistoryManager.navigate(retirePath, viewContext);
 179  0
     }
 180  
    
 181  
         
 182  
     
 183  
         private void showStateDialog(String newState) {
 184  0
             if (newState.equals(DtoConstants.STATE_RETIRED)) {
 185  
                     // TODO: create Retire dialog
 186  0
             } else if (newState.equals(DtoConstants.STATE_ACTIVE)) {                     
 187  
                     // TODO: use message e.g. activateCurrentInstr, activateModificationInstr                    
 188  0
                     activateSection.setInstructions(getInstructions(newState));                                    
 189  0
                 activateDialog.show();
 190  0
             } else if (newState.equals(DtoConstants.STATE_SUSPENDED)) {
 191  
                     // TODO: create Inactivate dialog
 192  
             }
 193  
             
 194  0
     }
 195  
         
 196  
     private String getInstructions(String newState) {            
 197  0
             if (isCurrentVersion){
 198  
                     // TODO: message
 199  0
                     return "Activating this course makes it viewable and available for scheduling.";
 200  
             } else { 
 201  
                     // TODO: message
 202  0
                     return "Activate this course makes it viewable and available for scheduling. The previous version will be inactivated, and available for reference in the version history.";
 203  
             }
 204  
     }
 205  
     
 206  
     private void buildActivateDialog(final Callback<String> stateChangeCallback){
 207  0
             FlowPanel panel = new FlowPanel();
 208  
             
 209  0
             activateDialog.setMaxHeight(200);
 210  0
             activateDialog.setMaxWidth(200);
 211  
             
 212  
             // TODO: use messages
 213  0
             activateSection = new VerticalSection(SectionTitle.generateH2Title("Activate Course"));
 214  
             
 215  0
         panel.add((Widget)activateSection);
 216  
             
 217  0
             KSButton activate = new KSButton("Activate",new ClickHandler(){
 218  
             public void onClick(ClickEvent event) {
 219  
                 //activateSection.updateModel(cluModel);
 220  
                 //set previous active to superseded
 221  
                 //set this version to active
 222  0
                 setCourseState(courseId, DtoConstants.STATE_ACTIVE, stateChangeCallback);
 223  0
                 activateDialog.hide();                
 224  0
             }
 225  
             });
 226  0
             activateDialog.addButton(activate);
 227  
             
 228  0
             KSButton cancel = new KSButton("Cancel", ButtonStyle.ANCHOR_LARGE_CENTERED, new ClickHandler(){
 229  
             public void onClick(ClickEvent event) {
 230  0
                 activateDialog.hide();
 231  0
             }
 232  
             });
 233  0
             activateDialog.addButton(cancel);
 234  
 
 235  0
             activateDialog.setWidget(panel);
 236  0
     }
 237  
     
 238  
     private void buildModifyDialog(final ViewContext viewContext, final String modifyPath, final DataModel model){
 239  0
             final KSLightBox modifyDialog = new KSLightBox();
 240  
             
 241  
             //Create a dialog for course selection
 242  0
             modifyDialog.setTitle((getMessage("modifyCourse")));
 243  
 
 244  0
         final VerticalPanel layout = new VerticalPanel();
 245  0
         layout.addStyleName("ks-form-module-fields");
 246  
                 
 247  0
         final KSButton continueButton = new KSButton(getMessage("continue"));
 248  
         
 249  0
         modifyDialog.addButton(continueButton);
 250  0
         Anchor cancelLink = new Anchor("Cancel");
 251  0
         cancelLink.addClickHandler(new ClickHandler(){
 252  
                         public void onClick(ClickEvent event) {
 253  0
                                 modifyDialog.hide();
 254  0
                         }
 255  
         });
 256  0
         modifyDialog.addButton(cancelLink);
 257  
         
 258  0
         HorizontalPanel titlePanel = new HorizontalPanel();
 259  0
         KSLabel titleLabel = new KSLabel(getMessage("modifyCourseSubTitle"));
 260  0
         titleLabel.addStyleName("bold");
 261  0
         titlePanel.add(titleLabel);
 262  
         
 263  0
         layout.add(titlePanel);
 264  
         
 265  0
         final KSRadioButton radioOptionModifyNoVersion = new KSRadioButton("modifyCreditCourseButtonGroup", getMessage("modifyCourseNoVersion"));
 266  0
         final KSRadioButton radioOptionModifyWithVersion = new KSRadioButton("modifyCreditCourseButtonGroup", getMessage("modifyCourseWithVersion"));
 267  0
         final KSCheckBox curriculumReviewOption = new KSCheckBox(getMessage("useCurriculumReview"));
 268  
         
 269  0
         radioOptionModifyNoVersion.addValueChangeHandler(new ValueChangeHandler<Boolean>(){
 270  
                         public void onValueChange(ValueChangeEvent<Boolean> event) {
 271  0
                                 if(event.getValue()){
 272  0
                             curriculumReviewOption.setEnabled(false);
 273  0
                             curriculumReviewOption.setValue(false);
 274  
                                 }
 275  0
                         }
 276  
         });
 277  0
         radioOptionModifyNoVersion.setValue(true);
 278  0
             curriculumReviewOption.setEnabled(false);
 279  
         
 280  0
         radioOptionModifyWithVersion.addValueChangeHandler(new ValueChangeHandler<Boolean>(){
 281  
                         public void onValueChange(ValueChangeEvent<Boolean> event) {
 282  0
                                 if(event.getValue()){
 283  0
                             curriculumReviewOption.setEnabled(true);
 284  
                                 }
 285  0
                         }
 286  
         });
 287  
         
 288  0
         continueButton.addClickHandler(new ClickHandler(){
 289  
                         @Override
 290  
                         public void onClick(ClickEvent event) {
 291  0
                                 if (radioOptionModifyNoVersion.getValue()){
 292  0
                                         viewContext.setId(courseId);
 293  0
                                         viewContext.setIdType(IdType.OBJECT_ID);
 294  0
                                         Application.navigate(AppLocations.Locations.COURSE_ADMIN_NO_VERSION.getLocation(), viewContext);
 295  0
                                 } else if (radioOptionModifyWithVersion.getValue()){
 296  0
                                     checkLatestVersion(viewContext, modifyPath, model, curriculumReviewOption.getValue());                            
 297  
                                     
 298  
                                 }
 299  0
                             modifyDialog.hide();
 300  0
                         }                
 301  
         });
 302  
         
 303  
         //Check that this is the latest version with an async call and only show modify with version options if it is the latest
 304  
        
 305  0
         layout.add(radioOptionModifyNoVersion);
 306  0
         if(isCurrentVersion){
 307  0
                 layout.add(radioOptionModifyWithVersion);
 308  0
             layout.add(curriculumReviewOption);
 309  
         }
 310  0
         modifyDialog.setWidget(layout);
 311  0
         modifyDialog.show();
 312  0
     }
 313  
     /**
 314  
      * Build Admin Retire Choice Widget
 315  
      *       
 316  
      * @param viewContext
 317  
      * @param retirePath
 318  
      * @param model
 319  
      */
 320  
     private void buildRetireDialog(final ViewContext viewContext, final String retirePath, final DataModel model){
 321  0
             final KSLightBox retireDialog = new KSLightBox((getMessage("retireCourseWidgetTitle")), KSLightBox.Size.SMALL);
 322  
                
 323  0
             retireDialog.setTitle((getMessage("retireCourse")));
 324  
 
 325  0
         final VerticalPanel layout = new VerticalPanel();
 326  0
         layout.addStyleName("ks-form-module-fields");
 327  
                 
 328  0
         final KSButton continueButton = new KSButton(getMessage("continue"));
 329  
         
 330  0
         retireDialog.addButton(continueButton);
 331  0
         Anchor cancelLink = new Anchor("Cancel");
 332  0
         cancelLink.addClickHandler(new ClickHandler(){
 333  
                         public void onClick(ClickEvent event) {
 334  0
                                 retireDialog.hide();
 335  0
                         }
 336  
         });
 337  0
         retireDialog.addButton(cancelLink);
 338  
         
 339  0
         HorizontalPanel titlePanel = new HorizontalPanel();
 340  0
         KSLabel titleLabel = new KSLabel(getMessage("retireCourseSubTitle"));
 341  0
         titleLabel.addStyleName("bold");
 342  0
         titlePanel.add(titleLabel);
 343  0
         layout.add(titlePanel);
 344  
         
 345  0
         final KSRadioButton radioOptionAdminRetire = new KSRadioButton("retireCourseButtonGroup", getMessage("retireCourseAdmin"));
 346  0
         final KSRadioButton radioOptionRetireByProposal = new KSRadioButton("retireCourseButtonGroup", getMessage("retireCourseByProposal"));
 347  
     
 348  
 
 349  0
         radioOptionAdminRetire.setValue(true);
 350  
    
 351  0
         continueButton.addClickHandler(new ClickHandler(){
 352  
                         @Override
 353  
                         public void onClick(ClickEvent event) {
 354  0
                                 if (radioOptionAdminRetire.getValue()){
 355  0
                                         viewContext.setId((String)model.get(CreditCourseConstants.ID));
 356  0
                                         viewContext.setIdType(IdType.OBJECT_ID);
 357  0
                                         Application.navigate(AppLocations.Locations.COURSE_RETIRE.getLocation(), viewContext);
 358  0
                                 } else if (radioOptionRetireByProposal.getValue()){
 359  0
                                          checkLatestVersionRetire(viewContext, retirePath, model);                                                                                                                
 360  
                                 }
 361  0
                             retireDialog.hide();
 362  0
                         }                
 363  
         });
 364  
               
 365  0
         if(isCurrentVersion){
 366  0
         layout.add(radioOptionAdminRetire);
 367  0
             layout.add(radioOptionRetireByProposal);
 368  
         }
 369  
         
 370  
         
 371  0
         retireDialog.setWidget(layout);
 372  0
         retireDialog.show();
 373  0
     }
 374  
     
 375  
     
 376  
     /**
 377  
      * Do a latest version check, if successful, call the modify action else display an error message that the current
 378  
      * version of the selected course is under modification. 
 379  
      * 
 380  
      * @param viewContext
 381  
      * @param modifyPath
 382  
      * @param model
 383  
      * @param reviewOption
 384  
      */
 385  
     private void checkLatestVersion(final ViewContext viewContext, final String modifyPath, final DataModel model, final boolean reviewOption){
 386  0
         String courseVerIndId = getCourseVersionIndId(model);
 387  0
         Long courseVersionSequence = getCourseVersionSequenceNumber(model);
 388  
     
 389  0
         courseServiceAsync.isLatestVersion(courseVerIndId, courseVersionSequence, new AsyncCallback<Boolean>(){
 390  
         
 391  
             public void onFailure(Throwable caught) {
 392  0
                 KSNotifier.add(new KSNotification("Error determining latest version of course", false, 5000));
 393  0
             }
 394  
         
 395  
             public void onSuccess(Boolean result) {
 396  0
                 if (result){
 397  0
                     if (reviewOption){
 398  0
                         doModifyActionItem(viewContext, modifyPath, model);
 399  
                     } else {
 400  0
                         if(hasCourseId(viewContext)){
 401  0
                             viewContext.setId(getCourseVersionIndId(model));
 402  0
                             viewContext.setIdType(IdType.COPY_OF_OBJECT_ID);
 403  
                             // FIXME: This needs to use a new workflow document type for admin modify with version
 404  0
                             viewContext.setAttribute(StudentIdentityConstants.DOCUMENT_TYPE_NAME, LUConstants.PROPOSAL_TYPE_COURSE_MODIFY_ADMIN);
 405  
                         }
 406  
 
 407  0
                         Application.navigate(AppLocations.Locations.COURSE_ADMIN.getLocation(), viewContext);
 408  
                     }
 409  
                 } else {
 410  0
                     isCurrentVersion = false;
 411  0
                     doUpdateCourseActionItems(model);
 412  0
                     KSNotifier.add(new KSNotification("Error creating new version for course, this course is currently under modification.", false, 5000));
 413  
                 }
 414  0
             }
 415  
         });
 416  0
     }
 417  
     
 418  
     
 419  
     /**
 420  
      * Do a latest version check, if successful, call the modify action else display an error message that the current
 421  
      * version of the selected course is under modification. 
 422  
      * 
 423  
      * @param viewContext
 424  
      * @param modifyPath
 425  
      * @param model
 426  
      * @param reviewOption
 427  
      */
 428  
     private void checkLatestVersionRetire(final ViewContext viewContext, final String retirePath, final DataModel model){
 429  0
         String courseVerIndId = getCourseVersionIndId(model);
 430  0
         Long courseVersionSequence = getCourseVersionSequenceNumber(model);
 431  
     
 432  0
         courseServiceAsync.isLatestVersion(courseVerIndId, courseVersionSequence, new AsyncCallback<Boolean>(){
 433  
         
 434  
             public void onFailure(Throwable caught) {
 435  0
                 KSNotifier.add(new KSNotification("Error determining latest version of course", false, 5000));
 436  0
             }
 437  
         
 438  
             public void onSuccess(Boolean result) {
 439  0
                 doRetireActionItem(viewContext, retirePath, model);
 440  0
             }
 441  
         });
 442  0
     }
 443  
     
 444  
     // TODO: add Retire and Inactivate Dialogs
 445  
     
 446  
         /**
 447  
          * Use this method to call the {@link CourseRpcServiceAsync#changeState(String, String, com.google.gwt.user.client.rpc.AsyncCallback)
 448  
          * method, which will handle all related change state operations required for the course depending on the state being set.  
 449  
          *  
 450  
          * @param courseId
 451  
          * @param newState
 452  
          * @param stateChangeCallback The callback to execute to indicate if the state change call was successful.
 453  
          */
 454  
     public static void setCourseState(final String courseId, final String newState, final Callback<String> stateChangeCallback) {
 455  0
             KSBlockingProgressIndicator.addTask(processingTask);
 456  
             
 457  0
             courseServiceAsync.changeState(courseId, newState, new KSAsyncCallback<StatusInfo>() {
 458  
                     
 459  
                     @Override
 460  
                  public void handleFailure(Throwable caught) {
 461  0
                      Window.alert("Error Updating State: "+caught.getMessage());
 462  0
                      KSBlockingProgressIndicator.removeTask(processingTask);
 463  0
                      stateChangeCallback.exec(null);
 464  0
                  }
 465  
          
 466  
                  @Override
 467  
                  public void onSuccess(StatusInfo result) {                         
 468  0
                          KSBlockingProgressIndicator.removeTask(processingTask);
 469  0
                          if (!result.getSuccess()){
 470  0
                                  stateChangeCallback.exec(null);
 471  
                          } else {
 472  0
                                  stateChangeCallback.exec(newState);
 473  
                          }
 474  0
                  }
 475  
             });
 476  
             
 477  0
     }
 478  
     
 479  
     
 480  
         /**
 481  
          *  This depends heavily on {@link CourseStateUtil#setCourseState(String, String, Callback)}. 
 482  
          *  Changes here will affect assumptions made there.
 483  
           *
 484  
          */
 485  
     public void updateCourseActionItems(final DataModel cluModel) {
 486  
             
 487  
                 //First we need the model
 488  0
                 String courseVerIndId = getCourseVersionIndId(cluModel);
 489  0
                 Long courseVersionSequence = getCourseVersionSequenceNumber(cluModel);
 490  
                 //Do an async check if this is the current version
 491  0
                 if(courseVerIndId==null){
 492  0
                         isCurrentVersion = true;
 493  0
                         doUpdateCourseActionItems(cluModel);
 494  
                 }else{
 495  0
                         courseServiceAsync.isLatestVersion(courseVerIndId, courseVersionSequence, new AsyncCallback<Boolean>(){
 496  
                                 public void onFailure(Throwable caught) {
 497  0
                                         KSNotifier.add(new KSNotification("Error determining latest version of course", false, 5000));
 498  0
                                 }
 499  
                                 
 500  
                                 public void onSuccess(Boolean result) {
 501  0
                                         isCurrentVersion = result;
 502  0
                                         doUpdateCourseActionItems(cluModel);
 503  0
                                 }
 504  
                         });
 505  
                 }
 506  0
     }
 507  
     
 508  
         private void doUpdateCourseActionItems(DataModel cluModel) {
 509  
                 
 510  0
             final String cluState = cluModel.get("state");
 511  0
             courseId = cluModel.get(CreditCourseConstants.ID);
 512  
             
 513  0
             items.clear();      
 514  
             
 515  0
                 Application.getApplicationContext().getSecurityContext().checkScreenPermission("cluModifyItem",
 516  0
                                 new Callback<Boolean>() {
 517  
                                         @Override
 518  
                                         public void exec(Boolean result) {
 519  
                                                 
 520  0
                                                 if (!result){
 521  0
                                                     setItems(getNonAdminItems(cluState));
 522  
                                                 } else {
 523  0
                                                     setItems(getAdminItems(cluState));
 524  
                                                 }
 525  
                                                 
 526  0
                                             CourseWorkflowActionList.this.setEnabled(true);
 527  0
                                                 if(CourseWorkflowActionList.this.isEmpty()) {
 528  0
                                                         CourseWorkflowActionList.this.setVisible(false);
 529  
                                                 }
 530  
                                                 else{
 531  0
                                                         CourseWorkflowActionList.this.setVisible(true);
 532  
                                                 }
 533  0
                                         }
 534  
                                 });                
 535  0
         }
 536  
         
 537  
         private List<KSMenuItemData> getNonAdminItems(String cluState){
 538  0
             if (cluState.equals(DtoConstants.STATE_APPROVED)) {   // this state is no longer used
 539  0
             items.add(modifyCourseActionItem);
 540  0
             items.add(activateCourseActionItem);
 541  0
             if (isCurrentVersion){
 542  0
                 items.add(retireCourseActionItem);
 543  
             }
 544  0
         } else if (cluState.equals(DtoConstants.STATE_ACTIVE)) {
 545  0
             items.add(modifyCourseActionItem);
 546  
 //            items.add(inactivateCourseActionItem);
 547  0
             if (isCurrentVersion){
 548  0
                 items.add(retireCourseActionItem);
 549  
             }
 550  0
         } else if (cluState.equals(DtoConstants.STATE_SUSPENDED)) {
 551  0
             items.add(activateCourseActionItem);
 552  0
         } else if (cluState.equals(DtoConstants.STATE_RETIRED)){
 553  0
             items.add(modifyCourseActionItem);          
 554  
         }
 555  0
         items.add(copyCourseActionItem);
 556  
 
 557  0
         if (!isCurrentVersion) {
 558  0
             items.remove(modifyCourseActionItem);
 559  0
                 items.remove(retireCourseActionItem);
 560  
         }
 561  
 
 562  0
         return items;
 563  
     }
 564  
         
 565  
         private List<KSMenuItemData> getAdminItems(String cluState){
 566  0
             if (cluState.equals(DtoConstants.STATE_APPROVED)) {    // this state is no longer used
 567  0
             items.add(modifyCourseActionItem);
 568  0
             items.add(activateCourseActionItem);
 569  0
             if (isCurrentVersion){
 570  0
                 items.add(retireCourseActionItem);
 571  
             }
 572  0
         } else if (cluState.equals(DtoConstants.STATE_ACTIVE)) {
 573  0
             items.add(modifyCourseActionItem);
 574  
 //            items.add(inactivateCourseActionItem);
 575  0
             if (isCurrentVersion){  
 576  0
                 items.add(retireCourseActionItem);
 577  
             }
 578  0
         } else if (cluState.equals(DtoConstants.STATE_SUSPENDED)) {
 579  0
             items.add(activateCourseActionItem);
 580  0
         } else if (cluState.equals(DtoConstants.STATE_RETIRED)){
 581  0
             items.add(modifyCourseActionItem);          
 582  0
         } else if(cluState.equals(DtoConstants.STATE_SUPERSEDED)) {
 583  0
             items.add(modifyCourseActionItem);
 584  
         }
 585  0
             items.add(copyCourseActionItem);
 586  0
             return items;
 587  
         }
 588  
         
 589  
     public boolean isEmpty() {
 590  0
             return (items.size() == 0);
 591  
     }
 592  
     
 593  
     public String getMessage(String courseMessageKey) {
 594  0
             String msg = Application.getApplicationContext().getMessage(MSG_GROUP, courseMessageKey);
 595  0
             if (msg == null) {
 596  0
                     msg = courseMessageKey;
 597  
             }
 598  0
             return msg;
 599  
     }
 600  
 
 601  
 
 602  
     /** 
 603  
      * This checks the ViewContext passed in to determine if it contains a non-empty courseId
 604  
      * 
 605  
      * @return  true if view context contains non-empty courseId, false otherwise
 606  
      */
 607  
     private boolean hasCourseId(ViewContext viewContext){
 608  0
             return viewContext != null && viewContext.getId() != null && !viewContext.getId().isEmpty();
 609  
     }
 610  
 
 611  
     /**
 612  
      * Retrieves the version independent from the course data model
 613  
      * 
 614  
      * @param courseModel
 615  
      * @return version independent id of course
 616  
      */
 617  
     private String getCourseVersionIndId(DataModel courseModel){
 618  0
             return (String)courseModel.get(CreditCourseConstants.VERSION_INFO + QueryPath.getPathSeparator() + CreditCourseConstants.VERSION_IND_ID);            
 619  
     }
 620  
     
 621  
     /**
 622  
      * Retrieves the version sequence number from the course data model
 623  
      * 
 624  
      * @param courseModel
 625  
      * @return version sequence number id of course
 626  
      */
 627  
     private Long getCourseVersionSequenceNumber(DataModel courseModel){
 628  0
                    return (Long)courseModel.get(CreditCourseConstants.VERSION_INFO + QueryPath.getPathSeparator() + CreditCourseConstants.VERSION_SEQ_NUMBER);
 629  
     }
 630  
 
 631  
     private void setupModifyCourseDialog(final ViewContext viewContext, final String modifyPath, final DataModel model) {
 632  0
                 Application.getApplicationContext().getSecurityContext().checkScreenPermission("cluModifyItem",
 633  0
                                 new Callback<Boolean>() {
 634  
                                         @Override
 635  
                                         public void exec(Boolean result) {
 636  0
                                                 hasAdminAccess = result;
 637  0
                                    if (hasAdminAccess){
 638  
                                                     //Admin users have the option to make modifications to the course administratively or via the
 639  
                                             //curriculum review process. Clicking on the "Modify Course" item will present the user with
 640  
                                             //a modify dialog to allow them to choose the method of modification.
 641  0
                                                     buildModifyDialog(viewContext, modifyPath, model);
 642  
                                     } else {
 643  
                                             //Non-admin users are only allowed to make modifications via proposal curriculum review process.
 644  
                                             //Clicking the "Modify Course" item will simply navigate user directly to modify course proposal screen.
 645  0
                                         checkLatestVersion(viewContext, modifyPath, model, true);
 646  
                                     }
 647  
 
 648  
 
 649  0
                                         }
 650  
                                 });
 651  0
         }
 652  
     
 653  
     // KSCM-983 Setup the Retire lightbox from the drop-down
 654  
     // For Admins only.  Non-Admins will be directly sent to 
 655  
     private void setupRetireCourseDialog(final ViewContext viewContext, final String retirePath, final DataModel model) { 
 656  0
             Application.getApplicationContext().getSecurityContext().checkScreenPermission("cluRetireItem",
 657  0
                                 new Callback<Boolean>() {
 658  
                                         @Override
 659  
                                         public void exec(Boolean result) {
 660  0
                                                 hasAdminAccess = result;
 661  0
                                    if (hasAdminAccess){
 662  
                                                     //Admin users have the option to retire a course administratively or to retire
 663  
                                             //a course by proposal. Clicking on the "Retire Course" item will present the user with
 664  
                                             //a Retire dialog to allow them to choose the method of Retirement.                                             
 665  0
                                                      buildRetireDialog(viewContext, retirePath, model);
 666  
                                     } else {
 667  
                                             //Non-admin users are only allowed to retire via proposal.
 668  
                                             //Clicking the "Retire Course" item will simply navigate user directly to modify course by proposal screen.
 669  0
                                             checkLatestVersionRetire(viewContext, retirePath, model);
 670  
                                     }
 671  0
                                         }
 672  
                                 });
 673  0
         }
 674  
 }