Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 6 additions & 5 deletions lms/static/scripts/frontend_apps/components/FilePickerApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ export default function FilePickerApp({ onSubmit }: FilePickerAppProps) {
// instructor picked that type in the workflow. This drives the
// `checkpoint_enabled` field the backend persists.
const checkpointEnabled = assignmentType === 'hide_and_reveal';
// UTC ISO string for the backend. Both submit paths send this same value.
const dueDateISO = dueDate ? new Date(dueDate).toISOString() : null;
// Current sub-step of the assignment-type workflow. When the workflow isn't
// enabled we start as `done` so it is skipped entirely.
const [workflowStep, setWorkflowStep] = useState<WorkflowStep>(
Expand Down Expand Up @@ -454,10 +456,7 @@ export default function FilePickerApp({ onSubmit }: FilePickerAppProps) {
...deepLinkingAPI.data,
auto_grading_config: autoGradingConfigToSave,
checkpoint_enabled: checkpointEnabled,
// Optional due date for "Hide & Reveal" assignments. The picker holds
// a local `datetime-local` value; convert it to a UTC ISO string for
// the backend. `null` when left blank or not a checkpoint assignment.
due_date: dueDate ? new Date(dueDate).toISOString() : null,
due_date: dueDateISO,
content,
group_set: groupConfig.useGroupSet ? groupConfig.groupSet : null,
title,
Expand Down Expand Up @@ -486,7 +485,7 @@ export default function FilePickerApp({ onSubmit }: FilePickerAppProps) {
[
authToken,
checkpointEnabled,
dueDate,
dueDateISO,
deepLinkingFields,
deepLinkingAPI,
groupConfig.groupSet,
Expand Down Expand Up @@ -824,6 +823,8 @@ export default function FilePickerApp({ onSubmit }: FilePickerAppProps) {
formFields={formFields}
groupSet={groupConfig.useGroupSet ? groupConfig.groupSet : null}
autoGradingConfig={autoGradingConfigToSave}
checkpointEnabled={checkpointEnabled}
dueDate={dueDateISO}
/>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ export type FilePickerFormFieldsProps = {

/** Auto-grading configuration for assignments where it is enabled */
autoGradingConfig: AutoGradingConfig | null;

/** Whether this is a "Hide & Reveal" assignment. */
checkpointEnabled: boolean;

/** Due date as a UTC ISO string, or `null` when not set. */
dueDate: string | null;
};

/**
Expand All @@ -38,6 +44,8 @@ export default function FilePickerFormFields({
formFields,
groupSet,
autoGradingConfig,
checkpointEnabled,
dueDate,
}: FilePickerFormFieldsProps) {
return (
<>
Expand All @@ -58,6 +66,12 @@ export default function FilePickerFormFields({
value={JSON.stringify(autoGradingConfig)}
/>
)}
{checkpointEnabled && (
<>
<input type="hidden" name="checkpoint_enabled" value="true" />
{dueDate && <input type="hidden" name="due_date" value={dueDate} />}
</>
)}
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ describe('FilePickerApp', () => {
formFields = {},
title = null,
autoGradingConfig = null,
checkpointEnabled = false,
dueDate = null,
},
) {
const fieldsComponent = wrapper.find('FilePickerFormFields');
Expand All @@ -85,6 +87,8 @@ describe('FilePickerApp', () => {
groupSet,
title,
autoGradingConfig,
checkpointEnabled,
dueDate,
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ describe('FilePickerFormFields', () => {
formFields={staticFormFields}
groupSet={null}
title={null}
checkpointEnabled={false}
dueDate={null}
{...props}
/>,
);
Expand Down Expand Up @@ -91,4 +93,33 @@ describe('FilePickerFormFields', () => {
assert.isTrue(configField.exists());
assert.equal(configField.prop('value'), JSON.stringify(autoGradingConfig));
});

it('omits checkpoint fields when `checkpointEnabled` is false', () => {
const formFields = createComponent({ dueDate: '2026-09-01T12:00:00.000Z' });

assert.isFalse(
formFields.find('input[name="checkpoint_enabled"]').exists(),
);
assert.isFalse(formFields.find('input[name="due_date"]').exists());
});

it('renders `checkpoint_enabled` when `checkpointEnabled` is set', () => {
const formFields = createComponent({ checkpointEnabled: true });

const field = formFields.find('input[name="checkpoint_enabled"]');
assert.isTrue(field.exists());
assert.equal(field.prop('value'), 'true');
assert.isFalse(formFields.find('input[name="due_date"]').exists());
});

it('renders `due_date` when a due date is set', () => {
const formFields = createComponent({
checkpointEnabled: true,
dueDate: '2026-09-01T12:00:00.000Z',
});

const field = formFields.find('input[name="due_date"]');
assert.isTrue(field.exists());
assert.equal(field.prop('value'), '2026-09-01T12:00:00.000Z');
});
});
Loading