MOBILE-3881 timeline: Fix overdue tasks showing different from LMS
parent
6d0b53f034
commit
f9b1951347
|
@ -37,6 +37,7 @@ export class AddonBlockTimelineEventsComponent implements OnChanges {
|
||||||
@Input() course?: CoreEnrolledCourseDataWithOptions; // Whether to show the course name.
|
@Input() course?: CoreEnrolledCourseDataWithOptions; // Whether to show the course name.
|
||||||
@Input() from = 0; // Number of days from today to offset the events.
|
@Input() from = 0; // Number of days from today to offset the events.
|
||||||
@Input() to?: number; // Number of days from today to limit the events to. If not defined, no limit.
|
@Input() to?: number; // Number of days from today to limit the events to. If not defined, no limit.
|
||||||
|
@Input() overdue = false; // If filtering overdue events or not.
|
||||||
@Input() canLoadMore = false; // Whether more events can be loaded.
|
@Input() canLoadMore = false; // Whether more events can be loaded.
|
||||||
@Output() loadMore = new EventEmitter(); // Notify that more events should be loaded.
|
@Output() loadMore = new EventEmitter(); // Notify that more events should be loaded.
|
||||||
|
|
||||||
|
@ -53,18 +54,13 @@ export class AddonBlockTimelineEventsComponent implements OnChanges {
|
||||||
|
|
||||||
if (changes.events || changes.from || changes.to) {
|
if (changes.events || changes.from || changes.to) {
|
||||||
if (this.events) {
|
if (this.events) {
|
||||||
const filteredEvents = await this.filterEventsByTime(this.from, this.to);
|
const filteredEvents = await this.filterEventsByTime();
|
||||||
this.empty = !filteredEvents || filteredEvents.length <= 0;
|
this.empty = !filteredEvents || filteredEvents.length <= 0;
|
||||||
|
|
||||||
const now = CoreTimeUtils.timestamp();
|
const eventsByDay: Record<number, AddonBlockTimelineEvent[]> = {};
|
||||||
|
|
||||||
const eventsByDay: Record<number, AddonCalendarEvent[]> = {};
|
|
||||||
filteredEvents.forEach((event) => {
|
filteredEvents.forEach((event) => {
|
||||||
const dayTimestamp = CoreTimeUtils.getMidnightForTimestamp(event.timesort);
|
const dayTimestamp = CoreTimeUtils.getMidnightForTimestamp(event.timesort);
|
||||||
|
|
||||||
// Already calculated on 4.0 onwards but this will be live.
|
|
||||||
event.overdue = event.timesort < now;
|
|
||||||
|
|
||||||
if (eventsByDay[dayTimestamp]) {
|
if (eventsByDay[dayTimestamp]) {
|
||||||
eventsByDay[dayTimestamp].push(event);
|
eventsByDay[dayTimestamp].push(event);
|
||||||
} else {
|
} else {
|
||||||
|
@ -89,20 +85,34 @@ export class AddonBlockTimelineEventsComponent implements OnChanges {
|
||||||
/**
|
/**
|
||||||
* Filter the events by time.
|
* Filter the events by time.
|
||||||
*
|
*
|
||||||
* @param start Number of days to start getting events from today. E.g. -1 will get events from yesterday.
|
|
||||||
* @param end Number of days after the start.
|
|
||||||
* @return Filtered events.
|
* @return Filtered events.
|
||||||
*/
|
*/
|
||||||
protected async filterEventsByTime(start: number, end?: number): Promise<AddonBlockTimelineEvent[]> {
|
protected async filterEventsByTime(): Promise<AddonBlockTimelineEvent[]> {
|
||||||
start = AddonBlockTimeline.getDayStart(start);
|
const start = AddonBlockTimeline.getDayStart(this.from);
|
||||||
end = end !== undefined ? AddonBlockTimeline.getDayStart(end) : end;
|
const end = this.to !== undefined
|
||||||
|
? AddonBlockTimeline.getDayStart(this.to)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const now = CoreTimeUtils.timestamp();
|
||||||
|
const midnight = AddonBlockTimeline.getDayStart();
|
||||||
|
|
||||||
return await Promise.all(this.events.filter((event) => {
|
return await Promise.all(this.events.filter((event) => {
|
||||||
if (end) {
|
if (start > event.timesort || (end && event.timesort >= end)) {
|
||||||
return start <= event.timesort && event.timesort < end;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return start <= event.timesort;
|
// Already calculated on 4.0 onwards but this will be live.
|
||||||
|
event.overdue = event.timesort < now;
|
||||||
|
|
||||||
|
if (event.eventtype === 'open' || event.eventtype === 'opensubmission') {
|
||||||
|
const dayTimestamp = CoreTimeUtils.getMidnightForTimestamp(event.timesort);
|
||||||
|
|
||||||
|
return dayTimestamp > midnight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When filtering by overdue, we fetch all events due today, in case any have elapsed already and are overdue.
|
||||||
|
// This means if filtering by overdue, some events fetched might not be required (eg if due later today).
|
||||||
|
return (!this.overdue || event.overdue);
|
||||||
}).map(async (event) => {
|
}).map(async (event) => {
|
||||||
event.iconUrl = await CoreCourse.getModuleIconSrc(event.icon.component);
|
event.iconUrl = await CoreCourse.getModuleIconSrc(event.icon.component);
|
||||||
event.modulename = event.modulename || event.icon.component;
|
event.modulename = event.modulename || event.icon.component;
|
||||||
|
@ -147,7 +157,8 @@ export class AddonBlockTimelineEventsComponent implements OnChanges {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AddonBlockTimelineEvent = AddonCalendarEvent & {
|
type AddonBlockTimelineEvent = Omit<AddonCalendarEvent, 'eventtype'> & {
|
||||||
|
eventtype: string;
|
||||||
iconUrl?: string;
|
iconUrl?: string;
|
||||||
iconTitle?: string;
|
iconTitle?: string;
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,12 +60,12 @@
|
||||||
|
|
||||||
<core-loading [hideUntil]="timeline.loaded" [hidden]="sort != 'sortbydates'">
|
<core-loading [hideUntil]="timeline.loaded" [hidden]="sort != 'sortbydates'">
|
||||||
<addon-block-timeline-events [events]="timeline.events" [canLoadMore]="timeline.canLoadMore" (loadMore)="loadMore()"
|
<addon-block-timeline-events [events]="timeline.events" [canLoadMore]="timeline.canLoadMore" (loadMore)="loadMore()"
|
||||||
[from]="dataFrom" [to]="dataTo"></addon-block-timeline-events>
|
[from]="dataFrom" [to]="dataTo" [overdue]="overdue"></addon-block-timeline-events>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
<core-loading [hideUntil]="timelineCourses.loaded" [hidden]="sort != 'sortbycourses'">
|
<core-loading [hideUntil]="timelineCourses.loaded" [hidden]="sort != 'sortbycourses'">
|
||||||
<ng-container *ngFor="let course of timelineCourses.courses">
|
<ng-container *ngFor="let course of timelineCourses.courses">
|
||||||
<addon-block-timeline-events [events]="course.events" [canLoadMore]="course.canLoadMore" (loadMore)="loadMore(course)"
|
<addon-block-timeline-events [events]="course.events" [canLoadMore]="course.canLoadMore" (loadMore)="loadMore(course)"
|
||||||
[course]="course" [from]="dataFrom" [to]="dataTo"></addon-block-timeline-events>
|
[course]="course" [from]="dataFrom" [to]="dataTo" [overdue]="overdue"></addon-block-timeline-events>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<core-empty-box *ngIf="timelineCourses.courses.length == 0" image="assets/img/icons/courses.svg"
|
<core-empty-box *ngIf="timelineCourses.courses.length == 0" image="assets/img/icons/courses.svg"
|
||||||
[message]="'addon.block_timeline.noevents' | translate"></core-empty-box>
|
[message]="'addon.block_timeline.noevents' | translate"></core-empty-box>
|
||||||
|
|
|
@ -58,6 +58,7 @@ export class AddonBlockTimelineComponent extends CoreBlockBaseComponent implemen
|
||||||
|
|
||||||
dataFrom?: number;
|
dataFrom?: number;
|
||||||
dataTo?: number;
|
dataTo?: number;
|
||||||
|
overdue = false;
|
||||||
|
|
||||||
searchEnabled = false;
|
searchEnabled = false;
|
||||||
searchText = '';
|
searchText = '';
|
||||||
|
@ -200,6 +201,7 @@ export class AddonBlockTimelineComponent extends CoreBlockBaseComponent implemen
|
||||||
switchFilter(filter: string): void {
|
switchFilter(filter: string): void {
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.currentSite.setLocalSiteConfig('AddonBlockTimelineFilter', this.filter);
|
this.currentSite.setLocalSiteConfig('AddonBlockTimelineFilter', this.filter);
|
||||||
|
this.overdue = this.filter === 'overdue';
|
||||||
|
|
||||||
switch (this.filter) {
|
switch (this.filter) {
|
||||||
case 'overdue':
|
case 'overdue':
|
||||||
|
|
|
@ -45,7 +45,7 @@ import { CoreText } from '@singletons/text';
|
||||||
const ROOT_CACHE_KEY = 'mmaCalendar:';
|
const ROOT_CACHE_KEY = 'mmaCalendar:';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context levels enumeration.
|
* Main calendar Event types enumeration.
|
||||||
*/
|
*/
|
||||||
export enum AddonCalendarEventType {
|
export enum AddonCalendarEventType {
|
||||||
SITE = 'site',
|
SITE = 'site',
|
||||||
|
|
Loading…
Reference in New Issue