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