1
2
3
4
5
6
7
8
9
10
11
12
13
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.assembly.data.Data;
21 import org.kuali.student.common.assembly.data.Metadata;
22 import org.kuali.student.common.rice.authorization.PermissionType;
23 import org.kuali.student.common.ui.client.application.Application;
24 import org.kuali.student.common.ui.client.application.KSAsyncCallback;
25 import org.kuali.student.common.ui.client.configurable.mvc.layouts.BasicLayout;
26 import org.kuali.student.common.ui.client.configurable.mvc.sections.Section;
27 import org.kuali.student.common.ui.client.event.SaveActionEvent;
28 import org.kuali.student.common.ui.client.event.SaveActionHandler;
29 import org.kuali.student.common.ui.client.mvc.Callback;
30 import org.kuali.student.common.ui.client.mvc.Controller;
31 import org.kuali.student.common.ui.client.mvc.DataModel;
32 import org.kuali.student.common.ui.client.mvc.DataModelDefinition;
33 import org.kuali.student.common.ui.client.mvc.ModelProvider;
34 import org.kuali.student.common.ui.client.mvc.ModelRequestCallback;
35 import org.kuali.student.common.ui.client.mvc.View;
36 import org.kuali.student.common.ui.client.mvc.WorkQueue;
37 import org.kuali.student.common.ui.client.mvc.WorkQueue.WorkItem;
38 import org.kuali.student.common.ui.client.security.AuthorizationCallback;
39 import org.kuali.student.common.ui.client.security.RequiresAuthorization;
40 import org.kuali.student.common.ui.client.service.DataSaveResult;
41 import org.kuali.student.common.ui.client.widgets.buttongroups.ButtonEnumerations;
42 import org.kuali.student.common.ui.client.widgets.buttongroups.ButtonEnumerations.ButtonEnum;
43 import org.kuali.student.common.ui.client.widgets.field.layout.button.ActionCancelGroup;
44 import org.kuali.student.common.ui.client.widgets.notification.KSNotification;
45 import org.kuali.student.common.ui.client.widgets.notification.KSNotifier;
46 import org.kuali.student.common.ui.client.widgets.progress.BlockingTask;
47 import org.kuali.student.common.ui.client.widgets.progress.KSBlockingProgressIndicator;
48 import org.kuali.student.common.validation.dto.ValidationResultInfo;
49 import org.kuali.student.common.validation.dto.ValidationResultInfo.ErrorLevel;
50 import org.kuali.student.lum.common.client.lu.LUUIPermissions;
51 import org.kuali.student.lum.common.client.widgets.CluSetHelper;
52 import org.kuali.student.lum.common.client.widgets.CluSetManagementRpcService;
53 import org.kuali.student.lum.common.client.widgets.CluSetManagementRpcServiceAsync;
54
55 import com.google.gwt.core.client.GWT;
56 import com.google.gwt.dom.client.Style;
57 import com.google.gwt.user.client.Window;
58 import com.google.gwt.user.client.ui.Widget;
59
60 public class CluSetsManagementController extends BasicLayout implements RequiresAuthorization{
61
62 private final DataModel cluSetModel = new DataModel();
63 private WorkQueue cluSetModelRequestQueue;
64
65 private ClusetView mainView;
66 private ClusetView createClusetView;
67 private ClusetView editClusetView;
68 private ClusetView viewClusetView;
69
70 private boolean initialized = false;
71 CluSetManagementRpcServiceAsync cluSetManagementRpcServiceAsync = GWT.create(CluSetManagementRpcService.class);
72 public static final String CLUSET_MGT_MODEL = "cluSetManagementModel";
73
74 private final BlockingTask initializingTask = new BlockingTask("Loading");
75 private final BlockingTask retrievingTask = new BlockingTask("Retrieving ...");
76 private final BlockingTask saving = new BlockingTask("Saving");
77
78 public CluSetsManagementController(){
79 super(CluSetsManagementController.class.getName());
80 setName("Course Set Management");
81 initialize();
82 }
83
84 public ClusetView getMainView() {
85 return mainView;
86 }
87
88 @Override
89 public <V extends Enum<?>> void showView(final V viewType) {
90 if (viewType == ClusetView.CluSetsManagementViews.EDIT) {
91 final String cluSetId = mainView.getSelectedCluSetId();
92 editClusetView.setSelectedCluSetId(cluSetId);
93 viewClusetView.setSelectedCluSetId(cluSetId);
94 if (cluSetId != null) {
95 KSBlockingProgressIndicator.addTask(retrievingTask);
96 cluSetManagementRpcServiceAsync.getData(cluSetId, new KSAsyncCallback<Data>() {
97 @Override
98 public void handleFailure(Throwable caught) {
99 KSBlockingProgressIndicator.removeTask(retrievingTask);
100 Window.alert("Failed to retrieve cluset with id" + cluSetId);
101 }
102 @Override
103 public void onSuccess(Data result) {
104 try {
105 cluSetModel.setRoot(result);
106 editClusetView.updateView(cluSetModel);
107 CluSetsManagementController.super.showView(viewType);
108 } finally {
109 KSBlockingProgressIndicator.removeTask(retrievingTask);
110 }
111 }
112 });
113 }
114 } else if (viewType == ClusetView.CluSetsManagementViews.VIEW) {
115 final String cluSetId = mainView.getSelectedCluSetId();
116 editClusetView.setSelectedCluSetId(cluSetId);
117 viewClusetView.setSelectedCluSetId(cluSetId);
118 if (cluSetId != null) {
119 KSBlockingProgressIndicator.addTask(retrievingTask);
120 cluSetManagementRpcServiceAsync.getData(cluSetId, new KSAsyncCallback<Data>() {
121 @Override
122 public void handleFailure(Throwable caught) {
123 KSBlockingProgressIndicator.removeTask(retrievingTask);
124 Window.alert("Failed to retrieve cluset with id" + cluSetId);
125 }
126 @Override
127 public void onSuccess(Data result) {
128 try {
129 cluSetModel.setRoot(result);
130 viewClusetView.updateView(cluSetModel);
131 afterModelLoaded();
132 CluSetsManagementController.super.showView(viewType);
133 } finally {
134 KSBlockingProgressIndicator.removeTask(retrievingTask);
135 }
136 }
137 });
138 }
139 } else {
140 cluSetModel.setRoot(new Data());
141 super.showView(viewType);
142 }
143 }
144
145 private void afterModelLoaded() {
146 viewClusetView.afterModelIsLoaded(cluSetModel);
147 }
148
149 private Widget getButtonPanel() {
150 ActionCancelGroup actionCancel = new ActionCancelGroup(
151 ButtonEnumerations.SaveCancelEnum.SAVE,
152 ButtonEnumerations.SaveCancelEnum.CANCEL);
153 actionCancel.addCallback(new Callback<ButtonEnumerations.ButtonEnum>() {
154 @Override
155 public void exec(ButtonEnum result) {
156 if (result == ButtonEnumerations.SaveCancelEnum.SAVE) {
157 fireApplicationEvent(new SaveActionEvent());
158 } else if (result == ButtonEnumerations.SaveCancelEnum.CANCEL) {
159 showView(ClusetView.CluSetsManagementViews.MAIN);
160 }
161 }
162 });
163 return actionCancel;
164 }
165
166 private void initialize() {
167 super.setDefaultModelId(CLUSET_MGT_MODEL);
168
169
170
171
172 createClusetView = new ClusetView(ClusetView.CluSetsManagementViews.CREATE,
173 "Build Course Set", CLUSET_MGT_MODEL, new Callback<Boolean>() {
174 @Override
175 public void exec(Boolean result) {
176 if (result == true) {
177 Widget buttonPanel = getButtonPanel();
178 buttonPanel.getElement().getStyle().setPaddingTop(50, Style.Unit.PX);
179 createClusetView.addWidget(buttonPanel);
180 }
181 }
182 });
183 editClusetView = new ClusetView(ClusetView.CluSetsManagementViews.EDIT,
184 "Edit Course Set", CLUSET_MGT_MODEL, new Callback<Boolean>() {
185 @Override
186 public void exec(Boolean result) {
187 if (result == true) {
188 Widget buttonPanel = getButtonPanel();
189 buttonPanel.getElement().getStyle().setPaddingTop(50, Style.Unit.PX);
190 editClusetView.addWidget(buttonPanel);
191 }
192 }
193 });
194 viewClusetView = new ClusetView(ClusetView.CluSetsManagementViews.VIEW,
195 "View Course Set", CLUSET_MGT_MODEL, null);
196
197 mainView = new ClusetView(ClusetView.CluSetsManagementViews.MAIN,
198 "", CLUSET_MGT_MODEL, null);
199
200 setDefaultView(ClusetView.CluSetsManagementViews.MAIN);
201 addView(createClusetView);
202 addView(editClusetView);
203 addView(viewClusetView);
204 addView(mainView);
205
206 super.registerModel(CLUSET_MGT_MODEL, new ModelProvider<DataModel>() {
207
208 @Override
209 public void requestModel(final ModelRequestCallback<DataModel> callback) {
210 if (cluSetModelRequestQueue == null){
211 cluSetModelRequestQueue = new WorkQueue();
212 }
213
214 WorkItem workItem = new WorkItem(){
215 @Override
216 public void exec(Callback<Boolean> workCompleteCallback) {
217 if (cluSetModel.getRoot() == null || cluSetModel.getRoot().size() == 0){
218 cluSetModel.setRoot(new Data());
219 }
220 callback.onModelReady(cluSetModel);
221 workCompleteCallback.exec(true);
222
223 }
224 };
225 cluSetModelRequestQueue.submit(workItem);
226 }
227
228 });
229
230 }
231
232 private void init(final Callback<Boolean> onReadyCallback) {
233
234 if (initialized) {
235 onReadyCallback.exec(true);
236 } else {
237 KSBlockingProgressIndicator.addTask(initializingTask);
238 cluSetManagementRpcServiceAsync.getMetadata("courseSet", null, new KSAsyncCallback<Metadata>(){
239
240 @Override
241 public void handleFailure(Throwable caught) {
242 onReadyCallback.exec(false);
243 KSBlockingProgressIndicator.removeTask(initializingTask);
244 throw new RuntimeException("Failed to get model definition.", caught);
245 }
246
247 @Override
248 public void onSuccess(Metadata result) {
249 DataModelDefinition def = new DataModelDefinition(result);
250 cluSetModel.setDefinition(def);
251 init(def);
252 initialized = true;
253 onReadyCallback.exec(true);
254 KSBlockingProgressIndicator.removeTask(initializingTask);
255 }
256 });
257 }
258 }
259
260 private void init(DataModelDefinition modelDefinition){
261
262 if (!initialized){
263
264
265
266
267
268
269 addApplicationEventHandler(SaveActionEvent.TYPE, new SaveActionHandler(){
270 @Override
271 public void doSave(SaveActionEvent saveAction) {
272 GWT.log("CluSetManagementController received save action request.", null);
273 doSaveAction(saveAction);
274 }
275 });
276 }
277
278 initialized = true;
279 }
280
281 @Override
282 protected void renderView(View view) {
283 super.renderView(view);
284
285
286 }
287
288 @SuppressWarnings("unchecked")
289 @Override
290 public void requestModel(Class modelType, final ModelRequestCallback callback) {
291 super.requestModel(modelType, callback);
292 }
293
294 public void doSaveAction(final SaveActionEvent saveActionEvent){
295
296
297 getCurrentView().updateModel();
298
299 if(cluSetModel!=null){
300 cluSetModel.validate(new Callback<List<ValidationResultInfo>>() {
301 @Override
302 public void exec(List<ValidationResultInfo> result) {
303
304 boolean save = true;
305 View v = getCurrentView();
306 if(v instanceof Section){
307 ((Section) v).setFieldHasHadFocusFlags(true);
308 ErrorLevel status = ((Section) v).processValidationResults(result);
309 if(status == ErrorLevel.ERROR){
310 save = false;
311 }
312 }
313
314 if(save){
315 getCurrentView().updateModel();
316 CluSetsManagementController.this.updateModel();
317
318
319 CluSetHelper.wrap((Data)cluSetModel.getRoot()).setReusable(new Boolean(true));
320 saveModel(cluSetModel, saveActionEvent);
321 }
322 else{
323 Window.alert("Save failed. Please check fields for errors.");
324 }
325
326 }
327 });
328 }
329 }
330
331 private void saveModel(final DataModel dataModel, final SaveActionEvent saveActionEvent) {
332 KSBlockingProgressIndicator.addTask(saving);
333
334 cluSetManagementRpcServiceAsync.saveData(dataModel.getRoot(), new KSAsyncCallback<DataSaveResult>() {
335 @Override
336 public void handleFailure(Throwable caught) {
337 GWT.log("Save Failed.", caught);
338 KSBlockingProgressIndicator.removeTask(saving);
339 KSNotifier.add(new KSNotification("Save Failed on server. Please try again.", false, true, 5000));
340 }
341
342 @Override
343 public void handleVersionMismatch(Throwable caught) {
344 super.handleVersionMismatch(caught);
345 KSBlockingProgressIndicator.removeTask(saving);
346 }
347
348 @Override
349 public void onSuccess(DataSaveResult result) {
350 KSBlockingProgressIndicator.removeTask(saving);
351 if (result.getValidationResults() != null &&
352 !result.getValidationResults().isEmpty()) {
353 StringBuilder errorMessage = new StringBuilder();
354 errorMessage.append("Validation error: ");
355 for (ValidationResultInfo validationError : result.getValidationResults()) {
356 errorMessage.append(validationError.getMessage()).append(" ");
357 }
358 KSNotifier.add(new KSNotification("Save Failed. " + errorMessage, false, 5000));
359 } else {
360 dataModel.setRoot(result.getValue());
361 KSNotifier.add(new KSNotification("Save Successful", false, 4000));
362 }
363 }
364 });
365
366 }
367
368 @Override
369 public void showDefaultView(final Callback<Boolean> onReadyCallback) {
370 init(new Callback<Boolean>() {
371 @Override
372 public void exec(Boolean result) {
373 if (result) {
374 doShowDefaultView(onReadyCallback);
375 } else {
376 onReadyCallback.exec(false);
377 }
378 }
379 });
380 }
381
382 @Override
383 public void beforeShow(Callback<Boolean> onReadyCallback) {
384 showDefaultView(onReadyCallback);
385 }
386
387 private void doShowDefaultView(final Callback<Boolean> onReadyCallback) {
388 super.showDefaultView(onReadyCallback);
389 }
390
391 @Override
392 public void setParentController(Controller controller) {
393 super.setParentController(controller);
394 }
395
396 @Override
397 public boolean isAuthorizationRequired() {
398 return true;
399 }
400
401 @Override
402 public void setAuthorizationRequired(boolean required) {
403 throw new UnsupportedOperationException();
404 }
405
406 @Override
407 public void checkAuthorization(final AuthorizationCallback authCallback) {
408 Application.getApplicationContext().getSecurityContext().checkScreenPermission(LUUIPermissions.USE_VIEW_COURSE_SET_MANAGEMENT_SCREENS, new Callback<Boolean>() {
409 @Override
410 public void exec(Boolean result) {
411
412 final boolean isAuthorized = result;
413
414 if(isAuthorized){
415 authCallback.isAuthorized();
416 }
417 else
418 authCallback.isNotAuthorized("User is not authorized: " + LUUIPermissions.USE_VIEW_COURSE_SET_MANAGEMENT_SCREENS);
419 }
420 });
421 }
422
423 }