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 CourseProposalConfigurer 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
121
122 protected DocumentTool documentTool;
123 protected CourseSummaryConfigurer summaryConfigurer;
124
125 protected List<StatementTypeInfo> stmtTypes;
126
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 public void setStatementTypes(List<StatementTypeInfo> stmtTypes) {
136 this.stmtTypes = stmtTypes;
137 }
138
139
140
141
142
143
144
145 public void configure(final CourseProposalController layout) {
146 type = "course";
147 state = DtoConstants.STATE_DRAFT;
148 groupName = LUUIConstants.COURSE_GROUP_NAME;
149
150 if (modelDefinition.getMetadata().isCanEdit()) {
151 addCluStartSection(layout);
152 String sections = getLabel(LUUIConstants.COURSE_SECTIONS);
153
154
155
156
157 layout.addMenu(sections);
158
159
160
161 layout.addMenuItem(sections, (SectionView)generateCourseInfoSection(initSectionView(CourseSections.COURSE_INFO, LUUIConstants.INFORMATION_LABEL_KEY)));
162 layout.addMenuItem(sections, (SectionView)generateGovernanceSection(initSectionView(CourseSections.GOVERNANCE, LUUIConstants.GOVERNANCE_LABEL_KEY)));
163 layout.addMenuItem(sections, (SectionView)generateCourseLogisticsSection(initSectionView(CourseSections.COURSE_LOGISTICS, LUUIConstants.LOGISTICS_LABEL_KEY)));
164 layout.addMenuItem(sections, generateLearningObjectivesSection());
165
166
167 layout.addMenuItem(sections, generateCourseRequisitesSection(layout,true));
168
169
170 layout.addMenuItem(sections, (SectionView)generateActiveDatesSection(initSectionView(CourseSections.ACTIVE_DATES, LUUIConstants.ACTIVE_DATES_LABEL_KEY)));
171 layout.addMenuItem(sections, (SectionView)generateFinancialsSection(initSectionView(CourseSections.FINANCIALS, LUUIConstants.FINANCIALS_LABEL_KEY)));
172
173
174 layout.addMenuItem(sections, new CollaboratorSectionView(CourseSections.PEOPLE_PERMISSONS, LUUIConstants.SECTION_AUTHORS_AND_COLLABORATORS,COURSE_PROPOSAL_MODEL));
175
176
177 documentTool = new DocumentTool(LUUIConstants.REF_DOC_RELATION_PROPOSAL_TYPE,CourseSections.DOCUMENTS, getLabel(LUUIConstants.TOOL_DOCUMENTS_LABEL_KEY));
178 documentTool.setModelDefinition((DataModelDefinition)modelDefinition);
179 layout.addMenuItem(sections, documentTool);
180
181
182 summaryConfigurer = new CourseSummaryConfigurer(type, state, groupName,(DataModelDefinition)modelDefinition, stmtTypes, (Controller)layout, COURSE_PROPOSAL_MODEL);
183 layout.addSpecialMenuItem(summaryConfigurer.generateProposalSummarySection(true), "Review and Submit");
184
185
186 List<Enum<?>> excludedViews = new ArrayList<Enum<?>>();
187 excludedViews.add(CourseSections.DOCUMENTS);
188 excludedViews.add(CourseSections.COURSE_REQUISITES);
189 layout.addCommonButton(LUUIConstants.COURSE_SECTIONS, layout.getSaveButton(), excludedViews);
190 layout.addCommonButton(LUUIConstants.COURSE_SECTIONS, layout.getCancelButton(CourseSections.SUMMARY), excludedViews);
191
192
193
194 layout.addButtonForView(CourseSections.DOCUMENTS, getContinueButton(layout));
195 }
196 else{
197 CourseSummaryConfigurer summaryConfigurer = new CourseSummaryConfigurer(type, state, groupName, (DataModelDefinition)modelDefinition, stmtTypes, (Controller)layout, COURSE_PROPOSAL_MODEL);
198 layout.removeMenuNavigation();
199 layout.addView(summaryConfigurer.generateProposalSummarySection(false));
200 }
201 layout.showPrint(true);
202 layout.setDefaultView(CourseSections.SUMMARY);
203 layout.addContentWidget(layout.getWfUtilities().getWorkflowStatusLabel());
204 final CommentTool commentTool = new CommentTool(CourseSections.COMMENTS, getLabel(LUUIConstants.TOOL_COMMENTS_LABEL_KEY), "kuali.comment.type.generalRemarks", "Proposal Comments");
205 commentTool.setController(layout);
206
207 layout.addContentWidget(new KSButton("Comments", ButtonStyle.DEFAULT_ANCHOR, new ClickHandler() {
208
209 @Override
210 public void onClick(ClickEvent event) {
211 commentTool.show();
212 }
213 }));
214
215
216 final DecisionPanel decisionPanel = new DecisionPanel(CourseSections.DECISIONS, getLabel(LUUIConstants.TOOL_DECISION_LABEL_KEY), "kuali.comment.type.generalRemarks");
217 layout.addView(decisionPanel);
218 layout.addContentWidget(new KSButton("Decisions", ButtonStyle.DEFAULT_ANCHOR, new ClickHandler() {
219
220 @Override
221 public void onClick(ClickEvent event) {
222 decisionPanel.show();
223 }
224 }));
225
226 }
227
228 protected KSButton getContinueButton(final CourseProposalController layout){
229 return new KSButton("Continue", new ClickHandler(){
230 public void onClick(ClickEvent event) {
231 layout.showNextViewOnMenu();
232 }
233 });
234 }
235
236 public void addCluStartSection(CourseProposalController layout) {
237 VerticalSectionView section = initSectionView(CourseSections.CLU_BEGIN, LUUIConstants.START_LABEL_KEY);
238 section.setController(layout);
239 addField(section, PROPOSAL_TITLE_PATH, generateMessageInfo(LUUIConstants.PROPOSAL_TITLE_LABEL_KEY));
240 addField(section, COURSE + "/" + COURSE_TITLE, generateMessageInfo(LUUIConstants.COURSE_TITLE_LABEL_KEY));
241
242
243 layout.addStartViewPopup(section);
244 layout.getStartPopup().setMaxHeight(600);
245 }
246
247 protected View generateCourseRequisitesSection(Controller layout, boolean showSaveButtons) {
248 return new CourseRequirementsViewController(layout, getLabel(LUUIConstants.REQUISITES_LABEL_KEY), CourseSections.COURSE_REQUISITES, false, showSaveButtons);
249 }
250
251 protected Section generateActiveDatesSection(Section section) {
252
253 addField(section, COURSE + "/" + START_TERM, generateMessageInfo(LUUIConstants.START_TERM_LABEL_KEY));
254 addField(section, COURSE + "/" + END_TERM, generateMessageInfo(LUUIConstants.END_TERM_LABEL_KEY));
255 addField(section, COURSE + "/" + PILOT_COURSE, generateMessageInfo(LUUIConstants.PILOT_COURSE_LABEL_KEY), new KSCheckBox(getLabel(LUUIConstants.PILOT_COURSE_TEXT_LABEL_KEY)));
256
257 return section;
258 }
259
260 protected VerticalSection generateActiveDateEndSection() {
261 VerticalSection endDate = initSection(getH3Title(LUUIConstants.END_DATE_LABEL_KEY), WITH_DIVIDER);
262 addField(endDate, COURSE + "/" + EXPIRATION_DATE, generateMessageInfo(LUUIConstants.EXPIRATION_DATE_LABEL_KEY));
263 return endDate;
264 }
265
266 protected VerticalSection generateActiveDateStartSection() {
267 VerticalSection startDate = initSection(getH3Title(LUUIConstants.START_DATE_LABEL_KEY), WITH_DIVIDER);
268 addField(startDate, COURSE + "/" + CreditCourseConstants.EFFECTIVE_DATE, generateMessageInfo(LUUIConstants.EFFECTIVE_DATE_LABEL_KEY));
269 return startDate;
270 }
271
272 protected Section generateGovernanceSection(Section section) {
273 addField(section, COURSE + "/" + CAMPUS_LOCATIONS, generateMessageInfo(LUUIConstants.CAMPUS_LOCATION_LABEL_KEY));
274 addField(section, COURSE + "/" + CURRICULUM_OVERSIGHT_ORGS_, generateMessageInfo(LUUIConstants.ACADEMIC_SUBJECT_ORGS_KEY));
275 addField(section, COURSE + "/" + ADMIN_ORGS, generateMessageInfo(LUUIConstants.ADMIN_ORG_LABEL_KEY));
276
277 return section;
278 }
279
280 public Section generateCourseInfoSection(Section section) {
281 addField(section, PROPOSAL_TITLE_PATH, generateMessageInfo(LUUIConstants.PROPOSAL_TITLE_LABEL_KEY));
282 addField(section, COURSE + "/" + COURSE_TITLE, generateMessageInfo(LUUIConstants.COURSE_TITLE_LABEL_KEY));
283 addField(section, COURSE + "/" + TRANSCRIPT_TITLE, generateMessageInfo(LUUIConstants.SHORT_TITLE_LABEL_KEY));
284 section.addSection(generateCourseNumberSection());
285 FieldDescriptor instructorsFd = addField(section, COURSE + "/" + INSTRUCTORS, generateMessageInfo(LUUIConstants.INSTRUCTORS_LABEL_KEY));
286 instructorsFd.setWidgetBinding(new KeyListModelWigetBinding("personId"));
287
288 section.addSection(generateDescriptionRationaleSection());
289
290 return section;
291 }
292
293
294 protected GroupSection generateCourseNumberSection() {
295
296
297 GroupSection courseNumber = new GroupSection(getH4Title(""));
298 courseNumber.addStyleName(LUUIConstants.STYLE_SECTION);
299 courseNumber.addStyleName(LUUIConstants.STYLE_SECTION_DIVIDER);
300 addField(courseNumber, COURSE + "/" + SUBJECT_AREA, generateMessageInfo(LUUIConstants.SUBJECT_CODE_LABEL_KEY));
301 addField(courseNumber, COURSE + "/" + COURSE_NUMBER_SUFFIX, generateMessageInfo(LUUIConstants.COURSE_NUMBER_LABEL_KEY));
302
303
304
305 courseNumber.addSection(generateCrossListed_Ver_Joint_Section());
306
307 return courseNumber;
308 }
309
310 protected CollapsableSection generateCrossListed_Ver_Joint_Section() {
311 CollapsableSection result = new CollapsableSection(getLabel(LUUIConstants.CL_V_J_LABEL_KEY));
312
313
314
315
316 SpanPanel crslabelpan = new SpanPanel();
317 crslabelpan.setStyleName("ks-multiplicity-section-label");
318 crslabelpan.setHTML("Cross Listed Courses");
319 crslabelpan.setVisible(true);
320 result.addWidget(crslabelpan);
321 addMultiplicityFields(result, COURSE + QueryPath.getPathSeparator() + CROSS_LISTINGS,
322 LUUIConstants.ADD_CROSS_LISTED_LABEL_KEY,
323 LUUIConstants.CROSS_LISTED_ITEM_LABEL_KEY,
324 Arrays.asList(
325 new MultiplicityFieldConfig(
326 SUBJECT_AREA,
327 LUUIConstants.SUBJECT_CODE_LABEL_KEY, null, null, true),
328 new MultiplicityFieldConfig(
329 COURSE_NUMBER_SUFFIX,
330 LUUIConstants.COURSE_NUMBER_LABEL_KEY, null, null, true)),
331 null,
332 null,0);
333 SpanPanel jntlabelpan = new SpanPanel();
334 jntlabelpan.setStyleName("ks-multiplicity-section-label");
335 jntlabelpan.setHTML("Jointly Offered Courses");
336 jntlabelpan.setVisible(true);
337 result.addWidget(jntlabelpan);
338 addMultiplicityFields(result, COURSE + QueryPath.getPathSeparator() + JOINTS,
339 LUUIConstants.ADD_EXISTING_LABEL_KEY,
340 LUUIConstants.JOINT_OFFER_ITEM_LABEL_KEY,
341 Arrays.asList(
342 new MultiplicityFieldConfig(
343 CreditCourseJointsConstants.COURSE_ID,
344 LUUIConstants.COURSE_NUMBER_OR_TITLE_LABEL_KEY, null, null, true)),
345 null,
346 null,0);
347 SpanPanel vsnlabelpan = new SpanPanel();
348 vsnlabelpan.setStyleName("ks-multiplicity-section-label");
349 vsnlabelpan.setHTML("Version Codes");
350 vsnlabelpan.setVisible(true);
351 result.addWidget(vsnlabelpan);
352 addMultiplicityFields(result, COURSE + QueryPath.getPathSeparator() + VERSIONS,
353 LUUIConstants.ADD_VERSION_CODE_LABEL_KEY,
354 LUUIConstants.VERSION_CODE_LABEL_KEY,
355 Arrays.asList(
356 new MultiplicityFieldConfig(
357 "variationCode",
358 LUUIConstants.VERSION_CODE_LABEL_KEY, null, null, true),
359 new MultiplicityFieldConfig(
360 "variationTitle",
361 LUUIConstants.TITLE_LABEL_KEY, null, null, true)
362 ),
363 null,
364 null,0);
365 return result;
366 }
367
368 protected void addFeeMultiplicityFields(Section section,
369 String path, String addItemlabelMessageKey,
370 String itemLabelMessageKey, List<MultiplicityFieldConfig> fieldConfigs,
371 Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition,
372 List<String> deletionParentKeys) {
373 MultiplicityConfiguration config = setupMultiplicityConfig(
374 MultiplicityConfiguration.MultiplicityType.GROUP,
375 MultiplicityConfiguration.StyleType.TOP_LEVEL_GROUP,
376 path, addItemlabelMessageKey, itemLabelMessageKey,
377 fieldConfigs, swappableFieldsDefinition, deletionParentKeys);
378 MultiplicitySection ms = null;
379 ms = new MultiplicitySection(config, swappableFieldsDefinition, deletionParentKeys);
380 section.addSection(ms);
381
382 }
383
384 protected MultiplicityConfiguration setupMultiplicityConfig(
385 MultiplicityConfiguration.MultiplicityType multiplicityType,
386 MultiplicityConfiguration.StyleType styleType,
387 String path, String addItemlabelMessageKey,
388 String itemLabelMessageKey, List<MultiplicityFieldConfig> fieldConfigs,
389 Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition,
390 List<String> deletionParentKeys) {
391 QueryPath parentPath = QueryPath.concat(path);
392 MultiplicityConfiguration config = new MultiplicityConfiguration(multiplicityType,
393 styleType, getMetaData(parentPath.toString()));
394 config.setAddItemLabel(getLabel(addItemlabelMessageKey));
395 config.setItemLabel(getLabel(itemLabelMessageKey));
396 config.setUpdateable(true);
397
398 FieldDescriptor parentFd = buildMultiplicityParentFieldDescriptor(path, getLabel(itemLabelMessageKey), null);
399 config.setParent(parentFd);
400
401 if (fieldConfigs != null) {
402 for (MultiplicityFieldConfig fieldConfig : fieldConfigs) {
403 MultiplicityFieldConfiguration fc = buildMultiplicityFD(fieldConfig.getFieldKey(),
404 fieldConfig.getLabelKey(), parentPath.toString());
405 config.addFieldConfiguration(fc);
406 if (fieldConfig.isNextLine()) {
407 config.nextLine();
408 }
409 }
410 }
411 return config;
412 }
413
414 protected MultiplicitySection addMultiplicityFields(Section section,
415 String path, String addItemlabelMessageKey,
416 String itemLabelMessageKey, List<MultiplicityFieldConfig> fieldConfigs,
417 Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition,
418 List<String> deletionParentKeys,int defaultItemsCreated) {
419 MultiplicityConfiguration config = setupMultiplicityConfig(
420 MultiplicityConfiguration.MultiplicityType.GROUP,
421 MultiplicityConfiguration.StyleType.TOP_LEVEL_GROUP,
422 path, addItemlabelMessageKey, itemLabelMessageKey,
423 fieldConfigs, swappableFieldsDefinition, deletionParentKeys);
424 config.setDefaultItemsCreated(defaultItemsCreated);
425 MultiplicitySection ms = null;
426 ms = new MultiplicitySection(config, swappableFieldsDefinition, deletionParentKeys);
427 section.addSection(ms);
428 return ms;
429 }
430
431 protected Metadata getMetaData(String fieldKey) {
432 return modelDefinition.getMetadata(QueryPath.concat(fieldKey));
433 }
434
435 protected MultiplicityFieldConfiguration buildMultiplicityFD(
436 String fieldKey, String labelKey, String parentPath) {
437
438 QueryPath fieldPath = QueryPath.concat(parentPath, QueryPath.getWildCard(), fieldKey);
439 Metadata meta = modelDefinition.getMetadata(fieldPath);
440
441 MultiplicityFieldConfiguration fd = new MultiplicityFieldConfiguration(
442 fieldPath.toString(), generateMessageInfo(labelKey), meta, null);
443
444
445 return fd;
446
447 }
448
449 protected FieldDescriptor buildMultiplicityParentFieldDescriptor(String fieldKey, String messageKey, String parentPath) {
450 QueryPath path = QueryPath.concat(parentPath, fieldKey);
451 Metadata meta = modelDefinition.getMetadata(path);
452
453 FieldDescriptor fd = new FieldDescriptor(path.toString(), generateMessageInfo(messageKey), meta);
454 fd.hideLabel();
455 return fd;
456 }
457
458 protected VerticalSection generateCourseInfoShortTitleSection() {
459 VerticalSection shortTitle = initSection(getH3Title(LUUIConstants.SHORT_TITLE_LABEL_KEY), WITH_DIVIDER);
460 addField(shortTitle, COURSE + "/" + TRANSCRIPT_TITLE, null);
461 return shortTitle;
462 }
463
464 protected VerticalSection generateLongTitleSection() {
465 VerticalSection longTitle = initSection(getH3Title(LUUIConstants.TITLE_LABEL_KEY), WITH_DIVIDER);
466 addField(longTitle, COURSE + "/" + COURSE_TITLE, null);
467 return longTitle;
468 }
469
470 protected VerticalSection generateDescriptionRationaleSection() {
471 SectionTitle title = getH4Title(LUUIConstants.PROPOSAL_TITLE_SECTION_LABEL_KEY);
472 VerticalSection description = initSection(title, !WITH_DIVIDER);
473 title.setStyleName("cluProposalTitleSection");
474
475
476 addField(description, COURSE + "/" + DESCRIPTION + "/" + RichTextInfoConstants.PLAIN, generateMessageInfo(LUUIConstants.DESCRIPTION_LABEL_KEY));
477 addField(description, "proposal/rationale", generateMessageInfo(LUUIConstants.PROPOSAL_RATIONALE_LABEL_KEY));
478 return description;
479 }
480
481 public Section generateCourseLogisticsSection(Section section) {
482 if (section instanceof SectionView){
483 ((SectionView)section).setInstructions(getLabel(LUUIConstants.LOGISTICS_LABEL_KEY + "-instruct") + "<br><br>");
484 }
485
486 section.addSection(generateSchedulingSection());
487 section.addSection(generateDurationSection());
488 section.addSection(generateLearningResultsSection());
489 section.addSection(generateCourseFormatsSection());
490
491 return section;
492 }
493
494 protected Section generateLearningResultsSection() {
495 VerticalSection learningResults = initSection(getH3Title(LUUIConstants.LEARNING_RESULTS_LABEL_KEY), WITH_DIVIDER);
496 learningResults.setInstructions(getLabel(LUUIConstants.LEARNING_RESULTS_LABEL_KEY + "-instruct") + "<br><br><br>");
497
498 learningResults.addSection(generateGradesAssessmentsSection());
499 learningResults.addSection(generateStudentRegistrationOptionsSection());
500 learningResults.addSection(generateFinalExamSection());
501 learningResults.addSection(generateOutcomesSection());
502
503 return learningResults;
504 }
505
506 protected Section generateOutcomesSection() {
507
508 String path = COURSE + QueryPath.getPathSeparator() + CREDIT_OPTIONS;
509 QueryPath creditTypeFullPath = QueryPath.concat(path, QueryPath.getWildCard(), CreditCourseConstants.TYPE);
510 QueryPath creditOptionFixedFullPath = QueryPath.concat(path, QueryPath.getWildCard(), CREDIT_OPTION_FIXED_CREDITS);
511 QueryPath creditOptionMinFullPath = QueryPath.concat(path, QueryPath.getWildCard(), CREDIT_OPTION_MIN_CREDITS);
512 QueryPath creditOptionMaxFullPath = QueryPath.concat(path, QueryPath.getWildCard(), CREDIT_OPTION_MAX_CREDITS);
513 QueryPath creditResultValuesFullPath = QueryPath.concat(path, QueryPath.getWildCard(), "resultValues");
514
515 VerticalSection courseOutcomes = initSection(getH3Title(LUUIConstants.LEARNING_RESULT_OUTCOME_LABEL_KEY), WITH_DIVIDER);
516 Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition =
517 new HashMap<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>>();
518 SwapCompositeCondition fixedCreditCondition = new SwapCompositeCondition(
519 CompositeConditionOperator.AND);
520 fixedCreditCondition.getChildrenConditions().add(
521 makeCondition(creditTypeFullPath, LUUIConstants.LEARNING_RESULT_OUTCOME_TYPE_LABEL_KEY, "kuali.resultComponentType.credit.degree.fixed")
522 );
523 fixedCreditCondition.setConditionId("1");
524 SwapCompositeCondition multipleCreditCondition = new SwapCompositeCondition(
525 CompositeConditionOperator.AND);
526 multipleCreditCondition.getChildrenConditions().add(
527 makeCondition(creditTypeFullPath, LUUIConstants.LEARNING_RESULT_OUTCOME_TYPE_LABEL_KEY, "kuali.resultComponentType.credit.degree.multiple")
528 );
529 multipleCreditCondition.setConditionId("2");
530 SwapCompositeCondition variableCreditCondition = new SwapCompositeCondition(
531 CompositeConditionOperator.AND);
532 variableCreditCondition.getChildrenConditions().add(
533 makeCondition(creditTypeFullPath, LUUIConstants.LEARNING_RESULT_OUTCOME_TYPE_LABEL_KEY, "kuali.resultComponentType.credit.degree.range")
534 );
535 variableCreditCondition.setConditionId("3");
536
537 swappableFieldsDefinition.put(fixedCreditCondition,
538 Arrays.asList(
539 new SwapCompositeConditionFieldConfig(
540 new MultiplicityFieldConfiguration(
541 creditOptionFixedFullPath.toString(),
542 generateMessageInfo(LUUIConstants.CREDIT_OPTION_FIXED_CREDITS_LABEL_KEY),
543 modelDefinition.getMetadata(creditOptionFixedFullPath),
544 null),
545 null
546 )
547 )
548 );
549 MultiplicityFieldWidgetInitializer multipleCreditInitializer =
550 new MultiplicityFieldWidgetInitializer() {
551 @Override
552 public ModelWidgetBinding<?> getModelWidgetBindingInstance() {
553 return new ListOfStringBinding();
554 }
555 @Override
556 public Widget getNewWidget() {
557 return new ListOfStringWidget("Add Item");
558 }
559 };
560
561 swappableFieldsDefinition.put(multipleCreditCondition,
562 Arrays.asList(
563 new SwapCompositeConditionFieldConfig(
564 new MultiplicityFieldConfiguration(
565 creditResultValuesFullPath.toString(),
566 generateMessageInfo(LUUIConstants.CREDIT_OPTION_FIXED_CREDITS_LABEL_KEY),
567 modelDefinition.getMetadata(creditResultValuesFullPath),
568 multipleCreditInitializer),
569 null
570 )
571 )
572 );
573 swappableFieldsDefinition.put(variableCreditCondition,
574 Arrays.asList(
575 new SwapCompositeConditionFieldConfig(
576 new MultiplicityFieldConfiguration(
577 creditOptionMinFullPath.toString(),
578 generateMessageInfo(LUUIConstants.CREDIT_OPTION_MIN_CREDITS_LABEL_KEY),
579 modelDefinition.getMetadata(creditOptionMinFullPath),
580 null),
581 null
582 ),
583 new SwapCompositeConditionFieldConfig(
584 new MultiplicityFieldConfiguration(
585 creditOptionMaxFullPath.toString(),
586 generateMessageInfo(LUUIConstants.CREDIT_OPTION_MAX_CREDITS_LABEL_KEY),
587 modelDefinition.getMetadata(creditOptionMaxFullPath),
588 null),
589 null
590 )
591 )
592 );
593
594 MultiplicitySection ms = addMultiplicityFields(
595 courseOutcomes,
596 path,
597 LUUIConstants.LEARNING_RESULT_OUTCOME_LABEL_KEY,
598 LUUIConstants.LEARNING_RESULT_OUTCOME_LABEL_KEY,
599 Arrays.asList(
600 new MultiplicityFieldConfig(
601 CreditCourseConstants.TYPE,
602 LUUIConstants.LEARNING_RESULT_OUTCOME_TYPE_LABEL_KEY,
603 null, null, true)
604 ), swappableFieldsDefinition, null,1);
605
606 courseOutcomes.setRequired(ms.getConfig().getParentFd().getFieldElement().getRequiredPanel());
607 return courseOutcomes;
608
609 }
610
611 protected Section generateStudentRegistrationOptionsSection() {
612 VerticalSection studentRegistrationOptionsSection = initSection(getH3Title(LUUIConstants.LEARNING_RESULTS_STUDENT_REGISTRATION_LABEL_KEY), WITH_DIVIDER);
613
614 addField(studentRegistrationOptionsSection, COURSE + "/" + AUDIT, generateMessageInfo(LUUIConstants.LEARNING_RESULT_AUDIT_LABEL_KEY), new KSCheckBox(getLabel(LUUIConstants.LEARNING_RESULT_AUDIT_TEXT_LABEL_KEY)));
615 addField(studentRegistrationOptionsSection, COURSE + "/" + PASS_FAIL, generateMessageInfo(LUUIConstants.LEARNING_RESULT_PASS_FAIL_LABEL_KEY), new KSCheckBox(getLabel(LUUIConstants.LEARNING_RESULT_PASS_FAIL_TEXT_LABEL_KEY)));
616
617 return studentRegistrationOptionsSection;
618 }
619
620 protected Section generateGradesAssessmentsSection() {
621 VerticalSection gradesAssessments = initSection(getH3Title(LUUIConstants.LEARNING_RESULTS_GRADES_ASSESSMENTS_LABEL_KEY), WITH_DIVIDER);
622
623 addField(gradesAssessments, COURSE + "/" + GRADING_OPTIONS, generateMessageInfo(LUUIConstants.LEARNING_RESULT_ASSESSMENT_SCALE_LABEL_KEY));
624
625 return gradesAssessments;
626 }
627
628 protected VerticalSection generateCourseFormatsSection() {
629
630 VerticalSection courseFormats = initSection(getH3Title(LUUIConstants.FORMATS_LABEL_KEY), WITH_DIVIDER);
631 courseFormats.setHelp(getLabel(LUUIConstants.FORMATS_LABEL_KEY + "-help"));
632 courseFormats.setInstructions(getLabel(LUUIConstants.FORMATS_LABEL_KEY + "-instruct"));
633 MultiplicityConfiguration courseFormatConfig = setupMultiplicityConfig(
634 MultiplicityConfiguration.MultiplicityType.GROUP,
635 MultiplicityConfiguration.StyleType.TOP_LEVEL_GROUP,
636 COURSE + "/" + FORMATS, LUUIConstants.COURSE_ADD_FORMAT_LABEL_KEY,
637 LUUIConstants.FORMAT_LABEL_KEY,
638 null, null, null);
639 courseFormatConfig.setDefaultItemsCreated(1);
640 MultiplicityConfiguration activitiesConfig = setupMultiplicityConfig(
641 MultiplicityConfiguration.MultiplicityType.GROUP,
642 MultiplicityConfiguration.StyleType.SUB_LEVEL_GROUP,
643 COURSE + "/" + FORMATS + "/*/" + ACTIVITIES,
644 LUUIConstants.ADD_ACTIVITY_LABEL_KEY,
645 LUUIConstants.ACTIVITY_LITERAL_LABEL_KEY,
646 Arrays.asList(
647 new MultiplicityFieldConfig(
648 ACTIVITY_TYPE,
649 LUUIConstants.ACTIVITY_TYPE_LABEL_KEY,
650 null,
651 null,
652 true),
653 new MultiplicityFieldConfig(
654 CONTACT_HOURS + "/" + "unitQuantity",
655 LUUIConstants.CONTACT_HOURS_LABEL_KEY,
656 null,
657 null,
658 false),
659 new MultiplicityFieldConfig(
660 CONTACT_HOURS + "/" + "unitType",
661 LUUIConstants.CONTACT_HOURS_FREQUENCY_LABEL_KEY,
662 null,
663 null,
664 true),
665 new MultiplicityFieldConfig(
666 CreditCourseActivityConstants.DURATION + "/" + "atpDurationTypeKey",
667 LUUIConstants.COURSE_FORMATS_DURATION_TYPE_LABEL_KEY,
668 null,
669 null,
670 false),
671 new MultiplicityFieldConfig(
672 CreditCourseActivityConstants.DURATION + "/" + "timeQuantity",
673 LUUIConstants.DURATION_QUANTITY_LABEL_KEY,
674 null,
675 null,
676 true),
677 new MultiplicityFieldConfig(
678 DEFAULT_ENROLLMENT_ESTIMATE,
679 LUUIConstants.CLASS_SIZE_LABEL_KEY,
680 null,
681 null,
682 true)
683 ), null, null);
684 activitiesConfig.setDefaultItemsCreated(1);
685 courseFormatConfig.setNestedConfig(activitiesConfig);
686
687
688 MultiplicitySection ms = null;
689 ms = new MultiplicitySection(courseFormatConfig,
690 null, null);
691 courseFormats.addSection(ms);
692 courseFormats.setRequired(courseFormatConfig.getParentFd().getFieldElement().getRequiredPanel());
693 return courseFormats;
694 }
695
696 protected VerticalSection generateSchedulingSection() {
697 VerticalSection scheduling = initSection(getH3Title(LUUIConstants.SCHEDULING_LABEL_KEY), WITH_DIVIDER);
698 addField(scheduling, COURSE + "/" + TERMS_OFFERED, generateMessageInfo(LUUIConstants.TERMS_OFFERED_LABEL_KEY));
699 return scheduling;
700 }
701
702 protected VerticalSection generateDurationSection() {
703 VerticalSection duration = initSection(getH3Title(LUUIConstants.DURATION_LITERAL_LABEL_KEY), WITH_DIVIDER);
704 duration.setInstructions(getLabel(LUUIConstants.DURATION_LITERAL_LABEL_KEY + "-instruct"));
705 GroupSection duration_group = new GroupSection();
706 addField(duration_group, COURSE + "/" + CreditCourseConstants.DURATION + "/" + "atpDurationTypeKey", generateMessageInfo(LUUIConstants.DURATION_TYPE_LABEL_KEY));
707 addField(duration_group, COURSE + "/" + CreditCourseConstants.DURATION + "/" + "timeQuantity", generateMessageInfo(LUUIConstants.DURATION_QUANTITY_LABEL_KEY));
708
709 duration.addSection(duration_group);
710 return duration;
711 }
712
713 protected VerticalSection generateFinalExamSection() {
714 VerticalSection finalExam = initSection(getH3Title(LUUIConstants.FINAL_EXAM_LABEL_KEY), WITH_DIVIDER);
715 GroupSection finalExam_group = new GroupSection();
716 GroupSection finalExamRationale_group = new GroupSection();
717 GroupSection finalExamRationale_group2 = new GroupSection();
718
719 FieldDescriptor field = addField(finalExam_group, COURSE + "/" + CreditCourseConstants.FINAL_EXAM, generateMessageInfo(LUUIConstants.FINAL_EXAM_STATUS_LABEL_KEY));
720
721 if (field.isVisible()){
722 KSSelectItemWidgetAbstract picker = (KSSelectItemWidgetAbstract) (((KSPicker) field.getFieldWidget()).getInputWidget());
723 addField(finalExamRationale_group, COURSE + "/" + CreditCourseConstants.FINAL_EXAM_RATIONALE, generateMessageInfo(LUUIConstants.FINAL_EXAM_RATIONALE_LABEL_KEY));
724 addField(finalExamRationale_group2, COURSE + "/" + CreditCourseConstants.FINAL_EXAM_RATIONALE, generateMessageInfo(LUUIConstants.FINAL_EXAM_RATIONALE_LABEL_KEY));
725 SwapSection swapSection = new SwapSection(picker);
726 swapSection.addSection(finalExamRationale_group, "ALT");
727 swapSection.addSection(finalExamRationale_group2, "None");
728 finalExam.addSection(finalExam_group);
729
730 finalExam.addSection(swapSection);
731 return finalExam;
732 } else {
733 return new VerticalSection();
734 }
735
736 }
737
738 protected VerticalSection generateInstructorsSection() {
739 VerticalSection instructors = initSection(getH3Title(LUUIConstants.INSTRUCTOR_LABEL_KEY), WITH_DIVIDER);
740 addField(instructors, COURSE + "/" + PRIMARY_INSTRUCTOR + "/personId");
741 return instructors;
742 }
743
744 protected SectionView generateLearningObjectivesSection() {
745 VerticalSectionView section = initSectionView(CourseSections.LEARNING_OBJECTIVES, LUUIConstants.LEARNING_OBJECTIVES_LABEL_KEY);
746 section.setInstructions(getLabel(LUUIConstants.LEARNING_OBJECTIVES_LABEL_KEY + "-instruct"));
747 section.addSection(generateLearningObjectivesNestedSection());
748 return section;
749 }
750
751 protected VerticalSection generateLearningObjectivesNestedSection() {
752 final VerticalSection los = initSection(null, NO_DIVIDER);
753
754 QueryPath path = QueryPath.concat(COURSE, COURSE_SPECIFIC_LOS, "*", "loInfo", "desc");
755 Metadata meta = modelDefinition.getMetadata(path);
756
757 LOBuilder loBuilder = new LOBuilder(type, state, groupName, "kuali.loRepository.key.singleUse", COURSE_SPECIFIC_LOS, meta);
758 final FieldDescriptor fd = addField(los, CreditCourseConstants.COURSE_SPECIFIC_LOS, null,loBuilder, COURSE);
759
760 loBuilder.addValueChangeHandler(new ValueChangeHandler<List<OutlineNode<LOPicker>>>(){
761 @Override
762 public void onValueChange(ValueChangeEvent<List<OutlineNode<LOPicker>>> event) {
763 los.setIsDirty(true);
764 fd.setDirty(true);
765 }
766 });
767
768
769
770 fd.setWidgetBinding(LOBuilderBinding.INSTANCE);
771
772 los.addStyleName("KS-LUM-Section-Divider");
773 return los;
774 }
775
776 public class PersonList extends KSDropDown {
777 final SimpleListItems people = new SimpleListItems();
778
779 public PersonList() {
780 final PersonList us = this;
781 final String userId = Application.getApplicationContext().getUserId();
782
783
784 people.addItem(userId, userId);
785 us.setListItems(people);
786 us.selectItem(userId);
787 us.setBlankFirstItem(false);
788 this.setEnabled(false);
789
790
791
792
793
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 @Override
819 public boolean isMultipleSelect() {
820 return true;
821 }
822 }
823
824 public class ProposerPersonList extends KSLabelList {
825 public ProposerPersonList() {
826 SimpleListItems list = new SimpleListItems();
827
828 super.setListItems(list);
829 }
830 }
831
832 protected VerticalSection generateShortTitleSection() {
833 VerticalSection shortTitle = initSection(getH3Title(LUUIConstants.SHORT_TITLE_LABEL_KEY), WITH_DIVIDER);
834 addField(shortTitle, "cluInfo/officialIdentifier/shortName", null);
835 return shortTitle;
836 }
837
838 protected VerticalSectionView initSectionView(Enum<?> viewEnum, String labelKey) {
839 VerticalSectionView section = new VerticalSectionView(viewEnum, getLabel(labelKey), COURSE_PROPOSAL_MODEL);
840 section.addStyleName(LUUIConstants.STYLE_SECTION);
841 return section;
842 }
843
844
845 protected VerticalSection initSection(SectionTitle title, boolean withDivider) {
846 VerticalSection section;
847 if (title != null) {
848 section = new VerticalSection(title);
849 } else {
850 section = new VerticalSection();
851 }
852 section.addStyleName(LUUIConstants.STYLE_SECTION);
853 if (withDivider)
854 section.addStyleName(LUUIConstants.STYLE_SECTION_DIVIDER);
855 return section;
856 }
857
858 @Override
859 protected MessageKeyInfo generateMessageInfo(String labelKey) {
860 return new MessageKeyInfo(groupName, type, state, labelKey);
861 }
862
863 protected Section generateFinancialsSection(Section section) {
864
865 VerticalSection justiFee = initSection(getH3Title(LUUIConstants.COURSE_FEE_TITLE), WITH_DIVIDER);
866 SpanPanel courseFeeInstruction = new SpanPanel();
867 courseFeeInstruction.setStyleName("ks-form-module-elements-instruction");
868 courseFeeInstruction.setHTML(getLabel(LUUIConstants.COURSE_FEE_TITLE + FieldLayoutComponent.INSTRUCT_MESSAGE_KEY));
869 courseFeeInstruction.setVisible(true);
870 justiFee.addWidget(courseFeeInstruction);
871
872
873
874 addField(justiFee, COURSE + "/" + "feeJustification" + "/" + RichTextInfoConstants.PLAIN, generateMessageInfo(LUUIConstants.JUSTIFICATION_FEE));
875 section.addSection(justiFee);
876 Map<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>> swappableFieldsDefinition =
877 new HashMap<SwapCompositeCondition, List<SwapCompositeConditionFieldConfig>>();
878
879
880
881
882
883
884
885 QueryPath feesPath = QueryPath.concat(COURSE, FEES);
886 QueryPath rateTypeFieldPath = QueryPath.concat(feesPath.toString(), QueryPath.getWildCard(), "rateType");
887
888
889
890
891
892
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