Added bulk import.
This commit is contained in:
parent
65e61a9fbf
commit
2b9b207e2d
|
@ -1,13 +1,15 @@
|
||||||
import handy_httpd;
|
import handy_httpd;
|
||||||
import handy_httpd.handlers.path_handler;
|
import handy_httpd.handlers.path_handler;
|
||||||
import std.stdio;
|
|
||||||
import d2sqlite3;
|
import d2sqlite3;
|
||||||
|
import std.process;
|
||||||
|
|
||||||
import db;
|
import db;
|
||||||
import api_modules.auth;
|
import api_modules.auth;
|
||||||
static import api_modules.classroom_compliance;
|
static import api_modules.classroom_compliance;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
string env = environment.get("TEACHER_TOOLS_API_ENV", "DEV");
|
||||||
|
|
||||||
// Initialize the database on startup.
|
// Initialize the database on startup.
|
||||||
auto db = getDb();
|
auto db = getDb();
|
||||||
db.close();
|
db.close();
|
||||||
|
@ -22,6 +24,11 @@ void main() {
|
||||||
config.defaultHeaders["Access-Control-Request-Method"] = "*";
|
config.defaultHeaders["Access-Control-Request-Method"] = "*";
|
||||||
config.defaultHeaders["Access-Control-Allow-Headers"] = "Authorization, Content-Length, Content-Type";
|
config.defaultHeaders["Access-Control-Allow-Headers"] = "Authorization, Content-Length, Content-Type";
|
||||||
|
|
||||||
|
if (env == "PROD") {
|
||||||
|
config.port = 8107;
|
||||||
|
config.workerPoolSize = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PathHandler handler = new PathHandler();
|
PathHandler handler = new PathHandler();
|
||||||
handler.addMapping(Method.OPTIONS, "/api/**", &optionsEndpoint);
|
handler.addMapping(Method.OPTIONS, "/api/**", &optionsEndpoint);
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
VITE_API_URL=https://teacher-tools.andrewlalis.com/api
|
|
@ -37,6 +37,8 @@ async function deleteThisClass() {
|
||||||
<div class="button-bar" style="margin-bottom: 1em;">
|
<div class="button-bar" style="margin-bottom: 1em;">
|
||||||
<button type="button" @click="router.push(`/classroom-compliance/classes/${cls.id}/edit-student`)">Add
|
<button type="button" @click="router.push(`/classroom-compliance/classes/${cls.id}/edit-student`)">Add
|
||||||
Student</button>
|
Student</button>
|
||||||
|
<button type="button" @click="router.push(`/classroom-compliance/classes/${cls.id}/import-students`)">Import
|
||||||
|
Students</button>
|
||||||
<button type="button" @click="deleteThisClass">Delete this Class</button>
|
<button type="button" @click="deleteThisClass">Delete this Class</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { showAlert } from '@/alerts';
|
||||||
|
import { ClassroomComplianceAPIClient } from '@/api/classroom_compliance';
|
||||||
|
import { useAuthStore } from '@/stores/auth';
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
classId: string
|
||||||
|
}>()
|
||||||
|
const authStore = useAuthStore()
|
||||||
|
const router = useRouter()
|
||||||
|
const apiClient = new ClassroomComplianceAPIClient(authStore)
|
||||||
|
|
||||||
|
const textContent = ref('')
|
||||||
|
const working = ref(false)
|
||||||
|
const lines = computed(() => textContent.value.trim().split('\n').filter(s => s.trim().length > 0))
|
||||||
|
const studentCount = computed(() => lines.value.length)
|
||||||
|
|
||||||
|
async function doImport() {
|
||||||
|
working.value = true
|
||||||
|
const classIdNumber = parseInt(props.classId, 10)
|
||||||
|
for (let i = 0; i < lines.value.length; i++) {
|
||||||
|
const line = lines.value[i]
|
||||||
|
const student = await apiClient.createStudent(classIdNumber, { name: line, deskNumber: 0, removed: false })
|
||||||
|
.handleErrorsWithAlert()
|
||||||
|
if (!student) break;
|
||||||
|
}
|
||||||
|
working.value = false
|
||||||
|
await showAlert('Created students!')
|
||||||
|
await router.replace(`/classroom-compliance/classes/${classIdNumber}`)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>Import Students</h1>
|
||||||
|
<p>
|
||||||
|
Import a large number of students to a class at once by pasting their names in the text box below, with one
|
||||||
|
student per line.
|
||||||
|
</p>
|
||||||
|
<form @submit.prevent="doImport">
|
||||||
|
<textarea style="min-width: 300px; min-height: 500px;" v-model="textContent"></textarea>
|
||||||
|
<div>
|
||||||
|
<span>Detected <span>{{ studentCount }}</span> students in the above text.</span>
|
||||||
|
</div>
|
||||||
|
<div class="button-bar">
|
||||||
|
<button type="submit" :disabled="working">Submit</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -54,6 +54,11 @@ const router = createRouter({
|
||||||
component: () => import('@/apps/classroom_compliance/EditStudentView.vue'),
|
component: () => import('@/apps/classroom_compliance/EditStudentView.vue'),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'classes/:classId/import-students',
|
||||||
|
component: () => import('@/apps/classroom_compliance/ImportStudentsView.vue'),
|
||||||
|
props: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
# Script for deploying the application to teacher-tools.andrewlalis.com.
|
||||||
|
|
||||||
|
echo "Building app"
|
||||||
|
cd app
|
||||||
|
rm -rf dist
|
||||||
|
npm run build
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
echo "Building API"
|
||||||
|
cd api
|
||||||
|
dub clean
|
||||||
|
dub build --build=release --compiler=/opt/ldc2/ldc2-1.36.0-linux-x86_64/bin/ldc2
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
ssh -f root@andrewlalis.com 'systemctl stop teacher-tools-api.service'
|
||||||
|
scp api/teacher-tools-api root@andrewlalis.com:/opt/teacher-tools/
|
||||||
|
rsync -rav -e ssh --delete app/dist/* root@andrewlalis.com:/opt/teacher-tools/app-content
|
||||||
|
ssh -f root@andrewlalis.com 'systemctl start teacher-tools-api.service'
|
|
@ -0,0 +1,14 @@
|
||||||
|
[Unit]
|
||||||
|
Description=teacher-tools-api
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
WorkingDirectory=/opt/teacher-tools
|
||||||
|
Environment="TEACHER_TOOLS_API_ENV=PROD"
|
||||||
|
ExecStart=/opt/teacher-tools/teacher-tools-api
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
Loading…
Reference in New Issue