forked from Simon-Initiative/oli-torus
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FEATURE] Time limit, grace period, late start, late submit, auto sub…
…mit and review submission settings (Simon-Initiative#3544) * infra, prologue late start prevention, was_late tracking * auto submit server impl * beginning of client side impl * timer and auto submit working * add 5 min remaining timer * add 1 minute slack time * Auto format * fix compile error * really fix the compile error * remove temporary time_limit setting code * fix two more tests * add page lifecycle test for was_late * add enforcement of late start in lifecyle * update to use finalization summary * implementation of review_submission setting --------- Co-authored-by: darrensiegel <darrensiegel@users.noreply.github.com>
- Loading branch information
1 parent
8463d28
commit 13c7cbc
Showing
18 changed files
with
641 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
export function initCountdownTimer( | ||
timerId: string, | ||
submitButtonId: string, | ||
timeOutInMins: number, | ||
startTimeInMs: any, | ||
effectiveTimeInMs: any, | ||
autoSubmit: boolean, | ||
) { | ||
const now = new Date().getTime(); | ||
|
||
if (effectiveTimeInMs > now) { | ||
const timeOutInMs = timeOutInMins * 60 * 1000; | ||
|
||
const timeLeft = effectiveTimeInMs - now; | ||
const realDeadlineInMs = timeLeft < timeOutInMs ? now + timeLeft : timeOutInMs + startTimeInMs; | ||
|
||
const interval = setInterval(function () { | ||
const now = new Date().getTime(); | ||
const distance = realDeadlineInMs - now; | ||
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); | ||
const seconds = Math.floor((distance % (1000 * 60)) / 1000); | ||
update(timerId, 'Time remaining: ' + minutes + 'm ' + seconds + 's '); | ||
|
||
if (distance < 0) { | ||
clearInterval(interval); | ||
update(timerId, ''); | ||
|
||
update(timerId, 'This is a late submission'); | ||
|
||
if (autoSubmit) { | ||
(document.getElementById(submitButtonId) as any).click(); | ||
} | ||
} | ||
}, 1000); | ||
} | ||
} | ||
|
||
export function initEndDateTimer( | ||
timerId: string, | ||
submitButtonId: string, | ||
effectiveTimeInMs: any, | ||
autoSubmit: boolean, | ||
) { | ||
const now = new Date().getTime(); | ||
|
||
if (effectiveTimeInMs > now) { | ||
const timeLeft = effectiveTimeInMs - now; | ||
const realDeadlineInMs = now + timeLeft; | ||
|
||
const interval = setInterval(function () { | ||
const now = new Date().getTime(); | ||
const distance = realDeadlineInMs - now; | ||
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); | ||
const seconds = Math.floor((distance % (1000 * 60)) / 1000); | ||
|
||
if (minutes < 5) { | ||
update(timerId, 'Time remaining: ' + minutes + 'm ' + seconds + 's '); | ||
} | ||
|
||
if (distance < 0) { | ||
clearInterval(interval); | ||
update(timerId, ''); | ||
|
||
update(timerId, 'This is a late submission'); | ||
|
||
if (autoSubmit) { | ||
(document.getElementById(submitButtonId) as any).click(); | ||
} | ||
} | ||
}, 1000); | ||
} | ||
} | ||
|
||
function update(id: string, content: string) { | ||
(document.getElementById(id) as any).innerHTML = content; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
defmodule Oli.Delivery.Attempts.AutoSubmit.Worker do | ||
use Oban.Worker, queue: :auto_submit, max_attempts: 5 | ||
|
||
alias Oli.Delivery.Attempts.AutoSubmit.Worker | ||
alias Oli.Delivery.Attempts.PageLifecycle | ||
alias Oli.Delivery.Attempts.Core.ResourceAttempt | ||
alias Oli.Delivery.Settings | ||
|
||
@moduledoc """ | ||
An Oban worker driven page attempts auto submission creator. | ||
""" | ||
|
||
@impl Oban.Worker | ||
def perform(%Oban.Job{ | ||
args: %{"attempt_guid" => attempt_guid, "section_slug" => section_slug, "datashop_session_id" => datashop_session_id} | ||
}) do | ||
PageLifecycle.finalize(section_slug, attempt_guid, datashop_session_id) | ||
end | ||
|
||
@doc """ | ||
Possibly schedules a finalization auto submit for a resource attempt. If the resource attempt | ||
is not eligible for auto submit, then no job is scheduled. If the resource attempt is eligible | ||
for auto submit, then a job is scheduled for the deadline and {:ok, job} is returned. If the | ||
resource attempt is already past the deadline or if there is no deadline or late_submit == :allow | ||
then {:ok, :not_scheduled} is returned. | ||
""" | ||
def maybe_schedule_auto_submit(effective_settings, section_slug, resource_attempt, datashop_session_id) do | ||
|
||
if needs_job?(effective_settings) do | ||
# calculate the deadline, taking into account the grace period | ||
deadline = Settings.determine_effective_deadline(resource_attempt, effective_settings) | ||
|
||
# ensure that we only schedule for deadlines in the future | ||
if DateTime.compare(deadline, DateTime.utc_now()) == :lt do | ||
{:ok, :not_scheduled} | ||
else | ||
|
||
# we schedule the auto submit job 1 minute past the actual deadline to allow for a client side | ||
# auto submit to take place and cancel this job. | ||
deadline_with_slack = DateTime.add(deadline, 1, :minute) | ||
|
||
{:ok, job} = %{attempt_guid: resource_attempt.attempt_guid, section_slug: section_slug, datashop_session_id: datashop_session_id} | ||
|> Worker.new(scheduled_at: deadline_with_slack) | ||
|> Oban.insert() | ||
|
||
{:ok, job.id} | ||
end | ||
|
||
else | ||
{:ok, :not_scheduled} | ||
end | ||
|
||
end | ||
|
||
def cancel_auto_submit(%ResourceAttempt{auto_submit_job_id: id}), do: Oban.cancel_job(id) | ||
|
||
# We only need an auto submit job when there is a deadline and the late_submit policy | ||
# is :disallow. If the late_submit policy is :allow, then we don't need to schedule. | ||
defp needs_job?(es) do | ||
has_deadline?(es) and es.late_submit == :disallow | ||
end | ||
|
||
defp has_deadline?(effective_settings) do | ||
effective_settings.end_date != nil or effective_settings.time_limit > 0 | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.