View Javadoc

1   /**
2    * Copyright 2010 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   */
15  
16  package org.kuali.student.lum.lu.ui.tools.client.configuration;
17  
18  import java.util.List;
19  
20  import org.kuali.student.common.ui.client.application.KSAsyncCallback;
21  import org.kuali.student.common.ui.client.configurable.mvc.layouts.BasicLayout;
22  import org.kuali.student.common.ui.client.configurable.mvc.sections.Section;
23  import org.kuali.student.common.ui.client.event.SaveActionEvent;
24  import org.kuali.student.common.ui.client.event.SaveActionHandler;
25  import org.kuali.student.common.ui.client.mvc.Callback;
26  import org.kuali.student.common.ui.client.mvc.Controller;
27  import org.kuali.student.common.ui.client.mvc.DataModel;
28  import org.kuali.student.common.ui.client.mvc.DataModelDefinition;
29  import org.kuali.student.common.ui.client.mvc.ModelProvider;
30  import org.kuali.student.common.ui.client.mvc.ModelRequestCallback;
31  import org.kuali.student.common.ui.client.mvc.View;
32  import org.kuali.student.common.ui.client.mvc.WorkQueue;
33  import org.kuali.student.common.ui.client.mvc.WorkQueue.WorkItem;
34  import org.kuali.student.common.ui.client.service.DataSaveResult;
35  import org.kuali.student.common.ui.client.widgets.KSLabel;
36  import org.kuali.student.common.ui.client.widgets.KSLightBox;
37  import org.kuali.student.common.ui.client.widgets.KSProgressIndicator;
38  import org.kuali.student.common.ui.client.widgets.buttongroups.ButtonEnumerations;
39  import org.kuali.student.common.ui.client.widgets.buttongroups.OkGroup;
40  import org.kuali.student.common.ui.client.widgets.buttongroups.ButtonEnumerations.ButtonEnum;
41  import org.kuali.student.common.ui.client.widgets.buttongroups.ButtonEnumerations.OkEnum;
42  import org.kuali.student.common.ui.client.widgets.field.layout.button.ActionCancelGroup;
43  import org.kuali.student.common.ui.client.widgets.progress.BlockingTask;
44  import org.kuali.student.common.ui.client.widgets.progress.KSBlockingProgressIndicator;
45  import org.kuali.student.core.assembly.data.Data;
46  import org.kuali.student.core.assembly.data.Metadata;
47  import org.kuali.student.core.validation.dto.ValidationResultInfo;
48  import org.kuali.student.core.validation.dto.ValidationResultInfo.ErrorLevel;
49  import org.kuali.student.lum.common.client.widgets.CluSetHelper;
50  import org.kuali.student.lum.common.client.widgets.CluSetManagementRpcService;
51  import org.kuali.student.lum.common.client.widgets.CluSetManagementRpcServiceAsync;
52  
53  import com.google.gwt.core.client.GWT;
54  import com.google.gwt.dom.client.Style;
55  import com.google.gwt.user.client.Window;
56  import com.google.gwt.user.client.ui.Widget;
57  
58  public class CluSetsManagementController extends BasicLayout {  
59  
60      private final DataModel cluSetModel = new DataModel();    
61      private WorkQueue cluSetModelRequestQueue;
62      
63      private ClusetView mainView;
64      private ClusetView createClusetView;
65      private ClusetView editClusetView;
66      private ClusetView viewClusetView;
67  
68      private boolean initialized = false;
69      CluSetManagementRpcServiceAsync cluSetManagementRpcServiceAsync = GWT.create(CluSetManagementRpcService.class);
70      public static final String CLUSET_MGT_MODEL = "cluSetManagementModel";
71      private BlockingTask retrievingTask = new BlockingTask("Retrieving ...");
72  
73      final KSLightBox progressWindow = new KSLightBox();
74  
75  
76      public CluSetsManagementController(){
77          super(CluSetsManagementController.class.getName());
78          setName("Course Set Management");
79          initialize();
80      }
81      
82      public ClusetView getMainView() {
83          return mainView;
84      }
85      
86      @Override
87      public <V extends Enum<?>> void showView(final V viewType) {
88          if (viewType == ClusetView.CluSetsManagementViews.EDIT) {
89              final String cluSetId = mainView.getSelectedCluSetId();
90              editClusetView.setSelectedCluSetId(cluSetId);
91              viewClusetView.setSelectedCluSetId(cluSetId);
92              if (cluSetId != null) {
93                  KSBlockingProgressIndicator.addTask(retrievingTask);
94                  cluSetManagementRpcServiceAsync.getData(cluSetId,  new KSAsyncCallback<Data>() {
95                      @Override
96                      public void handleFailure(Throwable caught) {
97                          KSBlockingProgressIndicator.removeTask(retrievingTask);
98                          Window.alert("Failed to retrieve cluset with id" + cluSetId);
99                      }
100                     @Override
101                     public void onSuccess(Data result) {
102                         try {
103                             cluSetModel.setRoot(result);
104                             editClusetView.updateView(cluSetModel);
105                             CluSetsManagementController.super.showView(viewType);
106                         } finally {
107                             KSBlockingProgressIndicator.removeTask(retrievingTask);
108                         }
109                     }
110                 });
111             }
112         } else if (viewType == ClusetView.CluSetsManagementViews.VIEW) {
113             final String cluSetId = mainView.getSelectedCluSetId();
114             editClusetView.setSelectedCluSetId(cluSetId);
115             viewClusetView.setSelectedCluSetId(cluSetId);
116             if (cluSetId != null) {
117                 KSBlockingProgressIndicator.addTask(retrievingTask);
118                 cluSetManagementRpcServiceAsync.getData(cluSetId,  new KSAsyncCallback<Data>() {
119                     @Override
120                     public void handleFailure(Throwable caught) {
121                         KSBlockingProgressIndicator.removeTask(retrievingTask);
122                         Window.alert("Failed to retrieve cluset with id" + cluSetId);
123                     }
124                     @Override
125                     public void onSuccess(Data result) {
126                         try {
127                             cluSetModel.setRoot(result);
128                             viewClusetView.updateView(cluSetModel);
129                             CluSetsManagementController.super.showView(viewType);
130                         } finally {
131                             KSBlockingProgressIndicator.removeTask(retrievingTask);
132                         }
133                     }
134                 });
135             }
136         } else {
137             cluSetModel.setRoot(new Data());
138             super.showView(viewType);
139         }
140     }
141 
142     private Widget getButtonPanel() {
143         ActionCancelGroup actionCancel =  new ActionCancelGroup(
144                 ButtonEnumerations.SaveCancelEnum.SAVE,
145                 ButtonEnumerations.SaveCancelEnum.CANCEL);
146         actionCancel.addCallback(new Callback<ButtonEnumerations.ButtonEnum>() {
147             @Override
148             public void exec(ButtonEnum result) {
149                 if (result == ButtonEnumerations.SaveCancelEnum.SAVE) {
150                     fireApplicationEvent(new SaveActionEvent());
151                 } else if (result == ButtonEnumerations.SaveCancelEnum.CANCEL) {
152                     showView(ClusetView.CluSetsManagementViews.MAIN);
153                 }
154             }
155         });
156         return actionCancel;
157     }
158 
159     private void initialize() {
160         super.setDefaultModelId(CLUSET_MGT_MODEL);
161         
162         // the callback is used here to append widgets at the end of the view.
163         // callback is needed here because there is an asynchronous call to retrieve
164         // metadata during the construction of ClusetView
165         createClusetView = new ClusetView(ClusetView.CluSetsManagementViews.CREATE,
166                 "Build Course Set", CLUSET_MGT_MODEL, new Callback<Boolean>() {
167                     @Override
168                     public void exec(Boolean result) {
169                         if (result == true) {
170                             Widget buttonPanel = getButtonPanel();
171                             buttonPanel.getElement().getStyle().setPaddingTop(50, Style.Unit.PX);
172                             createClusetView.addWidget(buttonPanel);
173                         }
174                     }
175         });
176         editClusetView = new ClusetView(ClusetView.CluSetsManagementViews.EDIT,
177                 "Edit Course Set", CLUSET_MGT_MODEL, new Callback<Boolean>() {
178                     @Override
179                     public void exec(Boolean result) {
180                         if (result == true) {
181                             Widget buttonPanel = getButtonPanel();
182                             buttonPanel.getElement().getStyle().setPaddingTop(50, Style.Unit.PX);
183                             editClusetView.addWidget(buttonPanel);
184                         }
185                     }
186         });
187         viewClusetView = new ClusetView(ClusetView.CluSetsManagementViews.VIEW,
188                 "View Course Set", CLUSET_MGT_MODEL, null);
189         
190         mainView = new ClusetView(ClusetView.CluSetsManagementViews.MAIN,
191                 "", CLUSET_MGT_MODEL, null);
192         
193         setDefaultView(ClusetView.CluSetsManagementViews.MAIN);
194         addView(createClusetView);
195         addView(editClusetView);
196         addView(viewClusetView);
197         addView(mainView);
198         
199         super.registerModel(CLUSET_MGT_MODEL, new ModelProvider<DataModel>() {
200 
201             @Override
202             public void requestModel(final ModelRequestCallback<DataModel> callback) {
203                 if (cluSetModelRequestQueue == null){
204                     cluSetModelRequestQueue = new WorkQueue();
205                 }
206 
207                 WorkItem workItem = new WorkItem(){
208                     @Override
209                     public void exec(Callback<Boolean> workCompleteCallback) {
210                         if (cluSetModel.getRoot() == null || cluSetModel.getRoot().size() == 0){
211                             cluSetModel.setRoot(new Data());
212                         }
213                         callback.onModelReady(cluSetModel);
214                         workCompleteCallback.exec(true);
215 
216                     }               
217                 };
218                 cluSetModelRequestQueue.submit(workItem);                
219             }
220 
221         });
222 
223     }
224     
225     private void init(final Callback<Boolean> onReadyCallback) {
226         KSProgressIndicator progressInd = new KSProgressIndicator();
227         progressInd.setText("Loading");
228         progressInd.show();
229         progressWindow.setWidget(progressInd);
230 
231         if (initialized) {
232             onReadyCallback.exec(true);
233         } else {
234             progressWindow.show();
235 
236             cluSetManagementRpcServiceAsync.getMetadata("courseSet", null, new KSAsyncCallback<Metadata>(){
237 
238                 @Override
239                 public void handleFailure(Throwable caught) {
240                     onReadyCallback.exec(false);
241                     progressWindow.hide();
242                     throw new RuntimeException("Failed to get model definition.", caught);                        
243                 }
244 
245                 @Override
246                 public void onSuccess(Metadata result) {
247                     DataModelDefinition def = new DataModelDefinition(result);
248                     cluSetModel.setDefinition(def);
249                     init(def);
250                     initialized = true;
251                     onReadyCallback.exec(true);
252                     progressWindow.hide();
253                 }                
254             });	        
255         }
256     }
257     
258     private void init(DataModelDefinition modelDefinition){
259 
260         if (!initialized){
261 //            cfg.configureCluSetManager(this);
262 //            addButton("Manage CLU Sets", getSaveButton());
263 //            addButton("Manage CLU Sets", getQuitButton());
264 //            addButton("View CLU Sets", getSaveButton());
265 //            addButton("View CLU Sets", getQuitButton());
266 
267             addApplicationEventHandler(SaveActionEvent.TYPE, new SaveActionHandler(){
268                 @Override
269                 public void doSave(SaveActionEvent saveAction) {
270                     GWT.log("CluSetManagementController received save action request.", null);
271                     doSaveAction(saveAction);
272                 }
273             });
274         }
275 
276         initialized = true;
277     } 
278 
279     /**
280      * @see org.kuali.student.common.ui.client.mvc.Controller#getViewsEnum()
281      */
282     @Override
283     public Class<? extends Enum<?>> getViewsEnum() {
284         return ClusetView.CluSetsManagementViews.class;
285     }
286 
287     @Override
288     protected void renderView(View view) {
289         super.renderView(view);
290 //        getNextButton("Manage CLU Sets").setVisible(false);
291 //        getNextButton("View CLU Sets").setVisible(false);
292     }
293 
294     @SuppressWarnings("unchecked")
295     @Override
296     public void requestModel(Class modelType, final ModelRequestCallback callback) {
297         super.requestModel(modelType, callback);
298     }
299 
300     public void doSaveAction(final SaveActionEvent saveActionEvent){
301 //        Enum clusetSectionEnum = getCurrentViewEnum();
302 
303         getCurrentView().updateModel();
304 
305         if(cluSetModel!=null){
306             cluSetModel.validate(new Callback<List<ValidationResultInfo>>() {
307 	            @Override
308 	            public void exec(List<ValidationResultInfo> result) {
309 	
310 	                boolean save = true;
311 	                View v = getCurrentView();
312 	                if(v instanceof Section){
313 	                    ((Section) v).setFieldHasHadFocusFlags(true);
314 	                    ErrorLevel status = ((Section) v).processValidationResults(result);
315 	                    if(status == ErrorLevel.ERROR){
316 	                        save = false;
317 	                    }
318 	                }
319 	
320 	                if(save){
321 	                    getCurrentView().updateModel();
322 	                    CluSetsManagementController.this.updateModel();
323 	                    // set reusable flag here for CluSetManagement.
324 //	                    CluSetHelper.wrap((Data)cluSetModel.getRoot().get("cluset")).setReusable(new Boolean(true));
325 	                    CluSetHelper.wrap((Data)cluSetModel.getRoot()).setReusable(new Boolean(true));
326 	                    saveModel(cluSetModel, saveActionEvent);
327 	                }
328 	                else{
329 	                    Window.alert("Save failed.  Please check fields for errors.");
330 	                }
331 	
332 	            }
333 	        });
334         }
335     }
336 
337     private void saveModel(final DataModel dataModel, final SaveActionEvent saveActionEvent) {
338         final KSLightBox saveWindow = new KSLightBox();
339         final KSLabel saveMessage = new KSLabel(saveActionEvent.getMessage() + "...");
340         final OkGroup buttonGroup = new OkGroup(new Callback<OkEnum>(){
341 
342             @Override
343             public void exec(OkEnum result) {
344                 saveWindow.hide();
345                 saveActionEvent.doActionComplete();                
346             }
347         });
348 
349         buttonGroup.setWidth("250px");
350         buttonGroup.getButton(OkEnum.Ok).setEnabled(false);
351         buttonGroup.setContent(saveMessage);
352 
353 
354         if (saveActionEvent.isAcknowledgeRequired()){
355             saveWindow.setWidget(buttonGroup);
356         } else {
357             saveWindow.setWidget(saveMessage);
358         }
359         saveWindow.show();
360 
361         final Callback<Throwable> saveFailedCallback = new Callback<Throwable>() {
362 
363             @Override
364             public void exec(Throwable caught) {
365                 GWT.log("Save Failed.", caught);
366                 saveWindow.setWidget(buttonGroup);
367                 saveMessage.setText("Save Failed!  Please Try Again.");
368                 buttonGroup.getButton(OkEnum.Ok).setEnabled(true);   
369             }
370 
371         };
372         try {
373             cluSetManagementRpcServiceAsync.saveData(dataModel.getRoot(), new KSAsyncCallback<DataSaveResult>() {
374                 @Override
375                 public void handleFailure(Throwable caught) {
376                     saveFailedCallback.exec(caught); 
377                 }
378 
379                 @Override
380                 public void onSuccess(DataSaveResult result) {
381                     if (result.getValidationResults() != null &&
382                             !result.getValidationResults().isEmpty()) {
383                         StringBuilder errorMessage = new StringBuilder();
384                         errorMessage.append("Validation error: ");
385                         for (ValidationResultInfo validationError : result.getValidationResults()) {
386                             errorMessage.append(validationError.getMessage()).append(" ");
387                         }
388                         saveMessage.setText(errorMessage.toString());
389                         buttonGroup.getButton(OkEnum.Ok).setEnabled(true);
390                     } else {
391                         dataModel.setRoot(result.getValue());
392                         if (saveActionEvent.isAcknowledgeRequired()){
393                             saveMessage.setText("Save Successful");
394                             buttonGroup.getButton(OkEnum.Ok).setEnabled(true);
395                         } else {
396                             saveWindow.hide();
397                             saveActionEvent.doActionComplete();
398                         }
399                     }
400                 }
401             });
402 
403         } catch (Exception e) {
404             saveFailedCallback.exec(e);
405         }
406     }
407 
408     @Override
409     public void showDefaultView(final Callback<Boolean> onReadyCallback) {
410         init(new Callback<Boolean>() {
411             @Override
412             public void exec(Boolean result) {
413                 if (result) {
414                     doShowDefaultView(onReadyCallback);
415                 } else {
416                     onReadyCallback.exec(false);
417                 }
418             }
419         });
420     }
421     
422     @Override
423     public void beforeShow(Callback<Boolean> onReadyCallback) {
424     	showDefaultView(onReadyCallback);
425     }
426 
427     private void doShowDefaultView(final Callback<Boolean> onReadyCallback) {
428         super.showDefaultView(onReadyCallback);
429     }
430 
431     @Override
432     public void setParentController(Controller controller) {
433         super.setParentController(controller);    
434     }
435     
436 }