Repository navigation
HTML-882: drop support for all-day appointments in ScheduleAppointment tag #344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,7 +52,6 @@ | |
| import org.openmrs.module.htmlformentry.widget.NumberFieldWidget; | ||
| import org.openmrs.module.htmlformentry.widget.TextFieldWidget; | ||
| import org.openmrs.module.htmlformentry.widget.TimeWidget; | ||
| import org.openmrs.util.OpenmrsUtil; | ||
|
|
||
| public class ScheduleAppointmentElement implements HtmlGeneratorElement, FormSubmissionControllerAction { | ||
|
|
||
|
|
@@ -76,9 +75,6 @@ public class ScheduleAppointmentElement implements HtmlGeneratorElement, FormSub | |
|
|
||
| private TextFieldWidget noteWidget; | ||
|
|
||
| // Hidden field tracking "allday" vs "specific" radio state | ||
| private TextFieldWidget allDayWidget; | ||
|
|
||
| private NumberFieldWidget durationWidget; | ||
|
|
||
| private ErrorWidget locationErrorWidget; | ||
|
|
@@ -252,10 +248,6 @@ public ScheduleAppointmentElement(FormEntryContext context, Map<String, String> | |
| context.registerErrorWidget(startDateTimeWidget, startDateTimeErrorWidget); | ||
| context.registerWidget(timeErrorWidget); | ||
|
|
||
| // --- All-day toggle (hidden field; value set by JS radio buttons) --- | ||
| allDayWidget = new TextFieldWidget(); | ||
| context.registerWidget(allDayWidget); | ||
|
|
||
| // --- Duration --- | ||
| durationWidget = new NumberFieldWidget(1.0, null, false); | ||
| durationErrorWidget = new ErrorWidget(); | ||
|
|
@@ -288,8 +280,6 @@ public String generateHtml(FormEntryContext context) { | |
| sb.append(".schedule-appointment p>label{display:block;margin-bottom:0.2em;}"); | ||
| sb.append(".schedule-appointment .field-widget{display:flex;align-items:center;gap:0.25em;flex-wrap:wrap;}"); | ||
| sb.append(".schedule-appointment-choice label{display:inline-flex;align-items:center;gap:0.3em;cursor:pointer;margin-right:1em;}"); | ||
| sb.append(".schedule-appointment-timing-options{display:flex;gap:1.5em;align-items:center;}"); | ||
| sb.append(".schedule-appointment-timing-option{display:inline-flex;align-items:center;gap:0.3em;cursor:pointer;}"); | ||
| sb.append(".schedule-appointment-date-time-widget{display:inline-flex;align-items:center;gap:0.5em;flex-wrap:wrap;}"); | ||
| sb.append(".schedule-appt-time{display:inline-flex;align-items:center;gap:0.25em;}"); | ||
| sb.append("</style>"); | ||
|
|
@@ -332,28 +322,7 @@ public String generateHtml(FormEntryContext context) { | |
| .append("\" value=\"").append(typeWidget.getOptions().get(0).getValue()).append("\"/>"); | ||
| } | ||
|
|
||
| // All-day / Specific-time toggle — shown BEFORE the date/time row | ||
| String allDayFieldName = context.getFieldName(allDayWidget); | ||
| sb.append("<p class=\"schedule-appointment-timing\">"); | ||
| sb.append("<label>").append(msg("htmlformentry.scheduleAppointment.timing")) | ||
| .append(" <span class=\"required\">*</span></label>"); | ||
| sb.append("<span class=\"field-widget schedule-appointment-timing-options\">"); | ||
| sb.append("<label class=\"schedule-appointment-timing-option\"><input type=\"radio\" name=\"").append(allDayFieldName).append("-radio\" value=\"allday\"") | ||
| .append(" onchange=\"this.closest('.schedule-appointment').querySelector('.schedule-appt-allday').value='allday';") | ||
| .append("this.closest('.schedule-appointment').querySelector('.schedule-appt-time').style.display='none';") | ||
| .append("this.closest('.schedule-appointment').querySelector('.schedule-appt-duration').style.display='none';\"> ") | ||
| .append(msg("htmlformentry.scheduleAppointment.allDay")).append("</label>"); | ||
| sb.append("<label class=\"schedule-appointment-timing-option\"><input type=\"radio\" name=\"").append(allDayFieldName).append("-radio\" value=\"specific\" checked") | ||
| .append(" onchange=\"this.closest('.schedule-appointment').querySelector('.schedule-appt-allday').value='specific';") | ||
| .append("this.closest('.schedule-appointment').querySelector('.schedule-appt-time').style.display='inline-flex';") | ||
| .append("this.closest('.schedule-appointment').querySelector('.schedule-appt-duration').style.display='block';\"> ") | ||
| .append(msg("htmlformentry.scheduleAppointment.specificTime")).append("</label>"); | ||
| sb.append("</span>"); | ||
| sb.append("<input type=\"hidden\" name=\"").append(allDayFieldName) | ||
| .append("\" class=\"schedule-appt-allday\" value=\"specific\"/>"); | ||
| sb.append("</p>"); | ||
|
|
||
| // Date + Time on one line; time portion shown/hidden by the toggle above | ||
| // Date + Time | ||
| sb.append("<p class=\"schedule-appointment-date-time\">"); | ||
| sb.append("<label>").append(msg("htmlformentry.scheduleAppointment.date")) | ||
| .append(" <span class=\"required\">*</span></label>"); | ||
|
|
@@ -370,13 +339,11 @@ public String generateHtml(FormEntryContext context) { | |
| .append(context.getFieldName(startDateTimeWidget.getDateWidget())).append("', '") | ||
| .append(context.getFieldName(startDateTimeWidget.getTimeWidget())).append("')</script>"); | ||
|
|
||
| // Duration (shown only for specific-time) | ||
| sb.append("<div class=\"schedule-appt-duration\">"); | ||
| // Duration | ||
| sb.append(fieldRow("schedule-appointment-duration", | ||
| msg("htmlformentry.scheduleAppointment.duration"), | ||
| durationWidget.generateHtml(context) + durationErrorWidget.generateHtml(context), | ||
| true)); | ||
| sb.append("</div>"); | ||
|
|
||
| // Provider | ||
| sb.append(fieldRow("schedule-appointment-provider", | ||
|
|
@@ -503,27 +470,22 @@ public Collection<FormSubmissionError> validateSubmission(FormEntryContext conte | |
| msg("htmlformentry.scheduleAppointment.error.dateRequired"))); | ||
| } | ||
|
|
||
| // Time and duration required only for specific-time appointments | ||
| String allDayValue = (String) allDayWidget.getValue(context, submission); | ||
| boolean isAllDay = "allday".equals(allDayValue); | ||
| if (!isAllDay) { | ||
| Date time = (Date) startDateTimeWidget.getTimeWidget().getValue(context, submission); | ||
| if (time == null) { | ||
| errors.add(new FormSubmissionError(context.getFieldName(timeErrorWidget), | ||
| msg("htmlformentry.scheduleAppointment.error.timeRequired"))); | ||
| } | ||
| Date time = (Date) startDateTimeWidget.getTimeWidget().getValue(context, submission); | ||
| if (time == null) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we add a validation test that omits the time selects (and one omitting duration), along the lines of |
||
| errors.add(new FormSubmissionError(context.getFieldName(timeErrorWidget), | ||
| msg("htmlformentry.scheduleAppointment.error.timeRequired"))); | ||
| } | ||
|
|
||
| Number durNum = null; | ||
| try { | ||
| durNum = (Number) durationWidget.getValue(context, submission); | ||
| } | ||
| catch (IllegalArgumentException e) { | ||
| // non-numeric input — falls through to error | ||
| } | ||
| if (durNum == null || durNum.intValue() < 1) { | ||
| errors.add(new FormSubmissionError(context.getFieldName(durationErrorWidget), | ||
| msg("htmlformentry.scheduleAppointment.error.durationRequired"))); | ||
| } | ||
| Number durNum = null; | ||
| try { | ||
| durNum = (Number) durationWidget.getValue(context, submission); | ||
| } | ||
| catch (IllegalArgumentException e) { | ||
| // non-numeric input — falls through to error | ||
| } | ||
| if (durNum == null || durNum.intValue() < 1) { | ||
| errors.add(new FormSubmissionError(context.getFieldName(durationErrorWidget), | ||
| msg("htmlformentry.scheduleAppointment.error.durationRequired"))); | ||
| } | ||
|
|
||
| Provider provider = (Provider) providerWidget.getValue(context, submission); | ||
|
|
@@ -552,8 +514,6 @@ public void handleSubmission(FormEntrySession session, HttpServletRequest submis | |
| String serviceUuid = (String) serviceWidget.getValue(context, submission); | ||
| String typeValue = (String) typeWidget.getValue(context, submission); | ||
| Date date = (Date) startDateTimeWidget.getDateWidget().getValue(context, submission); | ||
| String allDayValue = (String) allDayWidget.getValue(context, submission); | ||
| boolean isAllDay = "allday".equals(allDayValue); | ||
| Provider selectedProvider = (Provider) providerWidget.getValue(context, submission); | ||
| String note = (String) noteWidget.getValue(context, submission); | ||
|
|
||
|
|
@@ -563,44 +523,34 @@ public void handleSubmission(FormEntrySession session, HttpServletRequest submis | |
| // Build start datetime | ||
| Calendar cal = Calendar.getInstance(); | ||
| cal.setTime(date); | ||
| if (!isAllDay) { | ||
| Date time = (Date) startDateTimeWidget.getTimeWidget().getValue(context, submission); | ||
| if (time != null) { | ||
| Calendar timeCal = Calendar.getInstance(); | ||
| timeCal.setTime(time); | ||
| cal.set(Calendar.HOUR_OF_DAY, timeCal.get(Calendar.HOUR_OF_DAY)); | ||
| cal.set(Calendar.MINUTE, timeCal.get(Calendar.MINUTE)); | ||
| } | ||
| } else { | ||
| cal.set(Calendar.HOUR_OF_DAY, 0); | ||
| cal.set(Calendar.MINUTE, 0); | ||
| Date time = (Date) startDateTimeWidget.getTimeWidget().getValue(context, submission); | ||
| if (time != null) { | ||
| Calendar timeCal = Calendar.getInstance(); | ||
| timeCal.setTime(time); | ||
| cal.set(Calendar.HOUR_OF_DAY, timeCal.get(Calendar.HOUR_OF_DAY)); | ||
| cal.set(Calendar.MINUTE, timeCal.get(Calendar.MINUTE)); | ||
| } | ||
| cal.set(Calendar.SECOND, 0); | ||
| cal.set(Calendar.MILLISECOND, 0); | ||
| Date startDateTime = cal.getTime(); | ||
|
|
||
| // Build end datetime | ||
| Date endDateTime; | ||
| if (isAllDay) { | ||
| endDateTime = OpenmrsUtil.getLastMomentOfDay(date); | ||
| } else { | ||
| Integer durationMins = null; | ||
| try { | ||
| Number durNum = (Number) durationWidget.getValue(context, submission); | ||
| if (durNum != null) { | ||
| durationMins = durNum.intValue(); | ||
| } | ||
| } | ||
| catch (IllegalArgumentException e) { | ||
| // non-numeric input — validation should have caught this | ||
| } | ||
| if (durationMins == null && service != null) { | ||
| durationMins = service.getDurationMins(); | ||
| Integer durationMins = null; | ||
| try { | ||
| Number durNum = (Number) durationWidget.getValue(context, submission); | ||
| if (durNum != null) { | ||
| durationMins = durNum.intValue(); | ||
| } | ||
| endDateTime = durationMins != null | ||
| ? new Date(startDateTime.getTime() + (long) durationMins * 60 * 1000) | ||
| : null; | ||
| } | ||
| catch (IllegalArgumentException e) { | ||
| // non-numeric input — validation should have caught this | ||
| } | ||
| if (durationMins == null && service != null) { | ||
| durationMins = service.getDurationMins(); | ||
| } | ||
| Date endDateTime = durationMins != null | ||
| ? new Date(startDateTime.getTime() + (long) durationMins * 60 * 1000) | ||
| : null; | ||
|
|
||
| Appointment appointment = new Appointment(); | ||
| appointment.setPatient(session.getPatient()); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the toggle gone, the
htmlformentry.scheduleAppointment.timingandhtmlformentry.scheduleAppointment.specificTimekeys aren't referenced from anywhere anymore, but they're still in messages.properties and the es/fr/ht bundles. Worth dropping them in this PR so the dead strings don't stick around in the translation files. (allDayis still used by the view-mode rendering, so that one stays.)