commit
80f1b96f61
|
@ -15,7 +15,12 @@
|
|||
import { Component, OnInit, OnDestroy, Input, OnChanges, SimpleChange } from '@angular/core';
|
||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreCoursesProvider, CoreCoursesMyCoursesUpdatedEventData, CoreCourses } from '@features/courses/services/courses';
|
||||
import {
|
||||
CoreCoursesProvider,
|
||||
CoreCoursesMyCoursesUpdatedEventData,
|
||||
CoreCourses,
|
||||
CoreCourseSummaryData,
|
||||
} from '@features/courses/services/courses';
|
||||
import { CoreCourseSearchedDataWithExtraInfoAndOptions, CoreCoursesHelper } from '@features/courses/services/courses-helper';
|
||||
import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper';
|
||||
import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate';
|
||||
|
@ -35,7 +40,7 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
|||
|
||||
@Input() downloadEnabled = false;
|
||||
|
||||
courses: CoreCourseSearchedDataWithExtraInfoAndOptions[] = [];
|
||||
courses: (Omit<CoreCourseSummaryData, 'visible'> & CoreCourseSearchedDataWithExtraInfoAndOptions)[] = [];
|
||||
prefetchCoursesData: CorePrefetchStatusInfo = {
|
||||
icon: '',
|
||||
statusTranslatable: 'core.loading',
|
||||
|
@ -52,7 +57,6 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
|||
protected isDestroyed = false;
|
||||
protected coursesObserver?: CoreEventObserver;
|
||||
protected updateSiteObserver?: CoreEventObserver;
|
||||
protected courseIds = [];
|
||||
protected fetchContentDefaultError = 'Error getting recent courses data.';
|
||||
|
||||
constructor() {
|
||||
|
@ -60,7 +64,7 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
|||
}
|
||||
|
||||
/**
|
||||
* Component being initialized.
|
||||
* @inheritdoc
|
||||
*/
|
||||
async ngOnInit(): Promise<void> {
|
||||
// Generate unique id for scroll element.
|
||||
|
@ -82,12 +86,8 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
|||
this.coursesObserver = CoreEvents.on(
|
||||
CoreCoursesProvider.EVENT_MY_COURSES_UPDATED,
|
||||
(data) => {
|
||||
|
||||
if (this.shouldRefreshOnUpdatedEvent(data)) {
|
||||
this.refreshCourseList();
|
||||
}
|
||||
this.refreshCourseList(data);
|
||||
},
|
||||
|
||||
CoreSites.getCurrentSiteId(),
|
||||
);
|
||||
|
||||
|
@ -95,7 +95,7 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
|||
}
|
||||
|
||||
/**
|
||||
* Detect changes on input properties.
|
||||
* @inheritdoc
|
||||
*/
|
||||
ngOnChanges(changes: {[name: string]: SimpleChange}): void {
|
||||
if (changes.downloadEnabled && !changes.downloadEnabled.previousValue && this.downloadEnabled && this.loaded) {
|
||||
|
@ -105,21 +105,35 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
|||
}
|
||||
|
||||
/**
|
||||
* Perform the invalidate content function.
|
||||
*
|
||||
* @return Resolved when done.
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected async invalidateContent(): Promise<void> {
|
||||
const courseIds = this.courses.map((course) => course.id);
|
||||
|
||||
await this.invalidateCourses(courseIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to invalidate only selected courses.
|
||||
*
|
||||
* @param courseIds Course Id array.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected async invalidateCourses(courseIds: number[]): Promise<void> {
|
||||
const promises: Promise<void>[] = [];
|
||||
|
||||
// Invalidate course completion data.
|
||||
promises.push(CoreCourses.invalidateRecentCourses().finally(() =>
|
||||
// Invalidate course completion data.
|
||||
CoreUtils.allPromises(this.courseIds.map((courseId) =>
|
||||
CoreUtils.allPromises(courseIds.map((courseId) =>
|
||||
AddonCourseCompletion.invalidateCourseCompletion(courseId)))));
|
||||
|
||||
promises.push(CoreCourseOptionsDelegate.clearAndInvalidateCoursesOptions());
|
||||
if (this.courseIds.length > 0) {
|
||||
promises.push(CoreCourses.invalidateCoursesByField('ids', this.courseIds.join(',')));
|
||||
if (courseIds.length == 1) {
|
||||
promises.push(CoreCourseOptionsDelegate.clearAndInvalidateCoursesOptions(courseIds[0]));
|
||||
} else {
|
||||
promises.push(CoreCourseOptionsDelegate.clearAndInvalidateCoursesOptions());
|
||||
}
|
||||
if (courseIds.length > 0) {
|
||||
promises.push(CoreCourses.invalidateCoursesByField('ids', courseIds.join(',')));
|
||||
}
|
||||
|
||||
await CoreUtils.allPromises(promises).finally(() => {
|
||||
|
@ -128,9 +142,7 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
|||
}
|
||||
|
||||
/**
|
||||
* Fetch the courses for recent courses.
|
||||
*
|
||||
* @return Promise resolved when done.
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected async fetchContent(): Promise<void> {
|
||||
const showCategories = this.block.configsRecord && this.block.configsRecord.displaycategories &&
|
||||
|
@ -140,17 +152,17 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
|||
const courseIds = recentCourses.map((course) => course.id);
|
||||
|
||||
// Get the courses using getCoursesByField to get more info about each course.
|
||||
const courses: CoreCourseSearchedDataWithExtraInfoAndOptions[] = await CoreCourses.getCoursesByField(
|
||||
'ids',
|
||||
courseIds.join(','),
|
||||
);
|
||||
const courses = await CoreCourses.getCoursesByField('ids', courseIds.join(','));
|
||||
|
||||
// Sort them in the original order.
|
||||
courses.sort((courseA, courseB) => courseIds.indexOf(courseA.id) - courseIds.indexOf(courseB.id));
|
||||
this.courses = recentCourses.map((recentCourse) => {
|
||||
const course = courses.find((course) => recentCourse.id == course.id);
|
||||
|
||||
return Object.assign(recentCourse, course);
|
||||
});
|
||||
|
||||
// Get course options and extra info.
|
||||
const options = await CoreCourses.getCoursesAdminAndNavOptions(courseIds);
|
||||
courses.forEach((course) => {
|
||||
this.courses.forEach((course) => {
|
||||
course.navOptions = options.navOptions[course.id];
|
||||
course.admOptions = options.admOptions[course.id];
|
||||
|
||||
|
@ -161,24 +173,9 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
|||
|
||||
await CoreCoursesHelper.loadCoursesColorAndImage(courses);
|
||||
|
||||
this.courses = courses;
|
||||
|
||||
this.initPrefetchCoursesIcons();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the list of courses.
|
||||
*
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected async refreshCourseList(): Promise<void> {
|
||||
CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_REFRESHED);
|
||||
|
||||
await CoreUtils.ignoreErrors(CoreCourses.invalidateRecentCourses());
|
||||
|
||||
await this.loadContent(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the prefetch icon for selected courses.
|
||||
*/
|
||||
|
@ -194,44 +191,39 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
|||
}
|
||||
|
||||
/**
|
||||
* Whether list should be refreshed based on a EVENT_MY_COURSES_UPDATED event.
|
||||
* Refresh course list based on a EVENT_MY_COURSES_UPDATED event.
|
||||
*
|
||||
* @param data Event data.
|
||||
* @return Whether to refresh.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected shouldRefreshOnUpdatedEvent(data: CoreCoursesMyCoursesUpdatedEventData): boolean {
|
||||
protected async refreshCourseList(data: CoreCoursesMyCoursesUpdatedEventData): Promise<void> {
|
||||
if (data.action == CoreCoursesProvider.ACTION_ENROL) {
|
||||
// Always update if user enrolled in a course.
|
||||
return true;
|
||||
return await this.refreshContent();
|
||||
}
|
||||
|
||||
if (data.action == CoreCoursesProvider.ACTION_VIEW && data.courseId != CoreSites.getCurrentSiteHomeId() &&
|
||||
this.courses[0] && data.courseId != this.courses[0].id) {
|
||||
// Update list if user viewed a course that isn't the most recent one and isn't site home.
|
||||
return true;
|
||||
const courseIndex = this.courses.findIndex((course) => course.id == data.courseId);
|
||||
const course = this.courses[courseIndex];
|
||||
if (data.action == CoreCoursesProvider.ACTION_VIEW && data.courseId != CoreSites.getCurrentSiteHomeId()) {
|
||||
if (!course) {
|
||||
// Not found, use WS update.
|
||||
return await this.refreshContent();
|
||||
}
|
||||
|
||||
// Place at the begining.
|
||||
this.courses.splice(courseIndex, 1);
|
||||
this.courses.unshift(course);
|
||||
|
||||
await this.invalidateCourses([course.id]);
|
||||
}
|
||||
|
||||
if (data.action == CoreCoursesProvider.ACTION_STATE_CHANGED && data.state == CoreCoursesProvider.STATE_FAVOURITE &&
|
||||
data.courseId && this.hasCourse(data.courseId)) {
|
||||
// Update list if a visible course is now favourite or unfavourite.
|
||||
return true;
|
||||
if (data.action == CoreCoursesProvider.ACTION_STATE_CHANGED &&
|
||||
data.state == CoreCoursesProvider.STATE_FAVOURITE && course) {
|
||||
course.isfavourite = !!data.value;
|
||||
await this.invalidateCourses([course.id]);
|
||||
|
||||
this.initPrefetchCoursesIcons();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a certain course is in the list of courses.
|
||||
*
|
||||
* @param courseId Course ID to search.
|
||||
* @return Whether it's in the list.
|
||||
*/
|
||||
protected hasCourse(courseId: number): boolean {
|
||||
if (!this.courses) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !!this.courses.find((course) => course.id == courseId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -253,7 +245,7 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
|
|||
}
|
||||
|
||||
/**
|
||||
* Component being destroyed.
|
||||
* @inheritdoc
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
this.isDestroyed = true;
|
||||
|
|
|
@ -52,7 +52,6 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im
|
|||
protected isDestroyed = false;
|
||||
protected coursesObserver?: CoreEventObserver;
|
||||
protected updateSiteObserver?: CoreEventObserver;
|
||||
protected courseIds: number[] = [];
|
||||
protected fetchContentDefaultError = 'Error getting starred courses data.';
|
||||
|
||||
constructor() {
|
||||
|
@ -60,7 +59,7 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im
|
|||
}
|
||||
|
||||
/**
|
||||
* Component being initialized.
|
||||
* @inheritdoc
|
||||
*/
|
||||
async ngOnInit(): Promise<void> {
|
||||
// Generate unique id for scroll element.
|
||||
|
@ -76,17 +75,12 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im
|
|||
this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => {
|
||||
this.downloadCourseEnabled = !CoreCourses.isDownloadCourseDisabledInSite();
|
||||
this.downloadCoursesEnabled = !CoreCourses.isDownloadCoursesDisabledInSite();
|
||||
|
||||
}, CoreSites.getCurrentSiteId());
|
||||
|
||||
this.coursesObserver = CoreEvents.on(
|
||||
CoreCoursesProvider.EVENT_MY_COURSES_UPDATED,
|
||||
(data) => {
|
||||
|
||||
if (this.shouldRefreshOnUpdatedEvent(data)) {
|
||||
this.refreshCourseList();
|
||||
}
|
||||
this.refreshContent();
|
||||
this.refreshCourseList(data);
|
||||
},
|
||||
|
||||
CoreSites.getCurrentSiteId(),
|
||||
|
@ -96,7 +90,7 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im
|
|||
}
|
||||
|
||||
/**
|
||||
* Detect changes on input properties.
|
||||
* @inheritdoc
|
||||
*/
|
||||
ngOnChanges(changes: {[name: string]: SimpleChange}): void {
|
||||
if (changes.downloadEnabled && !changes.downloadEnabled.previousValue && this.downloadEnabled && this.loaded) {
|
||||
|
@ -106,21 +100,35 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im
|
|||
}
|
||||
|
||||
/**
|
||||
* Perform the invalidate content function.
|
||||
*
|
||||
* @return Resolved when done.
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected async invalidateContent(): Promise<void> {
|
||||
const courseIds = this.courses.map((course) => course.id);
|
||||
|
||||
await this.invalidateCourses(courseIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to invalidate only selected courses.
|
||||
*
|
||||
* @param courseIds Course Id array.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected async invalidateCourses(courseIds: number[]): Promise<void> {
|
||||
const promises: Promise<void>[] = [];
|
||||
|
||||
// Invalidate course completion data.
|
||||
promises.push(CoreCourses.invalidateUserCourses().finally(() =>
|
||||
// Invalidate course completion data.
|
||||
CoreUtils.allPromises(this.courseIds.map((courseId) =>
|
||||
CoreUtils.allPromises(courseIds.map((courseId) =>
|
||||
AddonCourseCompletion.invalidateCourseCompletion(courseId)))));
|
||||
|
||||
promises.push(CoreCourseOptionsDelegate.clearAndInvalidateCoursesOptions());
|
||||
if (this.courseIds.length > 0) {
|
||||
promises.push(CoreCourses.invalidateCoursesByField('ids', this.courseIds.join(',')));
|
||||
if (courseIds.length == 1) {
|
||||
promises.push(CoreCourseOptionsDelegate.clearAndInvalidateCoursesOptions(courseIds[0]));
|
||||
} else {
|
||||
promises.push(CoreCourseOptionsDelegate.clearAndInvalidateCoursesOptions());
|
||||
}
|
||||
if (courseIds.length > 0) {
|
||||
promises.push(CoreCourses.invalidateCoursesByField('ids', courseIds.join(',')));
|
||||
}
|
||||
|
||||
await CoreUtils.allPromises(promises).finally(() => {
|
||||
|
@ -129,54 +137,54 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im
|
|||
}
|
||||
|
||||
/**
|
||||
* Fetch the courses.
|
||||
*
|
||||
* @return Promise resolved when done.
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected async fetchContent(): Promise<void> {
|
||||
const showCategories = this.block.configsRecord && this.block.configsRecord.displaycategories &&
|
||||
this.block.configsRecord.displaycategories.value == '1';
|
||||
|
||||
// @TODO: Sort won't coincide with website because timemodified is not informed.
|
||||
this.courses = await CoreCoursesHelper.getUserCoursesWithOptions('timemodified', 0, 'isfavourite', showCategories);
|
||||
|
||||
this.initPrefetchCoursesIcons();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the list of courses.
|
||||
*
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected async refreshCourseList(): Promise<void> {
|
||||
CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_REFRESHED);
|
||||
|
||||
try {
|
||||
await CoreCourses.invalidateUserCourses();
|
||||
} catch (error) {
|
||||
// Ignore errors.
|
||||
}
|
||||
|
||||
await this.loadContent(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether list should be refreshed based on a EVENT_MY_COURSES_UPDATED event.
|
||||
* Refresh course list based on a EVENT_MY_COURSES_UPDATED event.
|
||||
*
|
||||
* @param data Event data.
|
||||
* @return Whether to refresh.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected shouldRefreshOnUpdatedEvent(data: CoreCoursesMyCoursesUpdatedEventData): boolean {
|
||||
protected async refreshCourseList(data: CoreCoursesMyCoursesUpdatedEventData): Promise<void> {
|
||||
if (data.action == CoreCoursesProvider.ACTION_ENROL) {
|
||||
// Always update if user enrolled in a course.
|
||||
// New courses shouldn't be favourite by default, but just in case.
|
||||
return true;
|
||||
return await this.refreshContent();
|
||||
}
|
||||
|
||||
if (data.action == CoreCoursesProvider.ACTION_STATE_CHANGED && data.state == CoreCoursesProvider.STATE_FAVOURITE) {
|
||||
// Update list when making a course favourite or not.
|
||||
return true;
|
||||
}
|
||||
const courseIndex = this.courses.findIndex((course) => course.id == data.courseId);
|
||||
if (courseIndex < 0) {
|
||||
// Not found, use WS update. Usually new favourite.
|
||||
return await this.refreshContent();
|
||||
}
|
||||
|
||||
return false;
|
||||
const course = this.courses[courseIndex];
|
||||
if (data.value === false) {
|
||||
// Unfavourite, just remove.
|
||||
this.courses.splice(courseIndex, 1);
|
||||
} else {
|
||||
// List is not synced, favourite course and place it at the begining.
|
||||
course.isfavourite = !!data.value;
|
||||
|
||||
this.courses.splice(courseIndex, 1);
|
||||
this.courses.unshift(course);
|
||||
}
|
||||
|
||||
await this.invalidateCourses([course.id]);
|
||||
this.initPrefetchCoursesIcons();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -212,7 +220,7 @@ export class AddonBlockStarredCoursesComponent extends CoreBlockBaseComponent im
|
|||
}
|
||||
|
||||
/**
|
||||
* Component being destroyed.
|
||||
* @inheritdoc
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
this.isDestroyed = true;
|
||||
|
|
|
@ -47,6 +47,6 @@
|
|||
[course]="course" [from]="dataFrom" [to]="dataTo"></addon-block-timeline-events>
|
||||
</ng-container>
|
||||
<core-empty-box *ngIf="timelineCourses.courses.length == 0" image="assets/img/icons/courses.svg" inline="true"
|
||||
[message]="'addon.block_timeline.nocoursesinprogress' | translate"></core-empty-box>
|
||||
[message]="'addon.block_timeline.noevents' | translate"></core-empty-box>
|
||||
</core-loading>
|
||||
</core-loading>
|
||||
|
|
|
@ -176,9 +176,15 @@ export class AddonBlockTimelineComponent extends CoreBlockBaseComponent implemen
|
|||
|
||||
const courseEvents = await AddonBlockTimeline.getActionEventsByCourses(this.courseIds);
|
||||
|
||||
this.timelineCourses.courses.forEach((course) => {
|
||||
this.timelineCourses.courses = this.timelineCourses.courses.filter((course) => {
|
||||
if (courseEvents[course.id].events.length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
course.events = courseEvents[course.id].events;
|
||||
course.canLoadMore = courseEvents[course.id].canLoadMore;
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ export class AddonBlogMainMenuHandlerService implements CoreMainMenuHandler {
|
|||
static readonly PAGE_NAME = 'blog';
|
||||
|
||||
name = 'AddonBlog';
|
||||
priority = 450;
|
||||
priority = 500;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
|
|
|
@ -26,7 +26,7 @@ export class AddonCalendarMainMenuHandlerService implements CoreMainMenuHandler
|
|||
static readonly PAGE_NAME = 'calendar';
|
||||
|
||||
name = 'AddonCalendar';
|
||||
priority = 900;
|
||||
priority = 800;
|
||||
|
||||
/**
|
||||
* Check if the handler is enabled on a site level.
|
||||
|
|
|
@ -38,7 +38,7 @@ export class AddonMessagesMainMenuHandlerService implements CoreMainMenuHandler,
|
|||
static readonly PAGE_NAME = 'messages';
|
||||
|
||||
name = 'AddonMessages';
|
||||
priority = 800;
|
||||
priority = 700;
|
||||
|
||||
protected handler: CoreMainMenuHandlerToDisplay = {
|
||||
icon: 'fas-comments',
|
||||
|
|
|
@ -33,7 +33,7 @@ export class AddonNotificationsMainMenuHandlerService implements CoreMainMenuHan
|
|||
static readonly PAGE_NAME = 'notifications';
|
||||
|
||||
name = 'AddonNotifications';
|
||||
priority = 700;
|
||||
priority = 600;
|
||||
|
||||
protected handlerData: CoreMainMenuHandlerData = {
|
||||
icon: 'fas-bell',
|
||||
|
|
|
@ -29,7 +29,7 @@ export class CoreCoursesMyCoursesMainMenuHandlerService implements CoreMainMenuH
|
|||
static readonly PAGE_NAME = 'courses';
|
||||
|
||||
name = 'CoreCoursesMyCourses';
|
||||
priority = 850;
|
||||
priority = 900;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
:host-context(ion-tabs.placement-side div.tabs-inner) {
|
||||
core-user-avatar {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:host-context(ion-tabs.placement-side ion-toolbar) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
:host-context(ion-toolbar) core-user-avatar ::ng-deep img {
|
||||
padding: 2px !important;
|
||||
border: 1px solid var(--color);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreDashboardHomeHandler } from '@features/courses/services/handlers/dashboard-home';
|
||||
import { CoreSiteHomeHomeHandler } from '@features/sitehome/services/handlers/sitehome-home';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { CoreMainMenuHandler, CoreMainMenuHandlerData } from '../mainmenu-delegate';
|
||||
|
||||
|
@ -25,13 +28,18 @@ export class CoreMainMenuHomeHandlerService implements CoreMainMenuHandler {
|
|||
static readonly PAGE_NAME = 'home';
|
||||
|
||||
name = 'CoreHome';
|
||||
priority = 1100;
|
||||
priority = 1000;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async isEnabled(): Promise<boolean> {
|
||||
return true;
|
||||
const siteId = CoreSites.getCurrentSiteId();
|
||||
|
||||
const dashboardEnabled = await CoreDashboardHomeHandler.isEnabledForSite(siteId);
|
||||
const siteHomeEnabled = await CoreSiteHomeHomeHandler.isEnabledForSite(siteId);
|
||||
|
||||
return dashboardEnabled || siteHomeEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,7 +27,7 @@ export class CoreTagMainMenuHandlerService implements CoreMainMenuHandler {
|
|||
static readonly PAGE_NAME = 'tag';
|
||||
|
||||
name = 'CoreTag';
|
||||
priority = 300;
|
||||
priority = 400;
|
||||
|
||||
/**
|
||||
* Check if the handler is enabled on a site level.
|
||||
|
|
|
@ -1090,7 +1090,7 @@ export class CoreSitesProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the list of sites stored, sorted by URL and full name.
|
||||
* Get the list of sites stored, sorted by sitename, URL and fullname.
|
||||
*
|
||||
* @param ids IDs of the sites to get. If not defined, return all sites.
|
||||
* @return Promise resolved when the sites are retrieved.
|
||||
|
@ -1098,24 +1098,28 @@ export class CoreSitesProvider {
|
|||
async getSortedSites(ids?: string[]): Promise<CoreSiteBasicInfo[]> {
|
||||
const sites = await this.getSites(ids);
|
||||
|
||||
// Sort sites by url and fullname.
|
||||
// Sort sites by site name, url and then fullname.
|
||||
sites.sort((a, b) => {
|
||||
// First compare by site url without the protocol.
|
||||
const compare = a.siteUrlWithoutProtocol.localeCompare(b.siteUrlWithoutProtocol);
|
||||
// First compare by site name.
|
||||
let textA = CoreTextUtils.cleanTags(a.siteName).toLowerCase().trim();
|
||||
let textB = CoreTextUtils.cleanTags(b.siteName).toLowerCase().trim();
|
||||
|
||||
let compare = textA.localeCompare(textB);
|
||||
if (compare !== 0) {
|
||||
return compare;
|
||||
}
|
||||
|
||||
// If site url is the same, use fullname instead.
|
||||
const fullNameA = a.fullName?.toLowerCase().trim();
|
||||
const fullNameB = b.fullName?.toLowerCase().trim();
|
||||
|
||||
if (!fullNameA || !fullNameB) {
|
||||
return 0;
|
||||
// If site name is the same, use site url without the protocol.
|
||||
compare = a.siteUrlWithoutProtocol.localeCompare(b.siteUrlWithoutProtocol);
|
||||
if (compare !== 0) {
|
||||
return compare;
|
||||
}
|
||||
|
||||
return fullNameA.localeCompare(fullNameB);
|
||||
// Finally use fullname.
|
||||
textA = a.fullName?.toLowerCase().trim() || '';
|
||||
textB = b.fullName?.toLowerCase().trim() || '';
|
||||
|
||||
return textA.localeCompare(textB);
|
||||
});
|
||||
|
||||
return sites;
|
||||
|
|
Loading…
Reference in New Issue