From f3619b20e1c5baa342eb7466c67c44d3192bb3eb Mon Sep 17 00:00:00 2001 From: Furkan Sahin Date: Tue, 13 Apr 2021 00:52:32 -0500 Subject: Initial TypeScript refactoring --- src/App.vue | 21 ------- src/features/parser.js | 138 --------------------------------------------- src/features/parser.ts | 141 ++++++++++++++++++++++++++++++++++++++++++++++ src/main.js | 6 -- src/main.ts | 6 ++ src/models/EventInfo.js | 41 -------------- src/models/EventInfo.ts | 46 +++++++++++++++ src/models/Lab.js | 17 ------ src/models/Lab.ts | 23 ++++++++ src/models/PeerTeacher.js | 29 ---------- src/models/PeerTeacher.ts | 41 ++++++++++++++ src/router/index.js | 27 --------- src/router/index.ts | 27 +++++++++ src/shims-vue.d.ts | 6 ++ src/store/index.js | 34 ----------- src/store/index.ts | 36 ++++++++++++ src/views/About.vue | 9 +-- src/views/Editor.vue | 72 +++++++++++------------ src/vuex-shim.d.ts | 17 ++++++ 19 files changed, 382 insertions(+), 355 deletions(-) delete mode 100644 src/features/parser.js create mode 100644 src/features/parser.ts delete mode 100644 src/main.js create mode 100644 src/main.ts delete mode 100644 src/models/EventInfo.js create mode 100644 src/models/EventInfo.ts delete mode 100644 src/models/Lab.js create mode 100644 src/models/Lab.ts delete mode 100644 src/models/PeerTeacher.js create mode 100644 src/models/PeerTeacher.ts delete mode 100644 src/router/index.js create mode 100644 src/router/index.ts create mode 100644 src/shims-vue.d.ts delete mode 100644 src/store/index.js create mode 100644 src/store/index.ts create mode 100644 src/vuex-shim.d.ts (limited to 'src') diff --git a/src/App.vue b/src/App.vue index c3a04c9..34945a9 100644 --- a/src/App.vue +++ b/src/App.vue @@ -15,25 +15,4 @@ html { height: 100vh; max-height: 100vh; } - -/* #app { - font-family: Avenir, Helvetica, Arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-align: center; - color: #2c3e50; -} - -#nav { - padding: 30px; -} - -#nav a { - font-weight: bold; - color: #2c3e50; -} - -#nav a.router-link-exact-active { - color: #42b983; -} */ diff --git a/src/features/parser.js b/src/features/parser.js deleted file mode 100644 index f91d926..0000000 --- a/src/features/parser.js +++ /dev/null @@ -1,138 +0,0 @@ -import Lab from '@/models/Lab'; -import PeerTeacher from '@/models/PeerTeacher'; -import EventInfo from '../models/EventInfo'; - -export function parseLabFile(file) { - const validCourses = [ - '110', - '111', - '121', - '206', - '221', - // '222', - '312', - '313', - // '314', - '315', - ]; - - const reader = new FileReader(); - - return new Promise((resolve, reject) => { - const result = []; - - reader.onload = (event) => { - let jsonData; - try { - jsonData = JSON.parse(event.target.result); - } catch (e) { - reject(new Error(e)); - } - const labs = jsonData.data; - - labs.forEach((lab) => { - if (validCourses.includes(lab.courseNumber)) { - const newLab = new Lab(lab.courseNumber, lab.sequenceNumber); - - if (lab.instructionalMethod !== 'Web Based') { - lab.meetingsFaculty.every((meeting) => { - const { meetingTime } = meeting; - - if (meetingTime.meetingType === 'LAB') { - let days = ''; - days += meetingTime.monday ? 'M' : ''; - days += meetingTime.tuesday ? 'T' : ''; - days += meetingTime.wednesday ? 'W' : ''; - days += meetingTime.thursday ? 'R' : ''; - days += meetingTime.friday ? 'F' : ''; - - newLab.event.days = days; - newLab.event.start = parseInt(meetingTime.beginTime, 10); - newLab.event.end = parseInt(meetingTime.endTime, 10); - - return false; - } - - return true; - }); - } - - result.push(newLab); - } - }); - - resolve(result); - }; - - reader.readAsText(file); - }); -} - -export function parsePtSchedule(file) { - const reader = new FileReader(); - - return new Promise((resolve) => { - reader.onload = (event) => { - const peerTeacher = new PeerTeacher(); - const namePattern = /^(.*)\s(.*)\s(\d{9})/; - const eventPattern = /^(M?T?W?R?F?)\s(\d{1,2}:\d{2})\s?-\s?(\d{1,2}:\d{2})/; - const lines = event.target.result.split('\n').filter((line) => line.trim()); - - lines.forEach((line) => { - const ptName = line.match(namePattern); - if (ptName) { - [, peerTeacher.firstname, peerTeacher.lastname] = ptName; - peerTeacher.uin = parseInt(ptName[3], 10); - } - - const eventMatch = line.match(eventPattern); - if (eventMatch) { - const newEvent = new EventInfo(eventMatch[1]); - newEvent.start = parseInt(eventMatch[2].replace(':', ''), 10); - newEvent.end = parseInt(eventMatch[3].replace(':', ''), 10); - peerTeacher.events.push(newEvent); - } - }); - - resolve(peerTeacher); - }; - - reader.readAsText(file); - }); -} - -export function parsePtDatabase(file) { - const reader = new FileReader(); - - return new Promise((resolve) => { - reader.onload = (event) => { - const jsonObj = JSON.parse(event.target.result); - const result = { - labs: new Map(), - peerTeachers: new Map(), - }; - - Object.keys(jsonObj.labs).forEach((key) => { - const lab = jsonObj.labs[key]; - result.labs.set(key, new Lab(lab.course, - lab.section, new EventInfo(lab.event.days, lab.event.start, lab.event.end))); - }); - - Object.keys(jsonObj.peerTeachers).forEach((key) => { - const pt = jsonObj.peerTeachers[key]; - const ptObj = new PeerTeacher(pt.firstname, pt.lastname, pt.uin); - ptObj.events = pt.events.map((eventObj) => new EventInfo(eventObj.days, - eventObj.start, eventObj.end)); - ptObj.assignedLabs = new Set(); - pt.assignedLabs.forEach((labId) => { - ptObj.assignedLabs.add(labId); - }); - result.peerTeachers.set(key, ptObj); - }); - - resolve(result); - }; - - reader.readAsText(file); - }); -} diff --git a/src/features/parser.ts b/src/features/parser.ts new file mode 100644 index 0000000..6ad1921 --- /dev/null +++ b/src/features/parser.ts @@ -0,0 +1,141 @@ +import Lab from '@/models/Lab'; +import PeerTeacher from '@/models/PeerTeacher'; +import EventInfo from '../models/EventInfo'; + +export function parseLabFile(file: File): Promise { + const validCourses = [ + '110', + '111', + '121', + '206', + '221', + // '222', + '312', + '313', + // '314', + '315', + ]; + + const reader = new FileReader(); + + return new Promise((resolve, reject) => { + const result: Lab[] = []; + + reader.onload = (event) => { + let jsonData; + try { + jsonData = JSON.parse(event.target!.result as string); + } catch (e) { + reject(new Error(e)); + } + const labs = jsonData.data; + + labs.forEach((lab: any) => { + if (validCourses.includes(lab.courseNumber)) { + const newLab = new Lab(lab.courseNumber, lab.sequenceNumber); + + if (lab.instructionalMethod !== 'Web Based') { + lab.meetingsFaculty.every((meeting: any) => { + const { meetingTime } = meeting; + + if (meetingTime.meetingType === 'LAB') { + let days = ''; + days += meetingTime.monday ? 'M' : ''; + days += meetingTime.tuesday ? 'T' : ''; + days += meetingTime.wednesday ? 'W' : ''; + days += meetingTime.thursday ? 'R' : ''; + days += meetingTime.friday ? 'F' : ''; + + newLab.event.days = days; + newLab.event.start = parseInt(meetingTime.beginTime, 10); + newLab.event.end = parseInt(meetingTime.endTime, 10); + + return false; + } + + return true; + }); + } + + result.push(newLab); + } + }); + + resolve(result); + }; + + reader.readAsText(file); + }); +} + +export function parsePtSchedule(file: File): Promise { + const reader = new FileReader(); + + return new Promise((resolve) => { + reader.onload = (event) => { + const peerTeacher = new PeerTeacher(); + const namePattern = /^(.*)\s(.*)\s(\d{9})/; + const eventPattern = /^(M?T?W?R?F?)\s(\d{1,2}:\d{2})\s?-\s?(\d{1,2}:\d{2})/; + const lines = (event.target!.result as string).split('\n').filter((line) => line.trim()); + + lines.forEach((line) => { + const ptName = line.match(namePattern); + if (ptName) { + [, peerTeacher.firstname, peerTeacher.lastname] = ptName; + peerTeacher.uin = parseInt(ptName[3], 10); + } + + const eventMatch = line.match(eventPattern); + if (eventMatch) { + const newEvent = new EventInfo(eventMatch[1]); + newEvent.start = parseInt(eventMatch[2].replace(':', ''), 10); + newEvent.end = parseInt(eventMatch[3].replace(':', ''), 10); + peerTeacher.events.push(newEvent); + } + }); + + resolve(peerTeacher); + }; + + reader.readAsText(file); + }); +} + +export function parsePtDatabase(file: File): Promise<{ + labs: Map, + peerTeachers: Map +}> { + const reader = new FileReader(); + + return new Promise((resolve) => { + reader.onload = (event) => { + const jsonObj = JSON.parse(event.target!.result as string); + const result = { + labs: new Map(), + peerTeachers: new Map(), + }; + + Object.keys(jsonObj.labs).forEach((key) => { + const lab = jsonObj.labs[key]; + result.labs.set(key, new Lab(lab.course, + lab.section, new EventInfo(lab.event.days, lab.event.start, lab.event.end))); + }); + + Object.keys(jsonObj.peerTeachers).forEach((key) => { + const pt = jsonObj.peerTeachers[key]; + const ptObj = new PeerTeacher(pt.firstname, pt.lastname, pt.uin); + ptObj.events = pt.events.map((eventObj: any) => new EventInfo(eventObj.days, + eventObj.start, eventObj.end)); + ptObj.assignedLabs = new Set(); + pt.assignedLabs.forEach((labId: string) => { + ptObj.assignedLabs.add(labId); + }); + result.peerTeachers.set(key, ptObj); + }); + + resolve(result); + }; + + reader.readAsText(file); + }); +} diff --git a/src/main.js b/src/main.js deleted file mode 100644 index c673f53..0000000 --- a/src/main.js +++ /dev/null @@ -1,6 +0,0 @@ -import { createApp } from 'vue'; -import App from './App.vue'; -import router from './router'; -import store from './store'; - -createApp(App).use(store).use(router).mount('#app'); diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..c673f53 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,6 @@ +import { createApp } from 'vue'; +import App from './App.vue'; +import router from './router'; +import store from './store'; + +createApp(App).use(store).use(router).mount('#app'); diff --git a/src/models/EventInfo.js b/src/models/EventInfo.js deleted file mode 100644 index c1624a8..0000000 --- a/src/models/EventInfo.js +++ /dev/null @@ -1,41 +0,0 @@ -export default class EventInfo { - constructor(days = '', start = 0, end = 0) { - this.days = days; - this.start = start; - this.end = end; - } - - static timeToStr(time) { - let hour = Math.floor(time / 100); - let minute = time % 100; - const meridiem = (hour < 12) ? 'AM' : 'PM'; - - if (hour === 0) { - hour = 12; - } else if (hour > 12) { - hour -= 12; - } - - if (minute < 10) { - minute = `0${minute}`; - } - - return `${hour}:${minute} ${meridiem}`; - } - - conflictsWith(event) { - const daysConflict = event.days.match(new RegExp(`[${this.days}]`)); - - if (daysConflict) { - return (this.start <= event.end) && (event.start <= this.end); - } - return false; - } - - get info() { - if (this.days === '') { - return 'ONLINE'; - } - return `${this.days} ${EventInfo.timeToStr(this.start)}-${EventInfo.timeToStr(this.end)}`; - } -} diff --git a/src/models/EventInfo.ts b/src/models/EventInfo.ts new file mode 100644 index 0000000..4493162 --- /dev/null +++ b/src/models/EventInfo.ts @@ -0,0 +1,46 @@ +export default class EventInfo { + days: string; + + start: number; + + end: number; + + constructor(days: string = '', start = 0, end = 0) { + this.days = days; + this.start = start; + this.end = end; + } + + static timeToStr(time: number) { + let hour = Math.floor(time / 100); + const minute = time % 100; + const meridiem = (hour < 12) ? 'AM' : 'PM'; + + if (hour === 0) { + hour = 12; + } else if (hour > 12) { + hour -= 12; + } + + if (minute < 10) { + return `${hour}:0${minute} ${meridiem}`; + } + return `${hour}:${minute} ${meridiem}`; + } + + conflictsWith(event: EventInfo) { + const daysConflict = event.days.match(new RegExp(`[${this.days}]`)); + + if (daysConflict) { + return (this.start <= event.end) && (event.start <= this.end); + } + return false; + } + + get info() { + if (this.days === '') { + return 'ONLINE'; + } + return `${this.days} ${EventInfo.timeToStr(this.start)}-${EventInfo.timeToStr(this.end)}`; + } +} diff --git a/src/models/Lab.js b/src/models/Lab.js deleted file mode 100644 index 2e4412d..0000000 --- a/src/models/Lab.js +++ /dev/null @@ -1,17 +0,0 @@ -import EventInfo from '@/models/EventInfo'; - -export default class Lab { - constructor(course = 0, section = 0, event = new EventInfo()) { - this.course = course; - this.section = section; - this.event = event; - } - - get id() { - return `${this.course}-${this.section}`; - } - - get fullInfo() { - return `${this.id} ${this.event.info}`; - } -} diff --git a/src/models/Lab.ts b/src/models/Lab.ts new file mode 100644 index 0000000..a6972ef --- /dev/null +++ b/src/models/Lab.ts @@ -0,0 +1,23 @@ +import EventInfo from '@/models/EventInfo'; + +export default class Lab { + course: number; + + section: number; + + event: EventInfo; + + constructor(course = 0, section = 0, event = new EventInfo()) { + this.course = course; + this.section = section; + this.event = event; + } + + get id() { + return `${this.course}-${this.section}`; + } + + get fullInfo() { + return `${this.id} ${this.event.info}`; + } +} diff --git a/src/models/PeerTeacher.js b/src/models/PeerTeacher.js deleted file mode 100644 index 00a2f0d..0000000 --- a/src/models/PeerTeacher.js +++ /dev/null @@ -1,29 +0,0 @@ -export default class PeerTeacher { - constructor(firstname = '', lastname = '', uin = 0) { - this.firstname = firstname; - this.lastname = lastname; - this.uin = uin; - this.events = []; - this.assignedLabs = new Set(); - } - - conflictsWith(event) { - let conflicts = false; - this.events.every((item) => { - if (item.conflictsWith(event)) { - conflicts = true; - return false; - } - return true; - }); - return conflicts; - } - - get name() { - return `${this.firstname} ${this.lastname}`; - } - - get id() { - return this.uin; - } -} diff --git a/src/models/PeerTeacher.ts b/src/models/PeerTeacher.ts new file mode 100644 index 0000000..f387431 --- /dev/null +++ b/src/models/PeerTeacher.ts @@ -0,0 +1,41 @@ +import EventInfo from './EventInfo'; + +export default class PeerTeacher { + firstname: string; + + lastname: string; + + uin: number; + + events: EventInfo[]; + + assignedLabs: Set; + + constructor(firstname = '', lastname = '', uin = 0) { + this.firstname = firstname; + this.lastname = lastname; + this.uin = uin; + this.events = []; + this.assignedLabs = new Set(); + } + + conflictsWith(event: EventInfo) { + let conflicts = false; + this.events.every((item) => { + if (item.conflictsWith(event)) { + conflicts = true; + return false; + } + return true; + }); + return conflicts; + } + + get name() { + return `${this.firstname} ${this.lastname}`; + } + + get id() { + return this.uin; + } +} diff --git a/src/router/index.js b/src/router/index.js deleted file mode 100644 index 7a598b3..0000000 --- a/src/router/index.js +++ /dev/null @@ -1,27 +0,0 @@ -import { createRouter, createWebHashHistory } from 'vue-router'; -import Editor from '../views/Editor.vue'; -import About from '../views/About.vue'; - -const routes = [ - { - path: '/', - name: 'About', - component: About, - }, - { - path: '/editor', - name: 'Editor', - // route level code-splitting - // this generates a separate chunk (about.[hash].js) for this route - // which is lazy-loaded when the route is visited. - // component: () => import(/* webpackChunkName: "about" */ '../views/Editor.vue'), - component: Editor, - }, -]; - -const router = createRouter({ - history: createWebHashHistory(), - routes, -}); - -export default router; diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..7a598b3 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,27 @@ +import { createRouter, createWebHashHistory } from 'vue-router'; +import Editor from '../views/Editor.vue'; +import About from '../views/About.vue'; + +const routes = [ + { + path: '/', + name: 'About', + component: About, + }, + { + path: '/editor', + name: 'Editor', + // route level code-splitting + // this generates a separate chunk (about.[hash].js) for this route + // which is lazy-loaded when the route is visited. + // component: () => import(/* webpackChunkName: "about" */ '../views/Editor.vue'), + component: Editor, + }, +]; + +const router = createRouter({ + history: createWebHashHistory(), + routes, +}); + +export default router; diff --git a/src/shims-vue.d.ts b/src/shims-vue.d.ts new file mode 100644 index 0000000..3804a43 --- /dev/null +++ b/src/shims-vue.d.ts @@ -0,0 +1,6 @@ +/* eslint-disable */ +declare module '*.vue' { + import type { DefineComponent } from 'vue' + const component: DefineComponent<{}, {}, any> + export default component +} diff --git a/src/store/index.js b/src/store/index.js deleted file mode 100644 index 0c3a5c9..0000000 --- a/src/store/index.js +++ /dev/null @@ -1,34 +0,0 @@ -import { createStore } from 'vuex'; - -export default createStore({ - state: { - labs: new Map(), - peerTeachers: new Map(), - }, - mutations: { - setLabs(state, labs) { - state.labs = labs; - }, - setPeerTeachers(state, peerTeachers) { - state.peerTeachers = peerTeachers; - }, - importLabs(state, labs) { - state.labs.clear(); - labs.forEach((lab) => { - state.labs.set(lab.id, lab); - }); - }, - addPeerTeachers(state, peerTeachers) { - peerTeachers.forEach((pt) => { - state.peerTeachers.set(pt.id, pt); - }); - }, - deletePeerTeacher(state, id) { - state.peerTeachers.delete(id); - }, - }, - actions: { - }, - modules: { - }, -}); diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..e63e257 --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,36 @@ +import Lab from '@/models/Lab'; +import PeerTeacher from '@/models/PeerTeacher'; +import { createStore } from 'vuex'; + +export default createStore({ + state: { + labs: new Map(), + peerTeachers: new Map(), + }, + mutations: { + setLabs(state, labs: Map) { + state.labs = labs; + }, + setPeerTeachers(state, peerTeachers: Map) { + state.peerTeachers = peerTeachers; + }, + importLabs(state, labs: Lab[]) { + state.labs.clear(); + labs.forEach((lab) => { + state.labs.set(lab.id, lab); + }); + }, + addPeerTeachers(state, peerTeachers: PeerTeacher[]) { + peerTeachers.forEach((pt) => { + state.peerTeachers.set(pt.id, pt); + }); + }, + deletePeerTeacher(state, id: number) { + state.peerTeachers.delete(id); + }, + }, + actions: { + }, + modules: { + }, +}); diff --git a/src/views/About.vue b/src/views/About.vue index ab4725e..ac2bde1 100644 --- a/src/views/About.vue +++ b/src/views/About.vue @@ -7,18 +7,19 @@ - diff --git a/src/views/Editor.vue b/src/views/Editor.vue index 5ef0131..fd83fb7 100644 --- a/src/views/Editor.vue +++ b/src/views/Editor.vue @@ -21,62 +21,58 @@ - diff --git a/src/views/Editor.vue b/src/views/Editor.vue index fd83fb7..b4a2e8e 100644 --- a/src/views/Editor.vue +++ b/src/views/Editor.vue @@ -1,30 +1,14 @@ @@ -106,14 +35,4 @@ export default defineComponent({ #home { max-height: inherit; } - -#editor { - display: flex; - max-height: inherit; -} - -.column { - flex: 1; - overflow: auto; -} -- cgit v1.2.3 From e14581fb25febd28b8e55ca8e2b24ebafa3abbc2 Mon Sep 17 00:00:00 2001 From: Furkan Sahin Date: Tue, 13 Apr 2021 09:52:45 -0500 Subject: Optimize selectedPeerTeacherAssignments sort condition --- src/components/EditorLists.vue | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'src') diff --git a/src/components/EditorLists.vue b/src/components/EditorLists.vue index 2d72b1e..ae0aa22 100644 --- a/src/components/EditorLists.vue +++ b/src/components/EditorLists.vue @@ -53,23 +53,7 @@ export default defineComponent({ .flatMap((id) => { const lab = this.$store.state.labs.get(id); return (lab === undefined) ? [] : [lab]; - }).sort((a, b) => { - if (a.course < b.course) { - return -1; - } - if (b.course < a.course) { - return 1; - } - - if (a.section < b.section) { - return -1; - } - if (b.section < a.section) { - return 1; - } - - return 0; - }); + }).sort((a, b) => a.course - b.course || a.section - b.section); }, }, data() { -- cgit v1.2.3