View Javadoc

1   package org.kuali.student.lum.lu.ui.tools.client.configuration;
2   
3   import java.util.Date;
4   import java.util.List;
5   
6   import org.kuali.student.common.ui.client.application.Application;
7   import org.kuali.student.common.ui.client.application.KSAsyncCallback;
8   import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
9   import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptorReadOnly;
10  import org.kuali.student.common.ui.client.configurable.mvc.SectionTitle;
11  import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBinding;
12  import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBindingSupport;
13  import org.kuali.student.common.ui.client.configurable.mvc.sections.Section;
14  import org.kuali.student.common.ui.client.configurable.mvc.sections.VerticalSection;
15  import org.kuali.student.common.ui.client.configurable.mvc.views.VerticalSectionView;
16  import org.kuali.student.common.ui.client.mvc.Callback;
17  import org.kuali.student.common.ui.client.mvc.Controller;
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.history.HistoryManager;
21  import org.kuali.student.common.ui.client.widgets.KSDatePicker;
22  import org.kuali.student.common.ui.client.widgets.KSLabel;
23  import org.kuali.student.common.ui.client.widgets.KSTextArea;
24  import org.kuali.student.common.ui.client.widgets.field.layout.element.MessageKeyInfo;
25  import org.kuali.student.common.ui.client.widgets.headers.KSDocumentHeader;
26  import org.kuali.student.common.ui.client.widgets.search.KSPicker;
27  import org.kuali.student.common.ui.client.widgets.search.SelectedResults;
28  import org.kuali.student.common.ui.client.widgets.table.summary.SummaryTableFieldBlock;
29  import org.kuali.student.common.ui.client.widgets.table.summary.SummaryTableFieldRow;
30  import org.kuali.student.common.ui.client.widgets.table.summary.SummaryTableSection;
31  import org.kuali.student.lum.common.client.lu.LUUIConstants;
32  import org.kuali.student.lum.common.client.widgets.CluSetDetailsWidget;
33  import org.kuali.student.lum.common.client.widgets.CluSetEditorWidget;
34  import org.kuali.student.lum.common.client.widgets.CluSetManagementRpcService;
35  import org.kuali.student.lum.common.client.widgets.CluSetManagementRpcServiceAsync;
36  import org.kuali.student.lum.common.client.widgets.CluSetRetriever;
37  import org.kuali.student.lum.common.client.widgets.CluSetRetrieverImpl;
38  import org.kuali.student.r1.common.assembly.data.LookupMetadata;
39  import org.kuali.student.r1.common.assembly.data.Metadata;
40  import org.kuali.student.r1.common.assembly.data.QueryPath;
41  
42  import com.google.gwt.core.client.GWT;
43  import com.google.gwt.dom.client.Style;
44  import com.google.gwt.event.dom.client.ClickEvent;
45  import com.google.gwt.event.dom.client.ClickHandler;
46  import com.google.gwt.i18n.client.DateTimeFormat;
47  import com.google.gwt.user.client.Window;
48  import com.google.gwt.user.client.rpc.AsyncCallback;
49  import com.google.gwt.user.client.ui.Anchor;
50  import com.google.gwt.user.client.ui.HasText;
51  import com.google.gwt.user.client.ui.SimplePanel;
52  import com.google.gwt.user.client.ui.Widget;
53  
54  public class ClusetView extends VerticalSectionView {
55  
56      protected CluSetManagementRpcServiceAsync cluSetManagementRpcServiceAsync = GWT.create(CluSetManagementRpcService.class);
57      protected CluSetRetriever cluSetRetriever = new CluSetRetrieverImpl();
58      protected DataModelDefinition modelDefinition;
59      protected DataModelDefinition searchDefinition;
60      protected String selectedCluSetId;
61      protected CluSetsManagementViews viewEnum;
62      protected SimplePanel cluSetDisplay = new SimplePanel();
63      protected CluSetEditorWidget cluSetEditor;
64      protected String cluSetType;
65  
66      protected KSLabel titleLabel = new KSLabel();
67  
68      public void afterModelIsLoaded(DataModel cluSetModel) {
69          titleLabel.setText(cluSetModel.<String>get("name"));
70      }
71  
72      public enum CluSetsManagementViews {
73          MAIN,
74          CREATE,
75          EDIT,
76          VIEW
77      }
78  
79      public ClusetView() {
80          super();
81      }
82  
83      public ClusetView(Enum<?> viewEnum, String name, String modelId,
84              boolean showTitle) {
85          super(viewEnum, name, modelId, showTitle);
86      }
87  
88      public ClusetView(Enum<?> viewEnum, String name, String modelId,
89              Widget titleWidget) {
90          super(viewEnum, name, modelId, titleWidget);
91      }
92  
93      public ClusetView(Enum<?> viewEnum, String name, String modelId) {
94          super(viewEnum, name, modelId);
95      }
96  
97      public void init(CluSetsManagementViews clusetViewEnum, String name, String modelId, final Callback<Boolean> onReady) {
98          init(clusetViewEnum, name, modelId, false, onReady);
99      }
100 
101     public void init(final CluSetsManagementViews clusetViewEnum, String name,
102             String clusetMgtModel, boolean showTitle, final Callback<Boolean> onReady) {
103         super.init(clusetViewEnum, name, modelId, showTitle);
104         cluSetType = "kuali.cluSet.type.CreditCourse";
105         if (clusetViewEnum == CluSetsManagementViews.CREATE ||
106                 clusetViewEnum == CluSetsManagementViews.EDIT) {
107             cluSetEditor = new CluSetEditorWidget(
108                     new CluSetRetrieverImpl(),
109                     clusetViewEnum, name, modelId, true, null,
110                     cluSetType, false);
111         }
112         viewEnum = clusetViewEnum;
113         cluSetManagementRpcServiceAsync.getMetadata("courseSet", null, new KSAsyncCallback<Metadata>() {
114             @Override
115             public void handleFailure(Throwable caught) {
116                 Window.alert("Failed to retrieve cluset definition");
117             }
118 
119             @Override
120             public void onSuccess(Metadata result) {
121                 DataModelDefinition def = new DataModelDefinition(result);
122                 setModelDefinition(def);
123                 cluSetManagementRpcServiceAsync.getMetadata("search", null, new AsyncCallback<Metadata>() {
124                     @Override
125                     public void onFailure(Throwable caught) {
126                         Window.alert("Failed to retrieve searchDefinition");
127                     }
128 
129                     @Override
130                     public void onSuccess(Metadata result) {
131                         setSearchDefinition(new DataModelDefinition(result));
132                         setupView(clusetViewEnum);
133                         if (onReady != null) {
134                             onReady.exec(new Boolean(true));
135                         }
136                     }
137                 });
138             }
139         });
140         setStyles();
141     }
142 
143     private void setStyles() {
144         titleLabel.addStyleName("cluSetTitle");
145     }
146 
147     private void setModelDefinition(DataModelDefinition modelDefinition) {
148         this.modelDefinition = modelDefinition;
149     }
150 
151     private void setSearchDefinition(DataModelDefinition searchDefinition) {
152         this.searchDefinition = searchDefinition;
153     }
154 
155     @Override
156     public void beforeShow(Callback<Boolean> onReadyCallback) {
157         super.beforeShow(onReadyCallback);
158         if (viewEnum == CluSetsManagementViews.VIEW) {
159             refreshCluSetDisplay();
160         }
161     }
162 
163     private void refreshCluSetDisplay() {
164         if (this.selectedCluSetId != null) {
165             CluSetDetailsWidget clusetDetailsWidget =
166                     new CluSetDetailsWidget(selectedCluSetId, cluSetRetriever);
167             cluSetDisplay.clear();
168             cluSetDisplay.setWidget(clusetDetailsWidget);
169         }
170     }
171 
172     private void setupView(CluSetsManagementViews clusetViewEnum) {
173         if (clusetViewEnum == CluSetsManagementViews.CREATE ||
174                 clusetViewEnum == CluSetsManagementViews.EDIT) {
175             setupCreateEditClusetView();
176         } else if (clusetViewEnum == CluSetsManagementViews.MAIN) {
177             setupMainView();
178         } else if (clusetViewEnum == CluSetsManagementViews.VIEW) {
179             setupViewClusetView();
180         }
181     }
182 
183     @Override
184     public void onHistoryEvent(String historyStack) {
185         super.onHistoryEvent(historyStack);
186         CluSetsManagementController cluSetsManagementController =
187                 (CluSetsManagementController) getController();
188         selectedCluSetId = HistoryManager.getTokenMap(historyStack).get("docId");
189         cluSetsManagementController.getMainView().setSelectedCluSetId(selectedCluSetId);
190         cluSetsManagementController.showView(CluSetsManagementViews.VIEW);
191     }
192 
193     private void setupViewClusetView() {
194         Anchor editCluSet = new Anchor("Edit Course Set");
195         editCluSet.addClickHandler(new ClickHandler() {
196             @Override
197             public void onClick(ClickEvent event) {
198                 Controller parentController = getController();
199                 parentController.showView(CluSetsManagementViews.EDIT);
200             }
201         });
202         addWidget(titleLabel);
203         this.addWidget(editCluSet);
204         Section generalClusInfoSection = new VerticalSection();
205         KSLabel cluSetTitle = new KSLabel();
206         cluSetTitle.getElement().getStyle().setProperty("fontWeight", "bold");
207         cluSetTitle.getElement().getStyle().setProperty("fontSize", "16px");
208         cluSetTitle.getElement().getStyle().setProperty("borderBotton", "1px solid #D8D8D8");
209 
210         addField(generalClusInfoSection,
211                 ToolsConstants.CLU_SET_NAME_FIELD,
212                 null,
213                 cluSetTitle,
214                 null);
215 //        addField(generalClusInfoSection, 
216 //                ToolsConstants.CLU_SET_DESCRIPTION_FIELD, 
217 //                generateMessageInfo(ToolsConstants.DESCRIPTION),
218 //                new KSLabel(),
219 //                null);
220 //        addField(generalClusInfoSection, 
221 //                ToolsConstants.CLU_SET_EXP_DATE_FIELD, 
222 //                generateMessageInfo(ToolsConstants.EXPIRATION_DATE),
223 //                new KSLabel(),
224 //                null);
225         this.addSection(setupGeneralClusInfoSection());
226 //        this.addSection(generalClusInfoSection);
227         this.addWidget(new KSLabel("Items in this Course Set"));
228         this.addWidget(cluSetDisplay);
229         this.setStyleName("standard-content-padding");
230     }
231 
232     private SummaryTableSection setupGeneralClusInfoSection() {
233         SummaryTableSection result = new SummaryTableSection(getController());
234         result.setEditable(false);
235 
236         SummaryTableFieldBlock block = new SummaryTableFieldBlock();
237 //        block.addEditingHandler(new EditHandler(CourseSections.COURSE_INFO));
238 //        block.setTitle(getLabel(LUConstants.INFORMATION_LABEL_KEY));
239         block.addSummaryTableFieldRow(getFieldRow(ToolsConstants.CLU_SET_DESCRIPTION_FIELD, generateMessageInfo(ToolsConstants.DESCRIPTION)));
240         SummaryTableFieldRow expDateRow = getFieldRow(ToolsConstants.CLU_SET_EXP_DATE_FIELD,
241                 generateMessageInfo(ToolsConstants.EXPIRATION_DATE), null, null, null,
242                 new ModelWidgetBindingSupport<HasText>() {
243                     public String dateToString(Date date) {
244                         String result = null;
245                         DateTimeFormat format = DateTimeFormat.getFormat("MM/dd/yyyy");
246                         result = format.format(date);
247 
248                         return result;
249                     }
250 
251                     @Override
252                     public void setModelValue(HasText widget, DataModel model, String path) {
253                         // not implementing here since this value should not be edited through this widget
254                     }
255 
256                     @Override
257                     public void setWidgetValue(HasText widget, DataModel model, String path) {
258                         try {
259                             QueryPath qPath = QueryPath.parse(path);
260 
261                             Object value = null;
262                             if (model != null) {
263                                 value = model.get(qPath);
264                             }
265 
266                             if (value != null && widget != null) {
267                                 if (value instanceof Date) {
268                                     widget.setText(dateToString((Date) value));
269                                 } else {
270                                     widget.setText(value.toString());
271                                 }
272                             } else if (value == null && widget != null) {
273                                 widget.setText("");
274                             }
275                         } catch (Exception e) {
276                             GWT.log("Error setting widget value for: " + path, e);
277                         }
278                     }
279 
280                 }
281                 , false);
282         block.addSummaryTableFieldRow(expDateRow);
283 
284         result.addSummaryTableFieldBlock(block);
285         return result;
286     }
287 
288     protected SummaryTableFieldRow getFieldRow(String fieldKey, MessageKeyInfo messageKey) {
289         return getFieldRow(fieldKey, messageKey, null, null, null, null, false);
290     }
291 
292     protected SummaryTableFieldRow getFieldRow(String fieldKey, MessageKeyInfo messageKey, boolean optional) {
293         return getFieldRow(fieldKey, messageKey, null, null, null, null, optional);
294     }
295 
296     protected SummaryTableFieldRow getFieldRow(String fieldKey, MessageKeyInfo messageKey, Widget widget, Widget widget2, String parentPath, ModelWidgetBinding<?> binding, boolean optional) {
297         QueryPath path = QueryPath.concat(parentPath, fieldKey);
298         Metadata meta = modelDefinition.getMetadata(path);
299 
300         FieldDescriptorReadOnly fd = new FieldDescriptorReadOnly(path.toString(), messageKey, meta);
301         if (widget != null) {
302             fd.setFieldWidget(widget);
303         }
304         if (binding != null) {
305             fd.setWidgetBinding(binding);
306         }
307         fd.setOptional(optional);
308 
309         FieldDescriptorReadOnly fd2 = new FieldDescriptorReadOnly(path.toString(), messageKey, meta);
310         if (widget2 != null) {
311             fd2.setFieldWidget(widget2);
312         }
313         if (binding != null) {
314             fd2.setWidgetBinding(binding);
315         }
316         fd2.setOptional(optional);
317 
318         SummaryTableFieldRow fieldRow = new SummaryTableFieldRow(fd, fd2);
319 
320         return fieldRow;
321     }
322 
323     private void setupMainView() {
324         this.addStyleName("blockLayout");
325         KSDocumentHeader header = new KSDocumentHeader();
326         header.setTitle("Course Set Management");
327         this.addWidget(header);
328 
329         Anchor createCluSet = new Anchor("<h2 class=\"contentBlock-title\">Create Course Set</h2>", true);
330         createCluSet.addClickHandler(new ClickHandler() {
331             @Override
332             public void onClick(ClickEvent event) {
333                 getController().showView(CluSetsManagementViews.CREATE);
334             }
335         });
336         this.addWidget(createCluSet);
337         this.addWidget(new KSLabel("Build a new Course set from courses, Course Sets, " +
338                 "or specific criteria."));
339 
340         Picker cluSetPicker = configureSearch(ToolsConstants.SEARCH_COURSE_SET);
341         cluSetPicker.addBasicSelectionCompletedCallback(new Callback<SelectedResults>() {
342             @Override
343             public void exec(SelectedResults result) {
344                 if (result != null && result.getReturnKey() != null && result.getReturnKey().trim().length() > 0) {
345                     selectedCluSetId = result.getReturnKey();
346                     Controller parentController = getController();
347                     parentController.showView(CluSetsManagementViews.VIEW);
348                 }
349             }
350         });
351         SectionTitle modifyCluSetTitle = SectionTitle.generateH2Title("View or Modify Course Sets");
352         modifyCluSetTitle.addStyleName("contentBlock-title");
353         modifyCluSetTitle.getElement().getStyle().setPaddingTop(40, Style.Unit.PX);
354         this.addWidget(modifyCluSetTitle);
355         this.addWidget(cluSetPicker);
356     }
357 
358     public String getSelectedCluSetId() {
359         return selectedCluSetId;
360     }
361 
362     public void setSelectedCluSetId(String selectedCluSetId) {
363         this.selectedCluSetId = selectedCluSetId;
364     }
365 
366     protected void setupCreateEditClusetView() {
367         String contextName = (cluSetType != null && cluSetType.equals("kuali.cluSet.type.Program")) ?
368                 "Program" : "Course";
369         VerticalSection defineCluSet = initSection(getH3Title(ToolsConstants.DEFINE_CLUSET + contextName), true);
370         
371         addFields(defineCluSet,contextName);
372 
373         KSLabel spacer = new KSLabel();
374         spacer.setHeight("20px");
375         this.addSection(cluSetEditor);
376         this.addWidget(spacer);
377         this.addSection(defineCluSet);
378         this.setStyleName("standard-content-padding");
379     }
380     
381     protected void addFields(VerticalSection defineCluSet, String contextName) {
382         addField(defineCluSet, ToolsConstants.CLU_SET_ORGANIZATION_FIELD, generateMessageInfo(ToolsConstants.ORGANIZATION), null, null);
383         addField(defineCluSet, ToolsConstants.CLU_SET_NAME_FIELD, generateMessageInfo(ToolsConstants.TITLE + contextName), null, null);
384         addField(defineCluSet, ToolsConstants.CLU_SET_DESCRIPTION_FIELD, generateMessageInfo(ToolsConstants.DESCRIPTION), new KSTextArea(), null);
385         addField(defineCluSet, ToolsConstants.CLU_SET_EFF_DATE_FIELD, generateMessageInfo(ToolsConstants.EFFECTIVE_DATE), new KSDatePicker(), null);
386         addField(defineCluSet, ToolsConstants.CLU_SET_EXP_DATE_FIELD, generateMessageInfo(ToolsConstants.EXPIRATION_DATE), new KSDatePicker(), null);
387     }
388 
389     protected static VerticalSection initSection(SectionTitle title, boolean withDivider) {
390         VerticalSection section = new VerticalSection(title);
391         section.addStyleName(LUUIConstants.STYLE_SECTION);
392         if (withDivider)
393             section.addStyleName(LUUIConstants.STYLE_SECTION_DIVIDER);
394         return section;
395     }
396 
397     private String getLabel(String labelKey) {
398         return Application.getApplicationContext().getUILabel("clusetmanagement", "clusetmanagement", "draft", labelKey);
399     }
400 
401     protected SectionTitle getH3Title(String labelKey) {
402         return SectionTitle.generateH3Title(getLabel(labelKey));
403     }
404 
405     protected MessageKeyInfo generateMessageInfo(String labelKey) {
406         return new MessageKeyInfo("clusetmanagement", "clusetmanagement", "draft", labelKey);
407     }
408 
409     private FieldDescriptor getFieldDescriptor(
410             String fieldKey,
411             MessageKeyInfo messageKey,
412             Widget widget,
413             String parentPath) {
414         QueryPath path = QueryPath.concat(parentPath, fieldKey);
415         Metadata meta = modelDefinition.getMetadata(path);
416         FieldDescriptor fd;
417         if (widget != null) {
418             fd = new FieldDescriptor(path.toString(), messageKey, meta, widget);
419         } else {
420             fd = new FieldDescriptor(path.toString(), messageKey, meta);
421         }
422         return fd;
423     }
424 
425     protected FieldDescriptor addField(Section section,
426                                      String fieldKey,
427                                      MessageKeyInfo messageKey,
428                                      Widget widget,
429                                      String parentPath) {
430         FieldDescriptor fd = getFieldDescriptor(fieldKey, messageKey, widget, parentPath);
431         section.addField(fd);
432         return fd;
433     }
434 
435     private Picker configureSearch(String fieldKey) {
436         QueryPath path = QueryPath.concat(null, fieldKey);
437         Metadata metaData = searchDefinition.getMetadata(path);
438         Picker picker = new Picker(metaData.getInitialLookup(), metaData.getAdditionalLookups());
439         return picker;
440     }
441 
442     public static class Picker extends KSPicker {
443 
444         private String name;
445         private LookupMetadata initLookupMetadata;
446         private List<LookupMetadata> additionalLookupMetadata;
447 
448         public Picker(LookupMetadata inLookupMetadata, List<LookupMetadata> additionalLookupMetadata) {
449             super(inLookupMetadata, additionalLookupMetadata);
450             this.initLookupMetadata = inLookupMetadata;
451             this.additionalLookupMetadata = additionalLookupMetadata;
452         }
453 
454         public String getName() {
455             return name;
456         }
457 
458         public void setName(String name) {
459             this.name = name;
460         }
461 
462         public LookupMetadata getInitLookupMetadata() {
463             return initLookupMetadata;
464         }
465 
466         public void setInitLookupMetadata(LookupMetadata initLookupMetadata) {
467             this.initLookupMetadata = initLookupMetadata;
468         }
469 
470         public List<LookupMetadata> getAdditionalLookupMetadata() {
471             return additionalLookupMetadata;
472         }
473 
474         public void setAdditionalLookupMetadata(List<LookupMetadata> additionalLookupMetadata) {
475             this.additionalLookupMetadata = additionalLookupMetadata;
476         }
477 
478     }
479 
480     @Override
481     public void setController(Controller controller) {
482         super.setController(controller);
483         if (cluSetEditor != null) {
484             cluSetEditor.setController(controller);
485         }
486     }
487 
488 }