Skip to content

Commit

Permalink
Clean up types and refactor asset loading (#106)
Browse files Browse the repository at this point in the history
* Clean up types

* Use query parameter for document loading

* Remove console.log

* Use blob urls instead of base64 urls
Chrome doesn't allow top-level navigation to base64 urls, so this increases device support for showing attachments and documents
  • Loading branch information
PurelyAnecdotal authored Dec 26, 2024
1 parent 75e2ff2 commit afa0e6a
Show file tree
Hide file tree
Showing 20 changed files with 220 additions and 232 deletions.
5 changes: 4 additions & 1 deletion bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"workspaces": {
"": {
"dependencies": {
"buffer": "^6.0.3",
"fast-xml-parser": "^4.5.1",
"file-type": "^19.6.0",
},
Expand Down Expand Up @@ -306,7 +307,7 @@

"browserslist": ["browserslist@4.24.3", "", { "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" } }, "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA=="],

"buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
"buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],

"bun-types": ["bun-types@1.1.37", "", { "dependencies": { "@types/node": "~20.12.8", "@types/ws": "~8.5.10" } }, "sha512-C65lv6eBr3LPJWFZ2gswyrGZ82ljnH8flVE03xeXxKhi2ZGtFiO4isRKTKnitbSqtRAcaqYSR6djt1whI66AbA=="],

Expand Down Expand Up @@ -864,6 +865,8 @@

"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],

"bl/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],

"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],

"import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"vite": "^6.0.5"
},
"dependencies": {
"buffer": "^6.0.3",
"fast-xml-parser": "^4.5.1",
"file-type": "^19.6.0"
},
Expand Down
70 changes: 20 additions & 50 deletions src/lib/cache.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import {
attendance,
attendanceLoaded,
documentsList,
documentsListLoaded,
documents,
documentsLoaded,
gradebook,
gradebookLoaded,
mail,
mailLoaded,
messages,
messagesLoaded,
reportCardList,
reportCardListLoaded,
mailData,
mailDataLoaded,
studentAccount,
studentInfo,
studentInfoLoaded
Expand Down Expand Up @@ -46,7 +42,7 @@ export const loadGradebook = async () => {
periodOverrideState.new = restoredState.new;
periodOverrideState.original = restoredState.original;

const grades = await get(studentAccount)?.grades(periodOverrideState.new?.index);
const grades = await get(studentAccount)?.gradebook(periodOverrideState.new?.index);

gradebook.set(grades);

Expand All @@ -55,7 +51,7 @@ export const loadGradebook = async () => {
return;
}

const grades = await get(studentAccount)?.grades();
const grades = await get(studentAccount)?.gradebook();

gradebook.set(grades);
localStorage.setItem('gradebook', JSON.stringify(grades));
Expand Down Expand Up @@ -89,54 +85,28 @@ export const loadStudentInfo = async () => {
studentInfoLoaded.set(true);
};

export const loadReportCardList = async () => {
reportCardListLoaded.set(false);
export const loadDocuments = async () => {
documentsLoaded.set(false);

writeCacheToStore('reportCardList', reportCardList);
writeCacheToStore('documents', documents);

const reportCardListRecord = await get(studentAccount)?.reportCardList();
const documentsRecord = await get(studentAccount)?.documents();

reportCardList.set(reportCardListRecord);
localStorage.setItem('reportCardList', JSON.stringify(reportCardListRecord));
documents.set(documentsRecord);
localStorage.setItem('documents', JSON.stringify(documentsRecord));

reportCardListLoaded.set(true);
documentsLoaded.set(true);
};

export const loadDocumentsList = async () => {
documentsListLoaded.set(false);
export const loadMailData = async () => {
mailDataLoaded.set(false);

writeCacheToStore('documentsList', documentsList);
writeCacheToStore('mailData', mailData);

const documentsListRecord = await get(studentAccount)?.documentsList();
const mailDataRecord = await get(studentAccount)?.mailData();

documentsList.set(documentsListRecord);
localStorage.setItem('documentsList', JSON.stringify(documentsListRecord));
mailData.set(mailDataRecord);
localStorage.setItem('mailData', JSON.stringify(mailDataRecord));

documentsListLoaded.set(true);
};

export const loadMessages = async () => {
messagesLoaded.set(false);

writeCacheToStore('messages', messages);

const messagesRecord = await get(studentAccount)?.messages();

messages.set(messagesRecord);
localStorage.setItem('messages', JSON.stringify(messagesRecord));

messagesLoaded.set(true);
};

export const loadMail = async () => {
mailLoaded.set(false);

writeCacheToStore('mail', mail);

const mailRecord = await get(studentAccount)?.mail();

mail.set(mailRecord);
localStorage.setItem('mail', JSON.stringify(mailRecord));

mailLoaded.set(true);
mailDataLoaded.set(true);
};
15 changes: 15 additions & 0 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { fileTypeFromBuffer } from 'file-type';
import { Buffer } from 'buffer';

export function getColorForGrade(grade: string | number) {
if (typeof grade == 'number') {
if (grade > 100) return 'blue';
Expand Down Expand Up @@ -47,3 +50,15 @@ export const shortDateFormatter = new Intl.DateTimeFormat('en-US', {
export const fullDateFormatter = new Intl.DateTimeFormat('en-US', {
dateStyle: 'full'
});

export async function getBlobURLFromBase64String(base64: string) {
const byteArray = new Uint8Array(Buffer.from(base64, 'base64'));

const mimeType = (await fileTypeFromBuffer(byteArray))?.mime;

if (!mimeType) throw new Error('Could not determine MIME type');

const blob = new Blob([byteArray], { type: mimeType });

return URL.createObjectURL(blob);
}
27 changes: 8 additions & 19 deletions src/lib/stores.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import type { Writable } from 'svelte/store';
import { writable } from 'svelte/store';

import type { StudentAccount } from '$lib/synergy';
import type { Attendance } from '$lib/types/Attendance';
import type { DocumentsList } from '$lib/types/DocumentsList';
import type { Documents } from '$lib/types/Documents';
import type { Gradebook } from '$lib/types/Gradebook';
import type { ReportCardListEntity } from '$lib/types/ReportCardListEntity';
import type { StudentInfo } from '$lib/types/StudentInfo';
import type { MailData } from '$lib/types/MailData';
import type { Message } from '$lib/types/Message';
import type { StudentInfo } from '$lib/types/StudentInfo';
import type { Writable } from 'svelte/store';
import { writable } from 'svelte/store';

export const studentAccount: Writable<StudentAccount | undefined> = writable();

Expand All @@ -24,18 +21,10 @@ export const studentInfo: Writable<StudentInfo | undefined> = writable();

export const studentInfoLoaded = writable(false);

export const reportCardList: Writable<ReportCardListEntity[] | undefined> = writable();

export const reportCardListLoaded = writable(false);

export const documentsList: Writable<DocumentsList | undefined> = writable();

export const documentsListLoaded = writable(false);

export const messages: Writable<Message[] | undefined> = writable();
export const documents: Writable<Documents | undefined> = writable();

export const messagesLoaded = writable(false);
export const documentsLoaded = writable(false);

export const mail: Writable<MailData | undefined> = writable();
export const mailData: Writable<MailData | undefined> = writable();

export const mailLoaded = writable(false);
export const mailDataLoaded = writable(false);
27 changes: 8 additions & 19 deletions src/lib/synergy.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import type { Attachment } from '$lib/types/Attachment';
import type { Attendance } from '$lib/types/Attendance';
import type { AuthToken } from '$lib/types/AuthToken';
import type { DocumentsList } from '$lib/types/DocumentsList';
import type { Documents } from '$lib/types/Documents';
import type { Gradebook } from '$lib/types/Gradebook';
import type { MailData } from '$lib/types/MailData';
import type { Message } from '$lib/types/Message';
import type { ReportCardDocument } from '$lib/types/ReportCardDocument';
import type { ReportCardListEntity } from '$lib/types/ReportCardListEntity';
import type { ReportCard, ReportCardNotFound } from '$lib/types/ReportCard';
import type { StudentInfo } from '$lib/types/StudentInfo';
import { XMLBuilder, XMLParser } from 'fast-xml-parser';

Expand Down Expand Up @@ -101,7 +99,7 @@ export class StudentAccount {
).AuthToken;
}

async grades(reportPeriod?: number): Promise<Gradebook> {
async gradebook(reportPeriod?: number): Promise<Gradebook> {
if (reportPeriod) {
// May return current reporting period instead of the one requested if the one requested cannot be found

Expand All @@ -119,29 +117,20 @@ export class StudentAccount {
return (await this.request('StudentInfo')).StudentInfo;
}

async reportCardList(): Promise<ReportCardListEntity[]> {
return (await this.request('GetReportCardInitialData')).RCReportingPeriodData.RCReportingPeriods
.RCReportingPeriod;
async documents(): Promise<Documents> {
return (await this.request('GetStudentDocumentInitialData')).StudentDocuments;
}

async reportCard(documentGU: string): Promise<ReportCardDocument> {
async reportCard(documentGU: string): Promise<ReportCard> {
return (await this.request('GetReportCardDocumentData', { DocumentGU: documentGU }))
.DocumentData;
}

async documentsList(): Promise<DocumentsList> {
return (await this.request('GetStudentDocumentInitialData')).StudentDocuments;
}

async messages(): Promise<Message[]> {
return (await this.request('GetPXPMessages')).PXPMessagesData.MessageListings.MessageListing;
}

async mail(): Promise<MailData> {
async mailData(): Promise<MailData> {
return (await this.request('SynergyMailGetData')).SynergyMailDataXML;
}

async attachmentBase64(attachmentGU: string): Promise<Attachment> {
async attachment(attachmentGU: string): Promise<Attachment> {
return (await this.request('SynergyMailGetAttachment', { SmAttachmentGU: attachmentGU }))
.AttachmentXML;
}
Expand Down
30 changes: 18 additions & 12 deletions src/lib/types/Attendance.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
export interface Attendance {
Absences: Absences;
TotalExcused: TotalAttendanceEvents;
TotalTardies: TotalAttendanceEvents;
TotalUnexcused: TotalAttendanceEvents;
TotalActivities: TotalAttendanceEvents;
TotalUnexcusedTardies: TotalAttendanceEvents;
TotalExcused: AttendanceEventTotal;
TotalTardies: AttendanceEventTotal;
TotalUnexcused: AttendanceEventTotal;
TotalActivities: AttendanceEventTotal;
TotalUnexcusedTardies: AttendanceEventTotal;
ConcurrentSchoolsLists: string;
'_xmlns:xsd': string;
'_xmlns:xsi': string;
Expand All @@ -14,10 +14,12 @@ export interface Attendance {
_PeriodCount: string;
_SchoolName: string;
}

export interface Absences {
Absence?: AbsenceEntity[] | null;
Absence?: Absence[] | null;
}
export interface AbsenceEntity {

export interface Absence {
Periods: Periods;
_AbsenceDate: string;
_Reason: string;
Expand All @@ -26,10 +28,12 @@ export interface AbsenceEntity {
_CodeAllDayReasonType: string;
_CodeAllDayDescription: string;
}

export interface Periods {
Period?: PeriodEntity[] | null;
Period?: Period[] | null;
}
export interface PeriodEntity {

export interface Period {
_Number: string;
_Name: string;
_Reason: string;
Expand All @@ -41,10 +45,12 @@ export interface PeriodEntity {
_StaffGU: string;
_OrgYearGU: string;
}
export interface TotalAttendanceEvents {
PeriodTotal?: PeriodTotalEntity[] | null;

export interface AttendanceEventTotal {
PeriodTotal?: PeriodTotal[] | null;
}
export interface PeriodTotalEntity {

export interface PeriodTotal {
_Number: string;
_Total: string;
}
8 changes: 5 additions & 3 deletions src/lib/types/DocumentsList.ts → src/lib/types/Documents.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export interface DocumentsList {
export interface Documents {
StudentDocumentDatas: StudentDocumentDatas;
'_xmlns:xsd': string;
'_xmlns:xsi': string;
Expand All @@ -8,10 +8,12 @@ export interface DocumentsList {
_StudentGU: string;
_StudentSSY: string;
}

export interface StudentDocumentDatas {
StudentDocumentData?: StudentDocumentDataEntity[] | null;
StudentDocumentData?: StudentDocumentData[] | null;
}
export interface StudentDocumentDataEntity {

export interface StudentDocumentData {
_DocumentGU: string;
_DocumentFileName: string;
_DocumentDate: string;
Expand Down
14 changes: 0 additions & 14 deletions src/lib/types/Message.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
export interface ReportCardDocument {
Base64Code: string;
export interface ReportCardNotFound {
'_xmlns:xsd': string;
'_xmlns:xsi': string;
}

export interface ReportCard extends ReportCardNotFound {
Base64Code: string;
_DocumentGU: string;
_FileName: string;
_DocFileName: string;
Expand Down
7 changes: 0 additions & 7 deletions src/lib/types/ReportCardListEntity.ts

This file was deleted.

Loading

0 comments on commit afa0e6a

Please sign in to comment.