Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1172 lecture week view #1411

Merged
merged 8 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion web/template/home.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,11 @@
:class="{'active' : isListView() }">
List View
</button>
<button type="button" @click="toggleWeekView()"
class="tum-live-button tum-live-button-tertiary"
:class="{'active' : isWeekView() }">
Week View
</button>
</section>
</header>
<section>
Expand All @@ -449,7 +454,7 @@
x-for="group in courseStreams.get(sortFn(streamSortMode), filterPred(streamFilterMode))">
<article class="mb-8">
<header class="mb-2">
<h6 class="font-semibold" x-text="group[0].GetMonthName()"></h6>
<h6 class="font-semibold" x-text="groupNames.get(group[0].ID);"></h6>
</header>
<section class="grid gap-3 grid-cols-1"
:class="isListView() ? 'xl:grid-cols-1 lg:grid-cols-1 md:grid-cols-1 grid-cols-1' : plannedStreams.hasElements()
Expand Down
6 changes: 6 additions & 0 deletions web/ts/api/courses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ type DownloadableVOD = {
readonly DownloadURL: string;
};

const MS_IN_DAY = 1000 * 60 * 60 * 24;

export class Stream implements Identifiable {
readonly ID: number;
readonly Name: string;
Expand Down Expand Up @@ -118,6 +120,10 @@ export class Stream implements Identifiable {
][this.StartDate().getMonth()];
}

public GetWeekNumber(dateOfFirstWeek: Date): number {
return Math.floor((this.StartDate().getTime() - dateOfFirstWeek.getTime()) / MS_IN_DAY / 7) + 1;
}

private static TimeOf(d: string): string {
return new Date(d).toLocaleTimeString("default", { hour: "2-digit", minute: "2-digit" });
}
Expand Down
85 changes: 81 additions & 4 deletions web/ts/components/course.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ export enum ViewMode {
List,
}

export enum GroupMode {
Month,
Week,
}

export function courseContext(slug: string, year: number, term: string, userId: number): AlpineComponent {
return {
userId: userId as number,
Expand All @@ -41,6 +46,11 @@ export function courseContext(slug: string, year: number, term: string, userId:
streamSortMode: +getFromStorage("streamSortMode") ?? StreamSortMode.NewestFirst,
streamFilterMode: +getFromStorage("streamFilterMode") ?? StreamFilterMode.ShowWatched,
viewMode: (+getFromStorage("viewMode") ?? ViewMode.Grid) as number,
groupMode: (+getFromStorage("groupMode") ?? GroupMode.Month) as number,

dateOfFirstWeek: new Date(),
weekCountWithoutEmptyWeeks: new Map<number, number>(),
groupNames: new Map<number, string>(),

/**
* AlpineJS init function which is called automatically in addition to 'x-init'
Expand Down Expand Up @@ -68,10 +78,12 @@ export function courseContext(slug: string, year: number, term: string, userId:
this.loadPinned();
this.plannedStreams.set(this.course.Planned.reverse()).reset();
this.upcomingStreams.set(this.course.Upcoming).reset();
this.loadProgresses(this.course.Recordings.map((s: Stream) => s.ID)).then((progresses) => {
this.course.Recordings.forEach((s: Stream, i) => (s.Progress = progresses[i]));
this.courseStreams.set(this.course.Recordings, (s: Stream) => s.StartDate().getMonth());
});
this.loadProgresses(this.course.Recordings.map((s: Stream) => s.ID))
.then((progresses) => {
this.course.Recordings.forEach((s: Stream, i) => (s.Progress = progresses[i]));
})
.then(() => this.initializeWeekMap())
.then(() => this.applyGroupView());
console.log("🌑 init course", this.course);
});
},
Expand Down Expand Up @@ -132,6 +144,71 @@ export function courseContext(slug: string, year: number, term: string, userId:
return this.viewMode == ViewMode.List;
},

toggleWeekView() {
this.groupMode = this.groupMode === GroupMode.Month ? GroupMode.Week : GroupMode.Month;
setInStorage("groupMode", this.groupMode.toString());
this.applyGroupView();
},

isWeekView() {
return this.groupMode == GroupMode.Week;
},

applyGroupView() {
if (this.groupMode === GroupMode.Month) {
this.courseStreams.set(this.course.Recordings, (s: Stream) => s.StartDate().getMonth());
} else {
this.courseStreams.set(this.course.Recordings, (s: Stream) =>
this.getTrueWeek(s.GetWeekNumber(this.dateOfFirstWeek)),
);
}

// update group names
const groups = this.courseStreams.get(
this.sortFn(this.streamSortMode),
this.filterPred(this.streamFilterMode),
);
this.groupNames.clear();
for (let i = 0; i < groups.length; i++) {
const s1 = groups[i][0];
this.groupNames.set(s1.ID, this.getGroupName(s1));
const s2 = groups[i][groups[i].length - 1];
this.groupNames.set(s2.ID, this.getGroupName(s2));
}
},

/**
* Maps the difference in Weeks between any lecture and the first lecture to the true week count ignoring weeks without lectures (e.g. Christmas Break)
*/
initializeWeekMap() {
let latestWeek = 1;
this.course.Recordings.sort(this.sortFn(StreamSortMode.OldestFirst)).forEach((s: Stream, i: number) => {
if (i === 0) {
this.dateOfFirstWeek = s.StartDate();
this.dateOfFirstWeek = new Date(
this.dateOfFirstWeek.getTime() - this.dateOfFirstWeek.getDay() * 1000 * 60 * 60 * 24,
);
this.dateOfFirstWeek.setHours(0, 1); // avoids errors e.g. in case week1 has vod on Monday at 10am, week2 at 8am
}
const week = s.GetWeekNumber(this.dateOfFirstWeek);
if (!this.weekCountWithoutEmptyWeeks.has(week)) {
this.weekCountWithoutEmptyWeeks.set(week, latestWeek++);
}
});
},

getTrueWeek(n: number): number {
return this.weekCountWithoutEmptyWeeks.get(n);
},

getGroupName(s: Stream): string {
if (this.groupMode === GroupMode.Month) {
return s.GetMonthName();
} else {
return "Week " + this.getTrueWeek(s.GetWeekNumber(this.dateOfFirstWeek)).toString();
}
},

/**
* Depending on the pinned value, pin or unpin course
*/
Expand Down
Loading