1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.kuali.student.lum.lu.ui.course.client.configuration;
31
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Map;
37
38 import org.kuali.student.common.assembly.data.Data;
39 import org.kuali.student.common.assembly.data.Metadata;
40 import org.kuali.student.common.assembly.data.QueryPath;
41 import org.kuali.student.common.assembly.data.Data.Value;
42 import org.kuali.student.common.dto.DtoConstants;
43 import org.kuali.student.common.ui.client.application.Application;
44 import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
45 import org.kuali.student.common.ui.client.configurable.mvc.SectionTitle;
46 import org.kuali.student.common.ui.client.configurable.mvc.binding.HasDataValueBinding;
47 import org.kuali.student.common.ui.client.configurable.mvc.binding.ListOfStringBinding;
48 import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBinding;
49 import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBindingSupport;
50 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.CompositeConditionOperator;
51 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityConfiguration;
52 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityFieldConfiguration;
53 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityFieldWidgetInitializer;
54 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.SwapCompositeCondition;
55 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.SwapCompositeConditionFieldConfig;
56 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.SwapCondition;
57 import org.kuali.student.common.ui.client.configurable.mvc.sections.CollapsableSection;
58 import org.kuali.student.common.ui.client.configurable.mvc.sections.GroupSection;
59 import org.kuali.student.common.ui.client.configurable.mvc.sections.MultiplicitySection;
60 import org.kuali.student.common.ui.client.configurable.mvc.sections.Section;
61 import org.kuali.student.common.ui.client.configurable.mvc.sections.SwapSection;
62 import org.kuali.student.common.ui.client.configurable.mvc.sections.VerticalSection;
63 import org.kuali.student.common.ui.client.configurable.mvc.views.SectionView;
64 import org.kuali.student.common.ui.client.configurable.mvc.views.VerticalSectionView;
65 import org.kuali.student.common.ui.client.mvc.Controller;
66 import org.kuali.student.common.ui.client.mvc.DataModel;
67 import org.kuali.student.common.ui.client.mvc.DataModelDefinition;
68 import org.kuali.student.common.ui.client.mvc.HasDataValue;
69 import org.kuali.student.common.ui.client.mvc.View;
70 import org.kuali.student.common.ui.client.widgets.KSButton;
71 import org.kuali.student.common.ui.client.widgets.KSCheckBox;
72 import org.kuali.student.common.ui.client.widgets.KSDropDown;
73 import org.kuali.student.common.ui.client.widgets.ListOfStringWidget;
74 import org.kuali.student.common.ui.client.widgets.KSButtonAbstract.ButtonStyle;
75 import org.kuali.student.common.ui.client.widgets.field.layout.element.MessageKeyInfo;
76 import org.kuali.student.common.ui.client.widgets.field.layout.element.SpanPanel;
77 import org.kuali.student.common.ui.client.widgets.field.layout.layouts.FieldLayoutComponent;
78 import org.kuali.student.common.ui.client.widgets.list.KSLabelList;
79 import org.kuali.student.common.ui.client.widgets.list.KSSelectItemWidgetAbstract;
80 import org.kuali.student.common.ui.client.widgets.list.KSSelectedList;
81 import org.kuali.student.common.ui.client.widgets.list.impl.SimpleListItems;
82 import org.kuali.student.common.ui.client.widgets.search.KSPicker;
83 import org.kuali.student.core.comments.ui.client.widgets.commenttool.CommentTool;
84 import org.kuali.student.core.comments.ui.client.widgets.decisiontool.DecisionPanel;
85 import org.kuali.student.core.document.ui.client.widgets.documenttool.DocumentTool;
86 import org.kuali.student.core.statement.dto.StatementTypeInfo;
87 import org.kuali.student.core.workflow.ui.client.views.CollaboratorSectionView;
88 import org.kuali.student.lum.common.client.lo.LOBuilder;
89 import org.kuali.student.lum.common.client.lo.LOBuilderBinding;
90 import org.kuali.student.lum.common.client.lo.LOPicker;
91 import org.kuali.student.lum.common.client.lo.OutlineNode;
92 import org.kuali.student.lum.common.client.lu.LUUIConstants;
93 import org.kuali.student.lum.lu.assembly.data.client.constants.base.RichTextInfoConstants;
94 import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseActivityConstants;
95 import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseConstants;
96 import org.kuali.student.lum.lu.assembly.data.client.constants.orch.CreditCourseJointsConstants;
97 import org.kuali.student.lum.lu.ui.course.client.controllers.CourseProposalController;
98 import org.kuali.student.lum.lu.ui.course.client.requirements.CourseRequirementsViewController;
99
100 import com.google.gwt.event.dom.client.ClickEvent;
101 import com.google.gwt.event.dom.client.ClickHandler;
102 import com.google.gwt.event.logical.shared.ValueChangeEvent;
103 import com.google.gwt.event.logical.shared.ValueChangeHandler;
104 import com.google.gwt.user.client.ui.Widget;
105
106
107
108
109
110
111
112 public class CourseConfigurer extends AbstractCourseConfigurer {
113
114 protected boolean WITH_DIVIDER = true;
115 protected boolean NO_DIVIDER = false;
116
117 public static final String PROPOSAL_PATH = "proposal";
118 public static final String PROPOSAL_TITLE_PATH = "proposal/name";
119 public static final String COURSE_TITLE_PATH = "/courseTitle";
120 public static final String CLU_PROPOSAL_MODEL = "cluProposalModel";
121 protected DocumentTool documentTool;
122
123 CourseSummaryConfigurer summaryConfigurer;
124
125
126 public static final String PROPOSAL = "";
127 public static final String COURSE = "";
128
129 public enum CourseSections {
130 CLU_BEGIN, PEOPLE_PERMISSONS, SUMMARY, AUTHORS_RATIONALE, GOVERNANCE, COURSE_LOGISTICS, COURSE_INFO, LEARNING_OBJECTIVES,
131 COURSE_REQUISITES, ACTIVE_DATES, FINANCIALS, ATTACHMENTS, COMMENTS,DECISIONS, DOCUMENTS,
132 PROGRAM_INFO, ASSEMBLER_TEST
133 }
134
135 protected List<StatementTypeInfo> stmtTypes;
136
137 public void setModelDefinition(DataModelDefinition modelDefinition) {
138 super.modelDefinition = modelDefinition;
139 }
140
141 public void setStatementTypes(List<StatementTypeInfo> stmtTypes) {
142 this.stmtTypes = stmtTypes;
143 }
144
145
146
147
148
149
150
151 public void configure(final CourseProposalController layout) {
152 type = "course";
153 state = DtoConstants.STATE_DRAFT;
154 groupName = LUUIConstants.COURSE_GROUP_NAME;
155
156 if (modelDefinition.getMetadata().isCanEdit()) {
157 addCluStartSection(layout);
158 String sections = getLabel(LUUIConstants.COURSE_SECTIONS);
159
160
161
162
163 layout.addMenu(sections);
164
165
166 layout.addMenuItem(sections, generateCourseInfoSection());
167 layout.addMenuItem(sections, generateGovernanceSection());
168 layout.addMenuItem(sections, generateCourseLogisticsSection());
169 layout.addMenuItem(sections, generateLearningObjectivesSection());
170
171
172 layout.addMenuItem(sections, generateCourseRequisitesSection(layout));
173
174
175 layout.addMenuItem(sections, generateActiveDatesSection());
176 layout.addMenuItem(sections, generateFinancialsSection());
177
178
179 layout.addMenuItem(sections, new CollaboratorSectionView(CourseSections.PEOPLE_PERMISSONS, LUUIConstants.SECTION_AUTHORS_AND_COLLABORATORS,CLU_PROPOSAL_MODEL));
180
181
182 documentTool = new DocumentTool(LUUIConstants.REF_DOC_RELATION_PROPOSAL_TYPE,CourseSections.DOCUMENTS, getLabel(LUUIConstants.TOOL_DOCUMENTS_LABEL_KEY));
183 documentTool.setModelDefinition((DataModelDefinition)modelDefinition);
184 layout.addMenuItem(sections, documentTool);
185
186
187 summaryConfigurer = new CourseSummaryConfigurer(type, state, groupName,(DataModelDefinition)modelDefinition, stmtTypes, (Controller)layout, CLU_PROPOSAL_MODEL);
188 layout.addSpecialMenuItem(summaryConfigurer.generateProposalSummarySection(true), "Review and Submit");
189
190
191 List<Enum<?>> excludedViews = new ArrayList<Enum<?>>();
192 excludedViews.add(CourseSections.DOCUMENTS);
193 excludedViews.add(CourseSections.COURSE_REQUISITES);
194 layout.addCommonButton(LUUIConstants.COURSE_SECTIONS, layout.getSaveButton(), excludedViews);
195 layout.addCommonButton(LUUIConstants.COURSE_SECTIONS, layout.getCancelButton(CourseSections.SUMMARY), excludedViews);
196
197
198
199 layout.addButtonForView(CourseSections.DOCUMENTS, getContinueButton(layout));
200 }
201 else{
202 CourseSummaryConfigurer summaryConfigurer = new CourseSummaryConfigurer(type, state, groupName, (DataModelDefinition)modelDefinition, stmtTypes, (Controller)layout, CLU_PROPOSAL_MODEL);
203 layout.removeMenuNavigation();
204 layout.addView(summaryConfigurer.generateProposalSummarySection(false));
205 }
206 layout.showPrint(true);
207 layout.setDefaultView(CourseSections.SUMMARY);
208 layout.addContentWidget(layout.getWfUtilities().getWorkflowStatusLabel());
209 final CommentTool commentTool = new CommentTool(CourseSections.COMMENTS, getLabel(LUUIConstants.TOOL_COMMENTS_LABEL_KEY), "kuali.comment.type.generalRemarks", "Proposal Comments");
210 commentTool.setController(layout);
211
212 layout.addContentWidget(new KSButton("Comments", ButtonStyle.DEFAULT_ANCHOR, new ClickHandler() {
213
214 @Override
215 public void onClick(ClickEvent event) {
216 commentTool.show();
217 }
218 }));
219
220
221 final DecisionPanel decisionPanel = new DecisionPanel(CourseSections.DECISIONS, getLabel(LUUIConstants.TOOL_DECISION_LABEL_KEY), "kuali.comment.type.generalRemarks");
222 layout.addView(decisionPanel);
223 layout.addContentWidget(new KSButton("Decisions", ButtonStyle.DEFAULT_ANCHOR, new ClickHandler() {
224
225 @Override
226 public void onClick(ClickEvent event) {
227 decisionPanel.show();
228 }
229 }));
230
231 }
232
233 protected KSButton getContinueButton(final CourseProposalController layout){
234 return new KSButton("Continue", new ClickHandler(){
235 public void onClick(ClickEvent event) {
236 layout.showNextViewOnMenu();
237 }
238 });
239 }
240
241 public void addCluStartSection(CourseProposalController layout) {
242 VerticalSectionView section = initSectionView(CourseSections.CLU_BEGIN, LUUIConstants.START_LABEL_KEY);
243 section.setController(layout);
244 addField(section, PROPOSAL_TITLE_PATH, generateMessageInfo(LUUIConstants.PROPOSAL_TITLE_LABEL_KEY));
245 addField(section, COURSE + "/" + COURSE_TITLE, generateMessageInfo(LUUIConstants.COURSE_TITLE_LABEL_KEY));
246
247
248 layout.addStartViewPopup(section);
249 layout.getStartPopup().setMaxHeight(600);
250 }
251
252 protected View generateCourseRequisitesSection(Controller layout) {
253 return new CourseRequirementsViewController(layout, getLabel(LUUIConstants.REQUISITES_LABEL_KEY), CourseSections.COURSE_REQUISITES, false);
254 }
255
256 protected SectionView generateActiveDatesSection() {
257 VerticalSectionView section = initSectionView(CourseSections.ACTIVE_DATES, LUUIConstants.ACTIVE_DATES_LABEL_KEY);
258
259 addField(section, COURSE + "/" + START_TERM, generateMessageInfo(LUUIConstants.START_TERM_LABEL_KEY));
260 addField(section, COURSE + "/" + END_TERM, generateMessageInfo(LUUIConstants.END_TERM_LABEL_KEY));
261 addField(section, COURSE + "/" + PILOT_COURSE, generateMessageInfo(LUUIConstants.PILOT_COURSE_LABEL_KEY), new KSCheckBox(getLabel(LUUIConstants.PILOT_COURSE_TEXT_LABEL_KEY)));
262
263 return section;
264 }
265
266 protected VerticalSection generateActiveDateEndSection() {
267 VerticalSection endDate = initSection(getH3Title(LUUIConstants.END_DATE_LABEL_KEY), WITH_DIVIDER);
268 addField(endDate, COURSE + "/" + EXPIRATION_DATE, generateMessageInfo(LUUIConstants.EXPIRATION_DATE_LABEL_KEY));
269 return endDate;
270 }
271
272 protected VerticalSection generateActiveDateStartSection() {
273 VerticalSection startDate = initSection(getH3Title(LUUIConstants.START_DATE_LABEL_KEY), WITH_DIVIDER);
274 addField(startDate, COURSE + "/" + CreditCourseConstants.EFFECTIVE_DATE, generateMessageInfo(LUUIConstants.EFFECTIVE_DATE_LABEL_KEY));
275 return startDate;
276 }
277
278 protected SectionView generateGovernanceSection() {
279 VerticalSectionView section = initSectionView(CourseSections.GOVERNANCE, LUUIConstants.GOVERNANCE_LABEL_KEY);
280 addField(section, COURSE + "/" + CAMPUS_LOCATIONS, generateMessageInfo(LUUIConstants.CAMPUS_LOCATION_LABEL_KEY));
281 addField(section, COURSE + "/" + CURRICULUM_OVERSIGHT_ORGS_, generateMessageInfo(LUUIConstants.ACADEMIC_SUBJECT_ORGS_KEY));
282 addField(section, COURSE + "/" + ADMIN_ORGS, generateMessageInfo(LUUIConstants.ADMIN_ORG_LABEL_KEY));
283
284 return section;
285 }
286
287 public SectionView generateCourseInfoSection() {
288 VerticalSectionView section = initSectionView(CourseSections.COURSE_INFO, LUUIConstants.INFORMATION_LABEL_KEY);
289 addField(section, PROPOSAL_TITLE_PATH, generateMessageInfo(LUUIConstants.PROPOSAL_TITLE_LABEL_KEY));
290 addField(section, COURSE + "/" + COURSE_TITLE, generateMessageInfo(LUUIConstants.COURSE_TITLE_LABEL_KEY));
291 addField(section, COURSE + "/" + TRANSCRIPT_TITLE, generateMessageInfo(LUUIConstants.SHORT_TITLE_LABEL_KEY));
292 section.addSection(generateCourseNumberSection());
293 FieldDescriptor instructorsFd = addField(section, COURSE + "/" + INSTRUCTORS, generateMessageInfo(LUUIConstants.INSTRUCTORS_LABEL_KEY));
294 instructorsFd.setWidgetBinding(new KeyListModelWigetBinding("personId"));
295 section.addSection(generateDescriptionRationaleSection());
296
297 return section;
298 }
299
300 protected GroupSection generateCourseNumberSection() {
301
302
303 GroupSection courseNumber = new GroupSection(getH4Title(""));
304 courseNumber.addStyleName(LUUIConstants.STYLE_SECTION);
305 courseNumber.addStyleName(LUUIConstants.STYLE_SECTION_DIVIDER);
306 addField(courseNumber, COURSE + "/" + SUBJECT_AREA, generateMessageInfo(LUUIConstants.SUBJECT_CODE_LABEL_KEY));
307 addField(courseNumber, COURSE + "/" + COURSE_NUMBER_SUFFIX, generateMessageInfo(LUUIConstants.COURSE_NUMBER_LABEL_KEY));
308
309
310
311 courseNumber.addSection(generateCrossListed_Ver_Joint_Section());
312
313 return courseNumber;
314 }
315
316 protected CollapsableSection generateCrossListed_Ver_Joint_Section() {
317 CollapsableSection result = new CollapsableSection(getLabel(LUUIConstants.CL_V_J_LABEL_KEY));
318
319
320
321
322 SpanPanel crslabelpan = new SpanPanel();
323 crslabelpan.setStyleName("ks-multiplicity-section-label");
324 crslabelpan.setHTML("Cross Listed Courses");
325 crslabelpan.setVisible(true);
326 result.addWidget(crslabelpan);
327 addMultiplicityFields(result, COURSE + QueryPath.getPathSeparator() + CROSS_LISTINGS,
328 LUUIConstants.ADD_CROSS_LISTED_LABEL_KEY,
329 LUUIConstants.CROSS_LISTED_ITEM_LABEL_KEY,
330 Arrays.asList(
331 new MultiplicityFieldConfig(
332 SUBJECT_AREA,
333 LUUIConstants.SUBJECT_CODE_LABEL_KEY, null, null, true),
334 new MultiplicityFieldConfig(
335 COURSE_NUMBER_SUFFIX,
336 LUUIConstants.COURSE_NUMBER_LABEL_KEY, null, null, true)),
337 null,
338 null,0);
339 SpanPanel jntlabelpan = new SpanPanel();
340 jntlabelpan.setStyleName("ks-multiplicity-section-label");
341 jntlabelpan.setHTML("Jointly Offered Courses");
342 jntlabelpan.setVisible(true);
343 result.addWidget(jntlabelpan);
344 addMultiplicityFields(result, COURSE + QueryPath.getPathSeparator() + JOINTS,
345 LUUIConstants.ADD_EXISTING_LABEL_KEY,
346 LUUIConstants.JOINT_OFFER_ITEM_LABEL_KEY,
347 Arrays.asList(
348 new MultiplicityFieldConfig(
349 CreditCourseJointsConstants.COURSE_ID,
350 LUUIConstants.COURSE_NUMBER_OR_TITLE_LABEL_KEY, null, null, true)),
351 null,
352 null,0);
353 SpanPanel vsnlabelpan = new SpanPanel();
354 vsnlabelpan.setStyleName("ks-multiplicity-section-label");
355 vsnlabelpan.setHTML("Version Codes");
356 vsnlabelpan.setVisible(true);
357 result.addWidget(vsnlabelpan);
358 addMultiplicityFields(result, COURSE + QueryPath.getPathSeparator() + VERSIONS,
359 LUUIConstants.ADD_VERSION_CODE_LABEL_KEY,
360 LUUIConstants.VERSION_CODE_LABEL_KEY,
361 Arrays.asList(
362 new MultiplicityFieldConfig(
363 "variationCode",
364 LUUIConstants.VERSION_CODE_LABEL_KEY, null, null, true),
365 new MultiplicityFieldConfig(
366 "variationTitle",
367 LUUIConstants.TITLE_LABEL_KEY, null, null, true)
368 ),
369 null,
370 null,0);
371 return result;
372 }
373
374 protected void addFeeMultiplicityFields(Section section,
375 String path, String addItemlabelMessageKey,
376 String itemLabelMessageKey, List<MultiplicityFieldConfig> fieldConfigs,
377 Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition,
378 List<String> deletionParentKeys) {
379 MultiplicityConfiguration config = setupMultiplicityConfig(
380 MultiplicityConfiguration.MultiplicityType.GROUP,
381 MultiplicityConfiguration.StyleType.TOP_LEVEL_GROUP,
382 path, addItemlabelMessageKey, itemLabelMessageKey,
383 fieldConfigs, swappableFieldsDefinition, deletionParentKeys);
384 MultiplicitySection ms = null;
385 ms = new MultiplicitySection(config, swappableFieldsDefinition, deletionParentKeys);
386 section.addSection(ms);
387
388 }
389
390 protected MultiplicityConfiguration setupMultiplicityConfig(
391 MultiplicityConfiguration.MultiplicityType multiplicityType,
392 MultiplicityConfiguration.StyleType styleType,
393 String path, String addItemlabelMessageKey,
394 String itemLabelMessageKey, List<MultiplicityFieldConfig> fieldConfigs,
395 Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition,
396 List<String> deletionParentKeys) {
397 QueryPath parentPath = QueryPath.concat(path);
398 MultiplicityConfiguration config = new MultiplicityConfiguration(multiplicityType,
399 styleType, getMetaData(parentPath.toString()));
400 config.setAddItemLabel(getLabel(addItemlabelMessageKey));
401 config.setItemLabel(getLabel(itemLabelMessageKey));
402 config.setUpdateable(true);
403
404 FieldDescriptor parentFd = buildMultiplicityParentFieldDescriptor(path, getLabel(itemLabelMessageKey), null);
405 config.setParent(parentFd);
406
407 if (fieldConfigs != null) {
408 for (MultiplicityFieldConfig fieldConfig : fieldConfigs) {
409 MultiplicityFieldConfiguration fc = buildMultiplicityFD(fieldConfig.getFieldKey(),
410 fieldConfig.getLabelKey(), parentPath.toString());
411 config.addFieldConfiguration(fc);
412 if (fieldConfig.isNextLine()) {
413 config.nextLine();
414 }
415 }
416 }
417 return config;
418 }
419
420 protected MultiplicitySection addMultiplicityFields(Section section,
421 String path, String addItemlabelMessageKey,
422 String itemLabelMessageKey, List<MultiplicityFieldConfig> fieldConfigs,
423 Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition,
424 List<String> deletionParentKeys,int defaultItemsCreated) {
425 MultiplicityConfiguration config = setupMultiplicityConfig(
426 MultiplicityConfiguration.MultiplicityType.GROUP,
427 MultiplicityConfiguration.StyleType.TOP_LEVEL_GROUP,
428 path, addItemlabelMessageKey, itemLabelMessageKey,
429 fieldConfigs, swappableFieldsDefinition, deletionParentKeys);
430 config.setDefaultItemsCreated(defaultItemsCreated);
431 MultiplicitySection ms = null;
432 ms = new MultiplicitySection(config, swappableFieldsDefinition, deletionParentKeys);
433 section.addSection(ms);
434 return ms;
435 }
436
437 protected Metadata getMetaData(String fieldKey) {
438 return modelDefinition.getMetadata(QueryPath.concat(fieldKey));
439 }
440
441 protected MultiplicityFieldConfiguration buildMultiplicityFD(
442 String fieldKey, String labelKey, String parentPath) {
443
444 QueryPath fieldPath = QueryPath.concat(parentPath, QueryPath.getWildCard(), fieldKey);
445 Metadata meta = modelDefinition.getMetadata(fieldPath);
446
447 MultiplicityFieldConfiguration fd = new MultiplicityFieldConfiguration(
448 fieldPath.toString(), generateMessageInfo(labelKey), meta, null);
449
450
451 return fd;
452
453 }
454
455 protected FieldDescriptor buildMultiplicityParentFieldDescriptor(String fieldKey, String messageKey, String parentPath) {
456 QueryPath path = QueryPath.concat(parentPath, fieldKey);
457 Metadata meta = modelDefinition.getMetadata(path);
458
459 FieldDescriptor fd = new FieldDescriptor(path.toString(), generateMessageInfo(messageKey), meta);
460 fd.hideLabel();
461 return fd;
462 }
463
464 protected VerticalSection generateCourseInfoShortTitleSection() {
465 VerticalSection shortTitle = initSection(getH3Title(LUUIConstants.SHORT_TITLE_LABEL_KEY), WITH_DIVIDER);
466 addField(shortTitle, COURSE + "/" + TRANSCRIPT_TITLE, null);
467 return shortTitle;
468 }
469
470 protected VerticalSection generateLongTitleSection() {
471 VerticalSection longTitle = initSection(getH3Title(LUUIConstants.TITLE_LABEL_KEY), WITH_DIVIDER);
472 addField(longTitle, COURSE + "/" + COURSE_TITLE, null);
473 return longTitle;
474 }
475
476 protected VerticalSection generateDescriptionRationaleSection() {
477 SectionTitle title = getH4Title(LUUIConstants.PROPOSAL_TITLE_SECTION_LABEL_KEY);
478 VerticalSection description = initSection(title, !WITH_DIVIDER);
479 title.setStyleName("cluProposalTitleSection");
480
481
482 addField(description, COURSE + "/" + PROPOSAL_DESCRIPTION + "/" + RichTextInfoConstants.PLAIN, generateMessageInfo(LUUIConstants.DESCRIPTION_LABEL_KEY));
483 addField(description, "proposal/rationale", generateMessageInfo(LUUIConstants.PROPOSAL_RATIONALE_LABEL_KEY));
484 return description;
485 }
486
487 public SectionView generateCourseLogisticsSection() {
488 VerticalSectionView section = initSectionView(CourseSections.COURSE_LOGISTICS, LUUIConstants.LOGISTICS_LABEL_KEY);
489 section.setInstructions(getLabel(LUUIConstants.LOGISTICS_LABEL_KEY + "-instruct") + "<br><br>");
490
491 section.addSection(generateSchedulingSection());
492 section.addSection(generateDurationSection());
493 section.addSection(generateLearningResultsSection());
494 section.addSection(generateCourseFormatsSection());
495
496 return section;
497 }
498
499 protected Section generateLearningResultsSection() {
500 VerticalSection learningResults = initSection(getH3Title(LUUIConstants.LEARNING_RESULTS_LABEL_KEY), WITH_DIVIDER);
501 learningResults.setInstructions(getLabel(LUUIConstants.LEARNING_RESULTS_LABEL_KEY + "-instruct") + "<br><br><br>");
502
503 learningResults.addSection(generateGradesAssessmentsSection());
504 learningResults.addSection(generateStudentRegistrationOptionsSection());
505 learningResults.addSection(generateFinalExamSection());
506 learningResults.addSection(generateOutcomesSection());
507
508 return learningResults;
509 }
510
511 protected Section generateOutcomesSection() {
512
513 String path = COURSE + QueryPath.getPathSeparator() + CREDIT_OPTIONS;
514 QueryPath creditTypeFullPath = QueryPath.concat(path, QueryPath.getWildCard(), CreditCourseConstants.TYPE);
515 QueryPath creditOptionFixedFullPath = QueryPath.concat(path, QueryPath.getWildCard(), CREDIT_OPTION_FIXED_CREDITS);
516 QueryPath creditOptionMinFullPath = QueryPath.concat(path, QueryPath.getWildCard(), CREDIT_OPTION_MIN_CREDITS);
517 QueryPath creditOptionMaxFullPath = QueryPath.concat(path, QueryPath.getWildCard(), CREDIT_OPTION_MAX_CREDITS);
518 QueryPath creditResultValuesFullPath = QueryPath.concat(path, QueryPath.getWildCard(), "resultValues");
519
520 VerticalSection courseOutcomes = initSection(getH3Title(LUUIConstants.LEARNING_RESULT_OUTCOME_LABEL_KEY), WITH_DIVIDER);
521 Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition =
522 new HashMap<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>>();
523 SwapCompositeCondition fixedCreditCondition = new SwapCompositeCondition(
524 CompositeConditionOperator.AND);
525 fixedCreditCondition.getChildrenConditions().add(
526 makeCondition(creditTypeFullPath, LUUIConstants.LEARNING_RESULT_OUTCOME_TYPE_LABEL_KEY, "kuali.resultComponentType.credit.degree.fixed")
527 );
528 fixedCreditCondition.setConditionId("1");
529 SwapCompositeCondition multipleCreditCondition = new SwapCompositeCondition(
530 CompositeConditionOperator.AND);
531 multipleCreditCondition.getChildrenConditions().add(
532 makeCondition(creditTypeFullPath, LUUIConstants.LEARNING_RESULT_OUTCOME_TYPE_LABEL_KEY, "kuali.resultComponentType.credit.degree.multiple")
533 );
534 multipleCreditCondition.setConditionId("2");
535 SwapCompositeCondition variableCreditCondition = new SwapCompositeCondition(
536 CompositeConditionOperator.AND);
537 variableCreditCondition.getChildrenConditions().add(
538 makeCondition(creditTypeFullPath, LUUIConstants.LEARNING_RESULT_OUTCOME_TYPE_LABEL_KEY, "kuali.resultComponentType.credit.degree.range")
539 );
540 variableCreditCondition.setConditionId("3");
541
542 swappableFieldsDefinition.put(fixedCreditCondition,
543 Arrays.asList(
544 new SwapCompositeConditionFieldConfig(
545 new MultiplicityFieldConfiguration(
546 creditOptionFixedFullPath.toString(),
547 generateMessageInfo(LUUIConstants.CREDIT_OPTION_FIXED_CREDITS_LABEL_KEY),
548 modelDefinition.getMetadata(creditOptionFixedFullPath),
549 null),
550 null
551 )
552 )
553 );
554 MultiplicityFieldWidgetInitializer multipleCreditInitializer =
555 new MultiplicityFieldWidgetInitializer() {
556 @Override
557 public ModelWidgetBinding<?> getModelWidgetBindingInstance() {
558 return new ListOfStringBinding();
559 }
560 @Override
561 public Widget getNewWidget() {
562 return new ListOfStringWidget("Add Item");
563 }
564 };
565
566 swappableFieldsDefinition.put(multipleCreditCondition,
567 Arrays.asList(
568 new SwapCompositeConditionFieldConfig(
569 new MultiplicityFieldConfiguration(
570 creditResultValuesFullPath.toString(),
571 generateMessageInfo(LUUIConstants.CREDIT_OPTION_FIXED_CREDITS_LABEL_KEY),
572 modelDefinition.getMetadata(creditResultValuesFullPath),
573 multipleCreditInitializer),
574 null
575 )
576 )
577 );
578 swappableFieldsDefinition.put(variableCreditCondition,
579 Arrays.asList(
580 new SwapCompositeConditionFieldConfig(
581 new MultiplicityFieldConfiguration(
582 creditOptionMinFullPath.toString(),
583 generateMessageInfo(LUUIConstants.CREDIT_OPTION_MIN_CREDITS_LABEL_KEY),
584 modelDefinition.getMetadata(creditOptionMinFullPath),
585 null),
586 null
587 ),
588 new SwapCompositeConditionFieldConfig(
589 new MultiplicityFieldConfiguration(
590 creditOptionMaxFullPath.toString(),
591 generateMessageInfo(LUUIConstants.CREDIT_OPTION_MAX_CREDITS_LABEL_KEY),
592 modelDefinition.getMetadata(creditOptionMaxFullPath),
593 null),
594 null
595 )
596 )
597 );
598
599 MultiplicitySection ms = addMultiplicityFields(
600 courseOutcomes,
601 path,
602 LUUIConstants.LEARNING_RESULT_OUTCOME_LABEL_KEY,
603 LUUIConstants.LEARNING_RESULT_OUTCOME_LABEL_KEY,
604 Arrays.asList(
605 new MultiplicityFieldConfig(
606 CreditCourseConstants.TYPE,
607 LUUIConstants.LEARNING_RESULT_OUTCOME_TYPE_LABEL_KEY,
608 null, null, true)
609 ), swappableFieldsDefinition, null,1);
610
611 courseOutcomes.setRequired(ms.getConfig().getParentFd().getFieldElement().getRequiredPanel());
612 return courseOutcomes;
613
614 }
615
616 protected Section generateStudentRegistrationOptionsSection() {
617 VerticalSection studentRegistrationOptionsSection = initSection(getH3Title(LUUIConstants.LEARNING_RESULTS_STUDENT_REGISTRATION_LABEL_KEY), WITH_DIVIDER);
618
619 addField(studentRegistrationOptionsSection, COURSE + "/" + AUDIT, generateMessageInfo(LUUIConstants.LEARNING_RESULT_AUDIT_LABEL_KEY), new KSCheckBox(getLabel(LUUIConstants.LEARNING_RESULT_AUDIT_TEXT_LABEL_KEY)));
620 addField(studentRegistrationOptionsSection, COURSE + "/" + PASS_FAIL, generateMessageInfo(LUUIConstants.LEARNING_RESULT_PASS_FAIL_LABEL_KEY), new KSCheckBox(getLabel(LUUIConstants.LEARNING_RESULT_PASS_FAIL_TEXT_LABEL_KEY)));
621
622 return studentRegistrationOptionsSection;
623 }
624
625 protected Section generateGradesAssessmentsSection() {
626 VerticalSection gradesAssessments = initSection(getH3Title(LUUIConstants.LEARNING_RESULTS_GRADES_ASSESSMENTS_LABEL_KEY), WITH_DIVIDER);
627
628 addField(gradesAssessments, COURSE + "/" + GRADING_OPTIONS, generateMessageInfo(LUUIConstants.LEARNING_RESULT_ASSESSMENT_SCALE_LABEL_KEY));
629
630 return gradesAssessments;
631 }
632
633 protected VerticalSection generateCourseFormatsSection() {
634
635 VerticalSection courseFormats = initSection(getH3Title(LUUIConstants.FORMATS_LABEL_KEY), WITH_DIVIDER);
636 courseFormats.setHelp(getLabel(LUUIConstants.FORMATS_LABEL_KEY + "-help"));
637 courseFormats.setInstructions(getLabel(LUUIConstants.FORMATS_LABEL_KEY + "-instruct"));
638 MultiplicityConfiguration courseFormatConfig = setupMultiplicityConfig(
639 MultiplicityConfiguration.MultiplicityType.GROUP,
640 MultiplicityConfiguration.StyleType.TOP_LEVEL_GROUP,
641 COURSE + "/" + FORMATS, LUUIConstants.COURSE_ADD_FORMAT_LABEL_KEY,
642 LUUIConstants.FORMAT_LABEL_KEY,
643 null, null, null);
644 courseFormatConfig.setDefaultItemsCreated(1);
645 MultiplicityConfiguration activitiesConfig = setupMultiplicityConfig(
646 MultiplicityConfiguration.MultiplicityType.GROUP,
647 MultiplicityConfiguration.StyleType.SUB_LEVEL_GROUP,
648 COURSE + "/" + FORMATS + "/*/" + ACTIVITIES,
649 LUUIConstants.ADD_ACTIVITY_LABEL_KEY,
650 LUUIConstants.ACTIVITY_LITERAL_LABEL_KEY,
651 Arrays.asList(
652 new MultiplicityFieldConfig(
653 ACTIVITY_TYPE,
654 LUUIConstants.ACTIVITY_TYPE_LABEL_KEY,
655 null,
656 null,
657 true),
658 new MultiplicityFieldConfig(
659 CONTACT_HOURS + "/" + "unitQuantity",
660 LUUIConstants.CONTACT_HOURS_LABEL_KEY,
661 null,
662 null,
663 false),
664 new MultiplicityFieldConfig(
665 CONTACT_HOURS + "/" + "unitType",
666 LUUIConstants.CONTACT_HOURS_FREQUENCY_LABEL_KEY,
667 null,
668 null,
669 true),
670 new MultiplicityFieldConfig(
671 CreditCourseActivityConstants.DURATION + "/" + "atpDurationTypeKey",
672 LUUIConstants.COURSE_FORMATS_DURATION_TYPE_LABEL_KEY,
673 null,
674 null,
675 false),
676 new MultiplicityFieldConfig(
677 CreditCourseActivityConstants.DURATION + "/" + "timeQuantity",
678 LUUIConstants.DURATION_QUANTITY_LABEL_KEY,
679 null,
680 null,
681 true),
682 new MultiplicityFieldConfig(
683 DEFAULT_ENROLLMENT_ESTIMATE,
684 LUUIConstants.CLASS_SIZE_LABEL_KEY,
685 null,
686 null,
687 true)
688 ), null, null);
689 activitiesConfig.setDefaultItemsCreated(1);
690 courseFormatConfig.setNestedConfig(activitiesConfig);
691
692
693 MultiplicitySection ms = null;
694 ms = new MultiplicitySection(courseFormatConfig,
695 null, null);
696 courseFormats.addSection(ms);
697 courseFormats.setRequired(courseFormatConfig.getParentFd().getFieldElement().getRequiredPanel());
698 return courseFormats;
699 }
700
701 protected VerticalSection generateSchedulingSection() {
702 VerticalSection scheduling = initSection(getH3Title(LUUIConstants.SCHEDULING_LABEL_KEY), WITH_DIVIDER);
703 addField(scheduling, COURSE + "/" + TERMS_OFFERED, generateMessageInfo(LUUIConstants.TERMS_OFFERED_LABEL_KEY));
704 return scheduling;
705 }
706
707 protected VerticalSection generateDurationSection() {
708 VerticalSection duration = initSection(getH3Title(LUUIConstants.DURATION_LITERAL_LABEL_KEY), WITH_DIVIDER);
709 duration.setInstructions(getLabel(LUUIConstants.DURATION_LITERAL_LABEL_KEY + "-instruct"));
710 GroupSection duration_group = new GroupSection();
711 addField(duration_group, COURSE + "/" + CreditCourseConstants.DURATION + "/" + "atpDurationTypeKey", generateMessageInfo(LUUIConstants.DURATION_TYPE_LABEL_KEY));
712 addField(duration_group, COURSE + "/" + CreditCourseConstants.DURATION + "/" + "timeQuantity", generateMessageInfo(LUUIConstants.DURATION_QUANTITY_LABEL_KEY));
713
714 duration.addSection(duration_group);
715 return duration;
716 }
717
718 protected VerticalSection generateFinalExamSection() {
719 VerticalSection finalExam = initSection(getH3Title(LUUIConstants.FINAL_EXAM_LABEL_KEY), WITH_DIVIDER);
720 GroupSection finalExam_group = new GroupSection();
721 GroupSection finalExamRationale_group = new GroupSection();
722 GroupSection finalExamRationale_group2 = new GroupSection();
723
724 FieldDescriptor field = addField(finalExam_group, COURSE + "/" + CreditCourseConstants.FINAL_EXAM, generateMessageInfo(LUUIConstants.FINAL_EXAM_STATUS_LABEL_KEY));
725
726 if (field.isVisible()){
727 KSSelectItemWidgetAbstract picker = (KSSelectItemWidgetAbstract) (((KSPicker) field.getFieldWidget()).getInputWidget());
728 addField(finalExamRationale_group, COURSE + "/" + CreditCourseConstants.FINAL_EXAM_RATIONALE, generateMessageInfo(LUUIConstants.FINAL_EXAM_RATIONALE_LABEL_KEY));
729 addField(finalExamRationale_group2, COURSE + "/" + CreditCourseConstants.FINAL_EXAM_RATIONALE, generateMessageInfo(LUUIConstants.FINAL_EXAM_RATIONALE_LABEL_KEY));
730 SwapSection swapSection = new SwapSection(picker);
731 swapSection.addSection(finalExamRationale_group, "ALT");
732 swapSection.addSection(finalExamRationale_group2, "None");
733 finalExam.addSection(finalExam_group);
734
735 finalExam.addSection(swapSection);
736 return finalExam;
737 } else {
738 return new VerticalSection();
739 }
740
741 }
742
743 protected VerticalSection generateInstructorsSection() {
744 VerticalSection instructors = initSection(getH3Title(LUUIConstants.INSTRUCTOR_LABEL_KEY), WITH_DIVIDER);
745 addField(instructors, COURSE + "/" + PRIMARY_INSTRUCTOR + "/personId");
746 return instructors;
747 }
748
749 protected SectionView generateLearningObjectivesSection() {
750 VerticalSectionView section = initSectionView(CourseSections.LEARNING_OBJECTIVES, LUUIConstants.LEARNING_OBJECTIVES_LABEL_KEY);
751 section.setInstructions(getLabel(LUUIConstants.LEARNING_OBJECTIVES_LABEL_KEY + "-instruct"));
752 section.addSection(generateLearningObjectivesNestedSection());
753 return section;
754 }
755
756 protected VerticalSection generateLearningObjectivesNestedSection() {
757 final VerticalSection los = initSection(null, NO_DIVIDER);
758
759 QueryPath path = QueryPath.concat(COURSE, COURSE_SPECIFIC_LOS, "*", "loInfo", "desc");
760 Metadata meta = modelDefinition.getMetadata(path);
761
762 LOBuilder loBuilder = new LOBuilder(type, state, groupName, "kuali.loRepository.key.singleUse", COURSE_SPECIFIC_LOS, meta);
763 final FieldDescriptor fd = addField(los, CreditCourseConstants.COURSE_SPECIFIC_LOS, null,loBuilder, COURSE);
764
765 loBuilder.addValueChangeHandler(new ValueChangeHandler<List<OutlineNode<LOPicker>>>(){
766 @Override
767 public void onValueChange(ValueChangeEvent<List<OutlineNode<LOPicker>>> event) {
768 los.setIsDirty(true);
769 fd.setDirty(true);
770 }
771 });
772
773
774
775 fd.setWidgetBinding(LOBuilderBinding.INSTANCE);
776
777 los.addStyleName("KS-LUM-Section-Divider");
778 return los;
779 }
780
781 public class PersonList extends KSDropDown {
782 final SimpleListItems people = new SimpleListItems();
783
784 public PersonList() {
785 final PersonList us = this;
786 final String userId = Application.getApplicationContext().getUserId();
787
788
789 people.addItem(userId, userId);
790 us.setListItems(people);
791 us.selectItem(userId);
792 us.setBlankFirstItem(false);
793 this.setEnabled(false);
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821 }
822
823 @Override
824 public boolean isMultipleSelect() {
825 return true;
826 }
827 }
828
829 public class ProposerPersonList extends KSLabelList {
830 public ProposerPersonList() {
831 SimpleListItems list = new SimpleListItems();
832
833 super.setListItems(list);
834 }
835 }
836
837 protected VerticalSection generateShortTitleSection() {
838 VerticalSection shortTitle = initSection(getH3Title(LUUIConstants.SHORT_TITLE_LABEL_KEY), WITH_DIVIDER);
839 addField(shortTitle, "cluInfo/officialIdentifier/shortName", null);
840 return shortTitle;
841 }
842
843 protected VerticalSectionView initSectionView(Enum<?> viewEnum, String labelKey) {
844 VerticalSectionView section = new VerticalSectionView(viewEnum, getLabel(labelKey), CLU_PROPOSAL_MODEL);
845 section.addStyleName(LUUIConstants.STYLE_SECTION);
846 return section;
847 }
848
849
850 protected VerticalSection initSection(SectionTitle title, boolean withDivider) {
851 VerticalSection section;
852 if (title != null) {
853 section = new VerticalSection(title);
854 } else {
855 section = new VerticalSection();
856 }
857 section.addStyleName(LUUIConstants.STYLE_SECTION);
858 if (withDivider)
859 section.addStyleName(LUUIConstants.STYLE_SECTION_DIVIDER);
860 return section;
861 }
862
863 @Override
864 protected MessageKeyInfo generateMessageInfo(String labelKey) {
865 return new MessageKeyInfo(groupName, type, state, labelKey);
866 }
867
868 protected SectionView generateFinancialsSection() {
869 VerticalSectionView section = initSectionView(CourseSections.FINANCIALS, LUUIConstants.FINANCIALS_LABEL_KEY);
870
871 VerticalSection justiFee = initSection(getH3Title(LUUIConstants.COURSE_FEE_TITLE), WITH_DIVIDER);
872 SpanPanel courseFeeInstruction = new SpanPanel();
873 courseFeeInstruction.setStyleName("ks-form-module-elements-instruction");
874 courseFeeInstruction.setHTML(getLabel(LUUIConstants.COURSE_FEE_TITLE + FieldLayoutComponent.INSTRUCT_MESSAGE_KEY));
875 courseFeeInstruction.setVisible(true);
876 justiFee.addWidget(courseFeeInstruction);
877
878
879
880 addField(justiFee, COURSE + "/" + "feeJustification" + "/" + RichTextInfoConstants.PLAIN, generateMessageInfo(LUUIConstants.JUSTIFICATION_FEE));
881 section.addSection(justiFee);
882 Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition =
883 new HashMap<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>>();
884
885
886
887
888
889
890
891 QueryPath feesPath = QueryPath.concat(COURSE, FEES);
892 QueryPath rateTypeFieldPath = QueryPath.concat(feesPath.toString(), QueryPath.getWildCard(), "rateType");
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266