Skip to content

Commit

Permalink
Convert student assessment instance EJS to TypeScript (#9974)
Browse files Browse the repository at this point in the history
* Saving WIP work

* Working conversion of page

* Add TODOs for tomorrow

* Convert studentAccessRulesPopover to TypeScript

* Convert zoneInfoBadge to TypeScript

* Convert row label to TypeScript

* Inline questionValue partial

* Convert help popovers to TypeScript

* Remove TODO

* Silence TypeScript error

* Delete EJS file

* Fix conditional

* Improve modals; fix markup issues

* Fix roles

* Remove old page again

* Fix tests again

* Use shared script for custom file input behavior

* Remove ts-expect-error

* Address code review comments

* Correctly show unanswered question warning

* Show time limit expiration modal on all necessary pages
  • Loading branch information
nwalters512 committed Jun 10, 2024
1 parent ee02389 commit 617f55d
Show file tree
Hide file tree
Showing 23 changed files with 907 additions and 517 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { on } from 'delegated-events';

// Ensure that custom file inputs display the file name.
on('change', 'input[type="file"].custom-file-input', function (event) {
const input = event.target as HTMLInputElement;
const value = input.value.replace(/\\/g, '/').replace(/.*\//, '');
const label = input.closest('.custom-file')?.querySelector('.custom-file-label');
if (label) label.textContent = value;
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './behaviors/custom-file-input.js';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './behaviors/custom-file-input.js';
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import './behaviors/custom-file-input.js';

$(function () {
$('[data-toggle="popover"]').popover({ sanitize: false, container: 'body' });
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './behaviors/custom-file-input.js';
62 changes: 62 additions & 0 deletions apps/prairielearn/src/components/StudentAccessRulesPopover.html.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { z } from 'zod';

import { escapeHtml, html } from '@prairielearn/html';

import { ModeSchema } from '../lib/db-types.js';

export const AuthzAccessRuleSchema = z.object({
credit: z.string(),
time_limit_min: z.string(),
start_date: z.string(),
end_date: z.string(),
mode: ModeSchema.nullable(),
active: z.boolean().nullable(),
});
export type AuthzAccessRule = z.infer<typeof AuthzAccessRuleSchema>;

export function StudentAccessRulesPopover({
assessmentSetName,
assessmentNumber,
accessRules,
}: {
assessmentSetName: string;
assessmentNumber: string;
accessRules: AuthzAccessRule[];
}) {
return html`
<a
tabindex="0"
class="btn btn-xs"
role="button"
data-toggle="popover"
data-trigger="focus"
data-container="body"
data-html="true"
title="${assessmentSetName} ${assessmentNumber}"
data-content="${escapeHtml(StudentAccessRulesPopoverContent({ accessRules }))}"
>
<i class="fa fa-question-circle"></i>
</a>
`;
}

function StudentAccessRulesPopoverContent({ accessRules }: { accessRules: AuthzAccessRule[] }) {
return html`
<table class="table">
<tr>
<th>Credit</th>
<th>Start</th>
<th>End</th>
</tr>
${accessRules.map(
(accessRule) => html`
<tr>
<td>${accessRule.credit}</td>
<td>${accessRule.start_date}</td>
<td>${accessRule.end_date}</td>
</tr>
`,
)}
</table>
`;
}
25 changes: 25 additions & 0 deletions apps/prairielearn/src/components/TimeLimitExpiredModal.html.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { html } from '@prairielearn/html';

import { Modal } from './Modal.html.js';

export function TimeLimitExpiredModal({ showAutomatically }: { showAutomatically: boolean }) {
return html`
${Modal({
id: 'timeLimitExpiredModal',
title: 'Time limit expired',
body: html`<p>Your time limit expired and your assessment is now finished.</p>`,
footer: html`
<button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
`,
})}
${showAutomatically
? html`
<script>
$(function () {
$('#timeLimitExpiredModal').modal('show');
});
</script>
`
: ''}
`;
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { html } from '@prairielearn/html';
import { renderEjs } from '@prairielearn/html-ejs';

import { TimeLimitExpiredModal } from '../components/TimeLimitExpiredModal.html.js';
import type { Assessment, AssessmentInstance, AssessmentSet } from '../lib/db-types.js';
import { formatPoints } from '../lib/format.js';

export function StudentAssessmentAccess({
resLocals,
showClosedScore = true,
showTimeLimitExpiredModal = false,
}: {
resLocals: Record<string, any>;
showClosedScore?: boolean;
showTimeLimitExpiredModal?: boolean;
}) {
const { assessment, assessment_set, assessment_instance, authz_result } = resLocals as {
assessment: Assessment;
Expand All @@ -28,6 +31,7 @@ export function StudentAssessmentAccess({
...resLocals,
navPage: '',
})}
${showTimeLimitExpiredModal ? TimeLimitExpiredModal({ showAutomatically: true }) : ''}
<main id="content" class="container">
<div class="card mb-4">
<div class="card-header bg-primary text-white">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ router.all('/', function (req, res, next) {
StudentAssessmentAccess({
resLocals: res.locals,
showClosedScore: res.locals.authz_result?.show_closed_assessment_score ?? true,
showTimeLimitExpiredModal: req.query.timeLimitExpired === 'true',
}),
);
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { html, escapeHtml } from '@prairielearn/html';
import { renderEjs } from '@prairielearn/html-ejs';

import { Modal } from '../../components/Modal.html.js';
import { nodeModulesAssetPath } from '../../lib/assets.js';
import { compiledScriptTag, nodeModulesAssetPath } from '../../lib/assets.js';
import { GroupConfig, IdSchema, UserSchema } from '../../lib/db-types.js';

export const GroupUsersRowSchema = z.object({
Expand Down Expand Up @@ -43,6 +43,7 @@ export function InstructorAssessmentGroups({
<script src="${nodeModulesAssetPath(
'tablesorter/dist/js/jquery.tablesorter.widgets.min.js',
)}"></script>
${compiledScriptTag('instructorAssessmentGroupsClient.ts')}
</head>
<body>
Expand All @@ -67,12 +68,6 @@ export function InstructorAssessmentGroups({
$('.js-group-action[data-toggle="popover"]').popover('hide');
});
});
// make the file inputs display the file name
$(document).on('change', '.custom-file-input', function () {
this.fileName = $(this).val().replace(/\\\\/g, '/').replace(/.*\\//, '');
$(this).parent('.custom-file').find('.custom-file-label').text(this.fileName);
});
</script>
${renderEjs(import.meta.url, "<%- include('../partials/navbar'); %>", resLocals)}
<main id="content" class="container-fluid">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { html } from '@prairielearn/html';
import { renderEjs } from '@prairielearn/html-ejs';

import { Modal } from '../../components/Modal.html.js';
import { compiledScriptTag } from '../../lib/assets.js';
import { JobSequenceSchema, UserSchema } from '../../lib/db-types.js';

export const UploadJobSequenceSchema = z.object({
Expand All @@ -25,15 +26,9 @@ export function InstructorAssessmentUploads({
<html lang="en">
<head>
${renderEjs(import.meta.url, "<%- include('../partials/head'); %>", resLocals)}
${compiledScriptTag('instructorAssessmentUploadsClient.ts')}
</head>
<body>
<script>
// make the file inputs display the file name
$(document).on('change', '.custom-file-input', function () {
this.fileName = $(this).val().replace(/\\\\/g, '/').replace(/.*\\//, '');
$(this).parent('.custom-file').find('.custom-file-label').text(this.fileName);
});
</script>
${renderEjs(import.meta.url, "<%- include('../partials/navbar'); %>", resLocals)}
<main id="content" class="container-fluid">
${renderEjs(
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

3 changes: 0 additions & 3 deletions apps/prairielearn/src/pages/partials/questionValue.ejs

This file was deleted.

18 changes: 0 additions & 18 deletions apps/prairielearn/src/pages/partials/studentAccessRulesPopover.ejs

This file was deleted.

This file was deleted.

10 changes: 0 additions & 10 deletions apps/prairielearn/src/pages/partials/zoneInfoBadge.ejs

This file was deleted.

Loading

0 comments on commit 617f55d

Please sign in to comment.