diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/FileUploads.svelte | 20 | ||||
| -rw-r--r-- | src/components/PeerTeachers.svelte | 17 | ||||
| -rw-r--r-- | src/logic/EditorActions.ts | 12 | ||||
| -rw-r--r-- | src/models/PeerTeacher.ts | 35 | ||||
| -rw-r--r-- | src/util/parser.ts | 78 |
5 files changed, 141 insertions, 21 deletions
diff --git a/src/components/FileUploads.svelte b/src/components/FileUploads.svelte index 14b0be3..e5df56f 100644 --- a/src/components/FileUploads.svelte +++ b/src/components/FileUploads.svelte @@ -8,12 +8,14 @@ parseDatabaseFile, parseLabScheduleFile, parsePTFile, + readQuestionairre, } from "../logic/EditorActions"; import { labStore, ptStore } from "../stores"; let ptSchedules: FileList | null; let labSchedule: FileList | null; let dbFile: FileList | null; + let questionairreFile: FileList | null; let snackbar: Snackbar; let snackbarText; @@ -81,6 +83,12 @@ } } + $: { + if (questionairreFile?.length) { + readQuestionairre(questionairreFile[0]); + } + } + function dbStringify(): string { const peerTeachers = [...$ptStore.values()]; const labs = [...$labStore.values()]; @@ -173,6 +181,18 @@ >LocalStorage</button > </Card> + + <Card + title="Upload PTs from Questionnairre" + desc="Gather all data from the questionnairre results. Should be in CSV format" + > + <UploadButton + color="btn-info" + accept="text/csv" + multiple={false} + bind:files={questionairreFile} + /> + </Card> </div> <!-- https://github.com/saadeghi/daisyui/issues/221 --> diff --git a/src/components/PeerTeachers.svelte b/src/components/PeerTeachers.svelte index f0d34de..22e1622 100644 --- a/src/components/PeerTeachers.svelte +++ b/src/components/PeerTeachers.svelte @@ -26,13 +26,12 @@ }); } - let headers = ["", "First", "Last", "UIN", "Email", "Lab Hours", ""]; + let headers = ["", "First", "Last", "Email", "UIN", "Phone", "Pref", "Lab", "Gen","Ethnicity", "Grad", "Status", ""]; - $: console.log(headers); </script> <div class="overflow-auto h-full"> - <table class="table w-full"> + <table class="table table-compact w-full"> <!-- head --> <thead> <tr> @@ -65,11 +64,15 @@ {/if} </th> <th>{pt.lastname}</th> - <th>{pt.id}</th> <th>{pt.email}</th> - <th> - {pt.lab_hours} - </th> + <th>{pt.id}</th> + <th>{pt.phone_number}</th> + <th>{pt.pref_work}</th> + <th>{pt.lab_hours}</th> + <th>{pt.gender}</th> + <th>{pt.ethnicity}</th> + <th>{pt.graduation}</th> + <th>{pt.new_ret}</th> <th ><button on:click={() => deletePT(pt.id)} diff --git a/src/logic/EditorActions.ts b/src/logic/EditorActions.ts index 4a83fbc..7c90c5b 100644 --- a/src/logic/EditorActions.ts +++ b/src/logic/EditorActions.ts @@ -1,4 +1,4 @@ -import { parseDatabase, parseLabSchedule, parsePTSchedule } from "../util/parser"; +import { parseDatabase, parseLabSchedule, parsePTSchedule, parseQuestionairreCSV } from "../util/parser"; export async function parsePTFile(file: File) { try { @@ -10,6 +10,16 @@ export async function parsePTFile(file: File) { } } +export async function readQuestionairre(file: File) { + try { + const text = await file.text(); + return parseQuestionairreCSV(text); + } catch (error) { + console.error(file.name, error); + throw error; + } +} + export async function parseLabScheduleFile(file: File) { const text = await file.text(); try { diff --git a/src/models/PeerTeacher.ts b/src/models/PeerTeacher.ts index 4f6144d..5f9cf3c 100644 --- a/src/models/PeerTeacher.ts +++ b/src/models/PeerTeacher.ts @@ -13,6 +13,16 @@ interface PeerTeacherSerializeInfo { }[], labs: number[], email: string, + phone_number: string, + gender: string, + ethnicity: string, + graduation: string, + can_teach: number[], + pref_teach: number[], + pref_work: number, + new_ret: string, + prof_pic_url: string, + schedule_url: string, } export default class PeerTeacher { @@ -22,6 +32,16 @@ export default class PeerTeacher { events: EventInfo[]; labs: Set<number>; email: string; + phone_number: string; + gender: string; + ethnicity: string; + graduation: string; + can_teach: Set<number>; + pref_teach: Set<number>; + pref_work: number; + new_ret: string; + prof_pic_url: string; + schedule_url: string; constructor(id: number | string, firstname: string, lastname: string, email: string) { if (typeof id === "string") { @@ -36,10 +56,23 @@ export default class PeerTeacher { this.email = email; } - static fromJSON({ id, firstname, lastname, events, labs, email }: PeerTeacherSerializeInfo) { + static fromJSON(qt: PeerTeacherSerializeInfo) { + const { id, firstname, lastname, events, labs, email } = qt; const pt = new PeerTeacher(id, firstname, lastname, email); pt.events = events.map(e => EventInfo.fromJSON(e)); pt.labs = new Set(labs); + pt.email = qt.email; + pt.phone_number = qt.phone_number; + pt.gender = qt.gender; + pt.ethnicity = qt.ethnicity; + pt.graduation = qt.graduation; + pt.can_teach = new Set(qt.can_teach); + pt.pref_teach = new Set(qt.pref_teach); + pt.pref_work = qt.pref_work; + pt.new_ret = qt.new_ret; + pt.prof_pic_url = qt.prof_pic_url; + pt.schedule_url = qt.schedule_url; + return pt; } diff --git a/src/util/parser.ts b/src/util/parser.ts index c466525..a51bf5f 100644 --- a/src/util/parser.ts +++ b/src/util/parser.ts @@ -3,6 +3,8 @@ import Lab from "../models/Lab"; import PeerTeacher from "../models/PeerTeacher"; import { labStore, ptStore } from "../stores"; import { PeerTeacherImportError } from "./error"; +import { get } from "svelte/store" +import { attr } from "svelte/internal"; interface LabSchedule { data: { @@ -42,18 +44,7 @@ interface DatabaseFile { room: string, assigned: boolean }[], - peerTeachers: { - id: number, - firstname: string, - lastname: string, - events: { - days: string, - start: number, - end: number - }[], - labs: number[], - email: string - }[] + peerTeachers: PeerTeacher[] } /** @@ -184,4 +175,67 @@ export function parseDatabaseLocalStorage(database_string: string) { labStore.set(result.labs); ptStore.set(result.peerTeachers) +} + +export function parseQuestionairreCSV(csv: string) { + const attributes = [ + "Timestamp", + "UIN", + "First Name", + "Last Name", + "Email Address", + "Phone Number", + "Gender", + "Racial Background", + "When are you graduating? (Day does not matter)", + "Classes you CAN peer teach for", + "Classes you PREFER to peer teach for", + "Number of hours you prefer to work", + "Are you a new hire or returning?", + "Profile picture for website (image)", + "Schedule (text file)" + ] + const t = csv.split("\n") + const sheet = t.map((val) => { + const reg = new RegExp(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))") + return val.split(reg) + }) + + const m = mapAttributeToIndex(attributes, sheet[0]); + + const pts = get(ptStore); + const data = sheet.slice(1, sheet.length); + data.forEach((row) => { + const uin = row[m["UIN"]]; + const u = parseInt(uin, 10); + if (pts.has(u)) { + const pt = pts.get(u); + pt.email = row[m["Email Address"]]; + pt.phone_number = row[m["Phone Number"]]; + pt.gender = row[m["Gender"]]; + pt.ethnicity = row[m["Racial Background"]]; + pt.graduation = row[m["When are you graduating? (Day does not matter)"]] + const c_teach = row[m["Classes you CAN peer teach for"]].split(",").map((val) => parseInt(val)); + pt.can_teach = new Set(c_teach) + const p_teach = row[m["Classes you PREFER to peer teach for"]].split(",").map((val) => parseInt(val)); + pt.pref_teach = new Set(p_teach); + const hours_work: number = parseInt(row[m["Number of hours you prefer to work"]]); + pt.pref_work = hours_work; + pt.new_ret = row[m["Are you a new hire or returning?"]] + pt.prof_pic_url = row[m["Profile picture for website (image)"]]; + pt.schedule_url = row[m["Schedule (text file)"]]; + } + }) +} + +/** + * @param {Array} attributes Strings of attributes to look for + * @param {Array} title_row Title row of sheet (usually first row: data[0]) + * @return {Object} [key: attribute, value: index] + */ +function mapAttributeToIndex(attributes: string[], title_row: string[]) { + return attributes.reduce((prev, curr) => ({ + ...prev, + [curr]: title_row.findIndex((cell) => cell.toString().toLocaleLowerCase().split(" ").join("").trim() == curr.toLocaleLowerCase().split(" ").join("").trim()) + }), {}) }
\ No newline at end of file |
