Skip to content
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

Replace datetimepicker #526

Merged
merged 25 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
478218e
Uninstall old Datetimepicker
Splines Jul 4, 2023
6b93a13
Remove old import hack for Datetimepicker
Splines Jul 4, 2023
2e8bdcb
Try out Tempus Dominus datetimepicker on assignments
Splines Jul 4, 2023
22abf4f
Show datetimepicker when clicking in text field
Splines Jul 11, 2023
9a9d3b2
Shrink "action" and enlargen "Deadline" column
Splines Jul 11, 2023
75ca523
Do not use not working jQuery version of datetimepicker
Splines Jul 11, 2023
3e682bb
Remove autocomplete from input field
Splines Jul 11, 2023
8d07ed0
Improve accessibility of Datetimepicker
Splines Jul 11, 2023
011c570
Add error message for invalid format & decouple from assignment view
Splines Jul 12, 2023
a5fc69c
Clean up datetimepicker.js
Splines Jul 12, 2023
bb92f78
Change invalid date format string
Splines Jul 12, 2023
d63eefd
Fix "is-invalid" CSS classes via JS
Splines Jul 12, 2023
658a371
Get rid of old datetimepicker occurrences
Splines Jul 12, 2023
fcf58a0
Get rid of "moment" as dependency for formatting dates
Splines Jul 12, 2023
eab7d34
Wait for document to be ready to init datetimepicker
Splines Jul 12, 2023
f0f6499
Replace old datetimepicker in publish media modal
Splines Jul 12, 2023
d29433e
Fix datetimepicker in assignments view
Splines Jul 12, 2023
483c464
Do not close datetimepicker when only time is changed
Splines Jul 12, 2023
a6d7c05
Improve comment
Splines Jul 12, 2023
a1458c9
Check if date is undefined
Splines Jul 12, 2023
377cc3d
Prevent turbolink issue with datetimepicker
Splines Jul 12, 2023
466180b
Fix assignment title CSS id
Splines Jul 12, 2023
9d6f59d
Empty error message upon update of assignment
Splines Jul 12, 2023
c0ab1a5
Restore old code for "assignment_title"
Splines Jul 12, 2023
b5e3fe9
Use 'before-cache' instead of 'load' with Turbolinks
Splines Jul 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions app/assets/javascripts/datetimepicker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
$(document).ready(function () {

fosterfarrell9 marked this conversation as resolved.
Show resolved Hide resolved
// Initialize Tempus Dominus datetimepicker(s)
startInitialization();
function startInitialization() {
const pickerElements = $('.td-picker');
if (pickerElements.length == 0) {
console.error('No datetimepicker element found on page, although requested.');
return;
}

pickerElements.each((i, element) => {
element = $(element);
const datetimePicker = initDatetimePicker(element);
registerErrorHandlers(datetimePicker, element);
registerFocusHandlers(datetimePicker, element);
});
}

function initDatetimePicker(element) {
// see https://getdatepicker.com
return new tempusDominus.TempusDominus(
element.get(0),
{
display: {
sideBySide: true, // clock to the right of the calendar
},
localization: {
startOfTheWeek: 1,
// choose format to be compliant with backend time format
format: 'yyyy-MM-dd HH:mm',
hourCycle: 'h23',
}
}
);
}

function registerErrorHandlers(datetimePicker, element) {
// Catch Tempus Dominus error when user types in invalid date
// this is rather hacky at the moment, see this discussion:
// https://github.com/Eonasdan/tempus-dominus/discussions/2656
datetimePicker.dates.oldParseInput = datetimePicker.dates.parseInput;
datetimePicker.dates.parseInput = (input) => {
try {
return datetimePicker.dates.oldParseInput(input);
} catch (err) {
const errorMsg = element.find('.td-error').data('td-invalid-date');
element.find('.td-error').text(errorMsg).show();
datetimePicker.dates.clear();
}
};

datetimePicker.subscribe(tempusDominus.Namespace.events.change, (e) => {
// see https://getdatepicker.com/6/namespace/events.html#change

// Clear error message
if (e.isValid && !e.isClear) {
element.find('.td-error').empty();
}

// If date was selected, close datetimepicker.
// However: leave the datetimepicker open if user only changed time
if (e.oldDate && !hasUserChangedDate(e.oldDate, e.date)) {
datetimePicker.hide();
}
});
}

function hasUserChangedDate(oldDate, newDate) {
return oldDate.getHours() != newDate.getHours()
|| oldDate.getMinutes() != newDate.getMinutes();
}

function registerFocusHandlers(datetimePicker, element) {
// Show datetimepicker when user clicks in text field next to button
// or when input field receives focus
var isButtonInvokingFocus = false;

element.find('.td-input').on('click focusin', (e) => {
try {
if (!isButtonInvokingFocus) {
datetimePicker.show();
}
}
finally {
isButtonInvokingFocus = false;
}
});

element.find('.td-picker-button').on('click', () => {
isButtonInvokingFocus = true;
element.find('.td-input').focus();
});

// Hide datetimepicker when input field loses focus
element.find('.td-input').blur((e) => {
if (!e.relatedTarget) {
return;
}
datetimePicker.hide();
});
}
});
15 changes: 1 addition & 14 deletions app/assets/javascripts/media.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,6 @@ fancyTimeFormat = (time) ->
output

$(document).on 'turbolinks:load', ->

# init datetimepicker
$('#release_date').datetimepicker
format: 'd.m.Y H:i'
inline: false
lang: 'en'

# disable/enable search field on the media search page, depending on
# whether 'all tags'/'all editors'/... are selected
$('[id^="search_all_"]').on 'change', ->
Expand Down Expand Up @@ -395,14 +388,8 @@ $(document).on 'turbolinks:load', ->
return

$('#release_date').on 'focus', ->
# Select other option if user clicks on release date input field
$('#medium_release_now_0').prop('checked', true)
$('#release_date').datetimepicker('toggle')
return

$('#medium_assignment_deadline').on 'focus', ->
$(this).datetimepicker
format: 'd.m.Y H:i'
inline: false
return

$('#medium_create_assignment').on 'click', ->
Expand Down
13 changes: 0 additions & 13 deletions app/javascript/packs/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,10 @@
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)

// JQuery Datetimepicker fix
// import '...' does not work, random names for the import don't work either
// we use "css" and "myLib" imports although these strings do not show up anywhere
// in our codebase. This is just a hack to make the imports-loader work. Maybe it has
// to do with how webpacker resolves the imports or how jquery-datetimepicker exports
// its module.
import css from 'jquery-datetimepicker/build/jquery.datetimepicker.min.css'
import myLib from 'imports-loader?imports=default%20jquery%20$!./../../../node_modules/jquery-datetimepicker/build/jquery.datetimepicker.full.min.js'

import moment from "moment"; // require
window.moment = moment;
import {
WidgetInstance
} from "friendly-challenge";
var friendlyChallengeWidgetInstance = WidgetInstance
$.datetimepicker.setLocale('de');


document.addEventListener("turbolinks:load", function () {
var doneCallback, element, options, widget;
Expand Down
1 change: 0 additions & 1 deletion app/javascript/packs/application.sass
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
@import "jquery-datetimepicker/build/jquery.datetimepicker.min.css"
37 changes: 29 additions & 8 deletions app/views/assignments/_form.html.erb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<%= javascript_include_tag 'datetimepicker' %>

<div class="list-group-item assignmentRow"
data-id="<%= assignment.id.to_i %>">
<%= form_with model: assignment do |f| %>
Expand All @@ -10,15 +12,33 @@
id="assignment-title-error">
</div>
</div>
<div class="form-group col-2">
<%= f.text_field :deadline,
class: 'form-control',
autocomplete: 'off',
id: "assignment_deadline_#{assignment.id}" %>
<div class="invalid-feedback"
id="assignment-deadline-error">

<%# Datetimepicker for assignment deadline %>
<div class="col-3 form-group">
<div
class="input-group log-event td-picker"
id="assignment-picker"
data-td-target-input="nearest"
data-td-target-toggle="nearest">
<%= f.text_field :deadline,
class: 'form-control td-input',
autocomplete: 'off',
'data-td-target': '#assignment-picker' %>
<span
class="input-group-text td-picker-button"
role="button"
data-td-target="#assignment-picker"
data-td-toggle="datetimepicker">
<i class="bi bi-calendar-fill"></i>
</span>
<div class="invalid-feedback td-error"
id="assignment-deadline-error"
data-td-invalid-date="<%= t('datetimepicker.invalid_date') %>">
</div>
</div>
</div>


<div class="form-group col-2">
<%= f.select :medium_id,
options_for_select(Medium.where(teachable: assignment.lecture,
Expand Down Expand Up @@ -48,12 +68,13 @@
id="assignment-deletion-date-error">
</div>
</div>
<div class="form-group col-2">
<div class="form-group col-1">
<%= f.submit t('buttons.save'),
class: 'btn btn-sm btn-primary ms-2' %>
<%= link_to t('buttons.cancel'),
cancel_editing_assignment_path(assignment),
class: 'btn btn-sm btn-secondary',
role: 'button',
remote: true %>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions app/views/assignments/_row.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<div class="col-2">
<%= assignment.title %>
</div>
<div class="col-2">
<div class="col-3">
<% if assignment.deadline %>
<%= I18n.l(assignment.deadline, format: :long) %>
<% end %>
Expand All @@ -26,7 +26,7 @@
<%= I18n.l(assignment.deletion_date, format: :long) %>
<% end %>
</div>
<div class="col-2">
<div class="col-1">
<% if assignment.persisted? %>
<%= link_to edit_assignment_path(assignment),
class: 'text-dark',
Expand Down
8 changes: 4 additions & 4 deletions app/views/assignments/create.coffee
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# clean up from previous error messages
$('#assignment_title').removeClass('is-invalid')
$('#assignment_title_').removeClass('is-invalid')
$('#assignment-title-error').empty()
$('#assignment_deadline').removeClass('is-invalid')
$('#assignment-deadline-error').empty()
$('#assignment_deletion_date').removeClass('is-invalid')
$('#assignment_deletion_date_').removeClass('is-invalid')
$('#assignment-deletion-date-error').empty()

# display error message
<% if @errors.present? %>
<% if @errors[:title].present? %>
$('#assignment-title-error')
.append('<%= @errors[:title].join(" ") %>').show()
$('#assignment_title').addClass('is-invalid')
$('#assignment_title_').addClass('is-invalid')
<% end %>
<% if @errors[:deadline].present? %>
$('#assignment-deadline-error')
Expand All @@ -21,7 +21,7 @@ $('#assignment_deadline').addClass('is-invalid')
<% if @errors[:deletion_date].present? %>
$('#assignment-deletion-date-error')
.append('<%= @errors[:deletion_date].join(" ") %>').show()
$('#assignment_deletion_date').addClass('is-invalid')
$('#assignment_deletion_date_').addClass('is-invalid')
<% end %>
<% else %>
$('.assignmentRow[data-id="0"')
Expand Down
7 changes: 0 additions & 7 deletions app/views/assignments/edit.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,3 @@ new TomSelect('#assignment_medium_id_<%= @assignment.id %>',
# make sure that no medium is preselected
$('#assignment_medium_id_<%= @assignment.id %>').val(null).trigger('change')
<% end %>

# using moment to format the date right
d = moment($("#assignment_deadline_<%= @assignment.id %>").val(),"YYYY-MM-DD hh:mm:ss z")
$("#assignment_deadline_<%= @assignment.id %>").val (d.format("DD.MM.Y H:mm"))
$("#assignment_deadline_<%= @assignment.id %>").datetimepicker
format:'d.m.Y H:i'
inline:false
5 changes: 0 additions & 5 deletions app/views/assignments/new.js.erb
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,3 @@ new TomSelect('#assignment_medium_id_', {
});

$('#assignment_medium_id_').val(null).trigger('change');

$("#assignment_deadline_").datetimepicker({
format: 'd.m.Y H:i',
inline: false
});
14 changes: 14 additions & 0 deletions app/views/layouts/_head.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@
integrity="sha256-rADF2WO6GbkNb5O9gqHdjQ/XhrfnXDtPdHdRe5KQmek="
crossorigin="anonymous">
</script>

<!-- Tempus Dominus Datetimepicker -->
<!-- Font awesome required for icons in Datetimepicker -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/js/solid.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/js/fontawesome.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" crossorigin="anonymous">
</script>
<script src="https://cdn.jsdelivr.net/npm/@eonasdan/[email protected]/dist/js/tempus-dominus.js">
</script>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@eonasdan/[email protected]/dist/css/tempus-dominus.css">

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/sanitize-html.min.js" integrity="sha256-+Tha6wUu+wzAOUzilJ7AmF4OXc3CsY1aMsWopnCVwb4=" crossorigin="anonymous"></script>
<script defer
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js"
Expand All @@ -59,6 +71,8 @@
</script>
<![endif]-->



<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no">

Expand Down
4 changes: 2 additions & 2 deletions app/views/lectures/edit/_assignments.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<%= t('basics.title') %>
</h6>
</div>
<div class="col-2">
<div class="col-3">
<h6>
<%= t('basics.deadline') %>
</h6>
Expand All @@ -61,7 +61,7 @@
<%= t('assignment.deletion_date') %>
</h6>
</div>
<div class="col-2">
<div class="col-1">
<h6>
<%= t('basics.action') %>
<%= helpdesk(t('assignment.destruction_info'), true) %>
Expand Down
Loading