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
216
217
218
219
220
221
222
223
224
225 this.addSection(setupGeneralClusInfoSection());
226
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
238
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
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 }