An export option adds your platform to the Send to… menu of a test, so teachers can send a test to it in a few clicks. Google Classroom, for example, posts the test's link to a class as a draft assignment, and Woots imports the test's questions.
Defining an export option
import {
ExportFormat,
ExportOption,
ExportResourceType,
ExportStatus,
} from "@examplary/apps";
import { z } from "zod";
export default new ExportOption({
id: "acme",
name: { en: "Acme Gradebook" },
icon: "./icon.svg",
resourceTypes: [ExportResourceType.Exam],
formats: [ExportFormat.Qti21],
getExportOptions: async (settings) => {
const classes = await listClasses(settings.apiToken);
return [
{
key: "classId",
label: { en: "Class" },
type: "select",
options: classes.map((c) => ({ value: c.id, label: c.name })),
schema: z.string(),
},
];
},
startExport: async (settings, test) => {
const job = await startImport(settings.apiToken, {
classId: settings.classId,
packageUrl: test.files.qti21!.url,
});
return { status: ExportStatus.inProgress, data: { jobId: job.id } };
},
getExportStatus: async (settings, { data }) => {
const job = await getImport(settings.apiToken, data.jobId);
if (job.state === "running") {
return { status: ExportStatus.inProgress, data };
}
if (job.state === "failed") {
return { status: ExportStatus.failed, message: job.error, data };
}
return { status: ExportStatus.completed, resultUrl: job.testUrl, data };
},
});Then add it to your app with app.addCapability(), as shown in the introduction.
| Property | Description |
|---|---|
id | Unique within your app. |
name | Shown in the Send to… menu. |
icon | Path to the icon shown in the menu. |
resourceTypes | What can be exported. For now, only ExportResourceType.Exam (tests). |
formats | Files Examplary should prepare for startExport, see below. |
statusCheckInterval | How often to call getExportStatus, in milliseconds. Defaults to 1000. |
getExportOptions | Returns the fields the teacher fills in for this export. Optional. |
startExport | Starts the export. Required. |
getExportStatus | Checks on an export that's still in progress. Optional. |
Export options
getExportOptions returns the fields to show the teacher before the export starts, like the class to send the test to. They're written like settings, and checked the same way. The values the teacher picks are passed to startExport along with the app's settings, so settings.classId above is the chosen class.
When a teacher hasn't filled in their own user settings yet, like connecting their account, Examplary asks for those first.
The test
startExport gets the test to export:
| Property | Description |
|---|---|
id | The test's ID. |
name | The test's name. |
publicUrl | The link students use to open the test. |
totalPoints | The points to earn, or null when the test doesn't show points. |
files | A download url and filename for each of the formats you asked for. |
The only format for now is ExportFormat.Qti21, a QTI 2.1 package that most assessment platforms can import. The download URLs are only valid for a short while, so pass the file on (or let your platform download it) right away.
Export status
startExport and getExportStatus both return the export's status:
| Property | Description |
|---|---|
status | ExportStatus.inProgress, completed or failed. |
resultUrl | Where the teacher can see the result, like the imported test. Shown as a button once it's completed. |
message | What went wrong, or anything else the teacher should know, like questions that couldn't be imported. |
data | Anything you need to check on the export later, like the ID of an import job. |
When an export can finish right away, return completed from startExport. Otherwise, return inProgress, and Examplary calls getExportStatus with the last status (including its data) every statusCheckInterval milliseconds, until the export is completed or failed. An export that's still in progress after 10 minutes counts as failed.