1 package org.kuali.student.lum.lu.ui.course.client.controllers;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.Map;
6
7 import org.kuali.student.common.assembly.data.Metadata;
8 import org.kuali.student.common.assembly.data.QueryPath;
9 import org.kuali.student.common.dto.DtoConstants;
10 import org.kuali.student.common.rice.StudentIdentityConstants;
11 import org.kuali.student.common.rice.authorization.PermissionType;
12 import org.kuali.student.common.ui.client.application.Application;
13 import org.kuali.student.common.ui.client.application.ViewContext;
14 import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
15 import org.kuali.student.common.ui.client.configurable.mvc.sections.Section;
16 import org.kuali.student.common.ui.client.configurable.mvc.views.VerticalSectionView;
17 import org.kuali.student.common.ui.client.event.ActionEvent;
18 import org.kuali.student.common.ui.client.event.SaveActionEvent;
19 import org.kuali.student.common.ui.client.mvc.ActionCompleteCallback;
20 import org.kuali.student.common.ui.client.mvc.Callback;
21 import org.kuali.student.common.ui.client.mvc.DataModel;
22 import org.kuali.student.common.ui.client.mvc.DataModelDefinition;
23 import org.kuali.student.common.ui.client.mvc.ModelRequestCallback;
24 import org.kuali.student.common.ui.client.util.WindowTitleUtils;
25 import org.kuali.student.common.ui.client.widgets.KSButton;
26 import org.kuali.student.common.ui.client.widgets.menus.KSMenuItemData;
27 import org.kuali.student.common.ui.client.widgets.notification.KSNotification;
28 import org.kuali.student.common.ui.client.widgets.notification.KSNotifier;
29 import org.kuali.student.common.ui.shared.IdAttributes.IdType;
30 import org.kuali.student.common.validation.dto.ValidationResultInfo;
31 import org.kuali.student.core.workflow.ui.client.widgets.WorkflowUtilities;
32 import org.kuali.student.lum.common.client.lu.LUUIConstants;
33 import org.kuali.student.lum.common.client.widgets.AppLocations;
34 import org.kuali.student.lum.lu.LUConstants;
35 import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseConstants;
36 import org.kuali.student.lum.lu.ui.course.client.configuration.CourseAdminConfigurer;
37 import org.kuali.student.lum.lu.ui.course.client.configuration.CourseProposalConfigurer;
38 import org.kuali.student.lum.lu.ui.course.client.configuration.CourseProposalConfigurer.CourseSections;
39
40 import com.google.gwt.core.client.GWT;
41 import com.google.gwt.event.dom.client.ClickEvent;
42 import com.google.gwt.event.dom.client.ClickHandler;
43 import com.google.gwt.user.client.DOM;
44 import com.google.gwt.user.client.Element;
45 import com.google.gwt.user.client.ui.Widget;
46
47
48
49
50
51
52
53
54
55
56 public class CourseAdminController extends CourseProposalController{
57
58
59 protected List<KSButton> cancelButtons = new ArrayList<KSButton>();
60
61
62
63
64 @Override
65 protected void initializeController() {
66
67 super.cfg = GWT.create(CourseAdminConfigurer.class);
68 super.proposalPath = cfg.getProposalPath();
69 super.workflowUtil = new WorkflowUtilities(CourseAdminController.this ,proposalPath);
70
71 cfg.setState(DtoConstants.STATE_DRAFT.toUpperCase());
72 cfg.setNextState(DtoConstants.STATE_APPROVED.toUpperCase());
73 super.setDefaultModelId(cfg.getModelId());
74 super.registerModelsAndHandlers();
75 super.addStyleName("ks-course-admin");
76 currentDocType = LUConstants.PROPOSAL_TYPE_COURSE_CREATE_ADMIN;
77
78 setViewContext(getViewContext());
79 }
80
81
82
83
84 @Override
85 public KSButton getSaveButton(){
86 KSButton saveButton = new KSButton("Save", new ClickHandler(){
87 public void onClick(ClickEvent event) {
88 handleButtonClick(DtoConstants.STATE_DRAFT);
89 }
90 });
91
92 saveButton.addStyleName("ks-button-spacing");
93 return saveButton;
94 }
95
96 public KSButton getApproveAndActivateButton(){
97 return new KSButton("Approve and Activate", new ClickHandler(){
98 public void onClick(ClickEvent event) {
99 handleButtonClick(DtoConstants.STATE_ACTIVE);
100 }
101 });
102 }
103
104 public KSButton getCancelButton(){
105 KSButton cancelButton = new KSButton("Cancel Proposal", new ClickHandler(){
106 public void onClick(ClickEvent event) {
107 if (isNew) {
108 Application.navigate(AppLocations.Locations.CURRICULUM_MANAGEMENT.getLocation());
109 } else {
110
111 workflowUtil.cancel(new Callback<Boolean>() {
112 @Override
113 public void exec(Boolean result) {
114 if (result) {
115 Application.navigate(AppLocations.Locations.CURRICULUM_MANAGEMENT.getLocation());
116 }
117 }
118
119 });
120 }
121 }
122 });
123
124 cancelButton.addStyleName("ks-button-spacing");
125 cancelButtons.add(cancelButton);
126 return cancelButton;
127 }
128
129
130
131
132
133
134
135
136 protected void handleButtonClick(final String state){
137
138
139 cluProposalModel.set(QueryPath.parse(CreditCourseConstants.STATE), state);
140
141 final SaveActionEvent saveActionEvent = getSaveActionEvent(state);
142
143
144 if((String)cluProposalModel.get(CreditCourseConstants.ID)!=null && cfg instanceof CourseAdminConfigurer){
145 ((CourseAdminConfigurer )cfg).getRequisitesSection().storeRules(new Callback<Boolean>(){
146 public void exec(Boolean result) {
147 if(result){
148 doAdminSaveAction(saveActionEvent, state);
149 }else{
150 KSNotifier.show("Error saving rules.");
151 }
152 }
153 });
154 }else{
155 doAdminSaveAction(saveActionEvent, state);
156 }
157 }
158
159
160
161
162
163
164
165
166 private SaveActionEvent getSaveActionEvent(final String state){
167 final SaveActionEvent saveActionEvent = new SaveActionEvent(false);
168 if (DtoConstants.STATE_ACTIVE.equalsIgnoreCase(state)){
169 saveActionEvent.setActionCompleteCallback(new ActionCompleteCallback(){
170 @Override
171 public void onActionComplete(ActionEvent actionEvent) {
172 if (saveActionEvent.isSaveSuccessful()){
173 workflowUtil.blanketApprove(new Callback<Boolean>(){
174 @Override
175 public void exec(Boolean result) {
176
177 final ViewContext viewContext = new ViewContext();
178 viewContext.setId((String)cluProposalModel.get(CreditCourseConstants.ID));
179 viewContext.setIdType(IdType.OBJECT_ID);
180 if (DtoConstants.STATE_ACTIVE.equalsIgnoreCase(state)){
181 KSNotifier.show("Course approved and activated. It may take a minute or two for course status to be updated. Refresh to see latest status.");
182 Application.navigate(AppLocations.Locations.VIEW_COURSE.getLocation(), viewContext);
183 }
184
185 }
186 });
187 }
188 }
189 });
190 } else {
191
192 saveActionEvent.setActionCompleteCallback(new ActionCompleteCallback(){
193 @Override
194 public void onActionComplete(ActionEvent action) {
195 for (KSButton cancelButton:cancelButtons){
196 cancelButton.setEnabled(true);
197 ((CourseAdminConfigurer )cfg).getDocumentTool().beforeShow(NO_OP_CALLBACK);
198 }
199 }
200 });
201 }
202
203 return saveActionEvent;
204 }
205
206
207
208
209
210
211
212
213
214 private void doAdminSaveAction(final SaveActionEvent saveActionEvent, String state){
215 if (DtoConstants.STATE_APPROVED.equalsIgnoreCase(state) || DtoConstants.STATE_ACTIVE.equalsIgnoreCase(state)){
216
217 cluProposalModel.validateNextState((new Callback<List<ValidationResultInfo>>() {
218 @Override
219 public void exec(List<ValidationResultInfo> result) {
220
221 boolean isSectionValid = isValid(result, true);
222
223 if(isSectionValid){
224 CourseAdminController.this.fireApplicationEvent(saveActionEvent); }
225 else{
226 KSNotifier.add(new KSNotification("Unable to save, please check fields for errors.", false, true, 5000));
227 }
228
229 }
230 }));
231 } else {
232 CourseAdminController.this.fireApplicationEvent(saveActionEvent);
233 }
234 }
235
236
237
238
239
240
241 protected void progressiveEnableFields() {
242 super.progressiveEnableFields();
243 }
244
245
246
247
248 @Override
249 protected void setHeaderTitle(){
250 String title;
251 if (cluProposalModel.get(cfg.getProposalTitlePath()) != null){
252 title = getProposalTitle();
253 }
254 else{
255 title = "New Course (Admin Proposal)";
256 }
257 this.setContentTitle(title);
258 this.setName(title);
259 WindowTitleUtils.setContextTitle(title);
260 currentTitle = title;
261 }
262
263 private String getProposalTitle(){
264 StringBuffer sb = new StringBuffer();
265 sb.append(cluProposalModel.get(cfg.getProposalTitlePath()));
266 sb.append(" (Admin Proposal)");
267 return sb.toString();
268 }
269
270
271
272
273
274
275
276
277
278
279 public void addMenuItemSection(String parentMenu, final String sectionName, final String widgetId, final Widget widget) {
280 KSMenuItemData parentItem = null;
281 for (int i = 0; i < topLevelMenuItems.size(); i++) {
282 if (topLevelMenuItems.get(i).getLabel().equals(parentMenu)) {
283 parentItem = topLevelMenuItems.get(i);
284 break;
285 }
286 }
287
288 KSMenuItemData item = new KSMenuItemData(sectionName);
289 widget.getElement().setId(widgetId);
290 item.setClickHandler(new ClickHandler(){
291 @Override
292 public void onClick(ClickEvent event) {
293 Element element = DOM.getElementById(widgetId);
294 scrollToSection(element);
295 }
296 });
297
298 if (parentItem != null) {
299 parentItem.addSubItem(item);
300 } else {
301 topLevelMenuItems.add(item);
302 }
303
304 menu.refresh();
305 }
306
307 public native void scrollToSection(Element element)
308
309 ;
310
311 @Override
312 protected void configureScreens(DataModelDefinition modelDefinition, final Callback<Boolean> onReadyCallback) {
313 super.configureScreens(modelDefinition, previousEndTermConfigurationCallback(onReadyCallback));
314 }
315
316
317
318
319
320
321
322 protected Callback<Boolean> previousEndTermConfigurationCallback(final Callback<Boolean> onReadyCallback){
323 return new Callback<Boolean>(){
324
325 @Override
326 public void exec(final Boolean result) {
327 requestModel(new ModelRequestCallback<DataModel>(){
328 @Override
329 public void onModelReady(DataModel model) {
330
331
332
333 if (model.getDefinition().getMetadata().isCanEdit()){
334 String versionedFromId = model.get("versionInfo/versionedFromId");
335 if(versionedFromId!=null && !versionedFromId.isEmpty()){
336
337
338 VerticalSectionView view = (VerticalSectionView) viewMap.get(CourseSections.COURSE_INFO);
339 Section activeDatesSection = view.getSection(LUUIConstants.ACTIVE_DATES_LABEL_KEY);
340 Metadata meta = cfg.getModelDefinition().getMetadata(CourseProposalConfigurer.PROPOSAL_PATH + "/" + CreditCourseConstants.PREV_END_TERM);
341 if(meta!=null&&meta.getConstraints().get(0)!=null){
342 meta.getConstraints().get(0).setRequiredForNextState(true);
343 meta.getConstraints().get(0).setNextState("ACTIVE");
344 }
345 FieldDescriptor fd = cfg.addField(activeDatesSection, CourseProposalConfigurer.PROPOSAL_PATH + "/" + CreditCourseConstants.PREV_END_TERM, cfg.generateMessageInfo(LUUIConstants.PROPOSAL_PREV_END_TERM));
346
347
348 WorkflowUtilities.updateCrossField(fd, model);
349 }
350 }
351
352 onReadyCallback.exec(result);
353 }
354
355 @Override
356 public void onRequestFail(Throwable cause) {
357 throw new RuntimeException("Error getting model",cause);
358 }
359 });
360 }
361 };
362 }
363
364 @Override
365 public void setViewContext(ViewContext viewContext) {
366
367 if (viewContext.getId() != null && !viewContext.getId().isEmpty()) {
368 if (viewContext.getIdType() != IdType.COPY_OF_OBJECT_ID
369 && viewContext.getIdType() != IdType.COPY_OF_KS_KEW_OBJECT_ID) {
370
371 viewContext.setPermissionType(PermissionType.OPEN);
372 } else {
373
374 viewContext.setPermissionType(PermissionType.INITIATE);
375 }
376 } else {
377
378 viewContext.setPermissionType(PermissionType.INITIATE);
379
380 }
381
382 context = viewContext;
383 }
384
385
386
387
388 public void addPermissionAttributes(Map<String, String> attributes){
389 super.addPermissionAttributes(attributes);
390
391 ViewContext viewContext = getViewContext();
392
393
394 if(viewContext.getId() != null && !viewContext.getId().isEmpty()){
395 if(viewContext.getIdType() != IdType.COPY_OF_OBJECT_ID && viewContext.getIdType() != IdType.COPY_OF_KS_KEW_OBJECT_ID){
396
397 attributes.put(StudentIdentityConstants.DOCUMENT_TYPE_NAME, LUConstants.PROPOSAL_TYPE_COURSE_CREATE_ADMIN);
398 } else{
399
400 attributes.put(StudentIdentityConstants.DOCUMENT_TYPE_NAME, LUConstants.PROPOSAL_TYPE_COURSE_MODIFY_ADMIN);
401 }
402 } else{
403
404 attributes.put(StudentIdentityConstants.DOCUMENT_TYPE_NAME, LUConstants.PROPOSAL_TYPE_COURSE_CREATE_ADMIN);
405 }
406 }
407
408 }
409