MOBILE-3594 sitehome: Add sitehome tab to home page
parent
cc5378aee7
commit
9b41458104
|
@ -20,6 +20,7 @@ import { CoreEmulatorModule } from './emulator/emulator.module';
|
||||||
import { CoreFileUploaderInitModule } from './fileuploader/fileuploader-init.module';
|
import { CoreFileUploaderInitModule } from './fileuploader/fileuploader-init.module';
|
||||||
import { CoreLoginModule } from './login/login.module';
|
import { CoreLoginModule } from './login/login.module';
|
||||||
import { CoreSettingsInitModule } from './settings/settings-init.module';
|
import { CoreSettingsInitModule } from './settings/settings-init.module';
|
||||||
|
import { CoreSiteHomeInitModule } from './sitehome/sitehome-init.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -29,6 +30,7 @@ import { CoreSettingsInitModule } from './settings/settings-init.module';
|
||||||
CoreCoursesModule,
|
CoreCoursesModule,
|
||||||
CoreSettingsInitModule,
|
CoreSettingsInitModule,
|
||||||
CoreFileUploaderInitModule,
|
CoreFileUploaderInitModule,
|
||||||
|
CoreSiteHomeInitModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class CoreFeaturesModule {}
|
export class CoreFeaturesModule {}
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-list class="core-search-history" [hidden]="!historyShown">
|
<ion-list class="core-search-history" [hidden]="!historyShown">
|
||||||
<ion-item class="ion-text-wrap" *ngFor="let item of history"
|
<ion-item button class="ion-text-wrap" *ngFor="let item of history"
|
||||||
(click)="historyClicked($event, item.searchedtext)" class="core-clickable" tabindex="1">
|
(click)="historyClicked($event, item.searchedtext)" tabindex="1" detail>
|
||||||
<ion-icon name="fa-history" slot="start">
|
<ion-icon name="fa-history" slot="start">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
{{item.searchedtext}}
|
{{item.searchedtext}}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<ion-item *ngIf="isIOS"
|
<ion-item *ngIf="isIOS"
|
||||||
(click)="openHandler('CoreSharedFilesListPage', {manage: true, siteId: siteId, hideSitePicker: true})"
|
(click)="openHandler('CoreSharedFilesListPage', {manage: true, siteId: siteId, hideSitePicker: true})"
|
||||||
[title]="'core.sharedfiles.sharedfiles' | translate"
|
[title]="'core.sharedfiles.sharedfiles' | translate"
|
||||||
[class.core-split-item-selected]="'CoreSharedFilesListPage' == selectedPage" details>
|
[class.core-split-item-selected]="'CoreSharedFilesListPage' == selectedPage" detail>
|
||||||
<ion-icon name="fas-folder" slot="start"></ion-icon>
|
<ion-icon name="fas-folder" slot="start"></ion-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'core.sharedfiles.sharedfiles' | translate }}</h2>
|
<h2>{{ 'core.sharedfiles.sharedfiles' | translate }}</h2>
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-item *ngFor="let handler of handlers" [ngClass]="['core-settings-handler', handler.class]"
|
<ion-item *ngFor="let handler of handlers" [ngClass]="['core-settings-handler', handler.class]"
|
||||||
(click)="openHandler(handler.page, handler.params)" [title]="handler.title | translate" details
|
(click)="openHandler(handler.page, handler.params)" [title]="handler.title | translate" detail
|
||||||
[class.core-split-item-selected]="handler.page == selectedPage">
|
[class.core-split-item-selected]="handler.page == selectedPage">
|
||||||
<ion-icon [name]="handler.icon" slot="start" *ngIf="handler.icon">
|
<ion-icon [name]="handler.icon" slot="start" *ngIf="handler.icon">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"sitehome": "Site home",
|
||||||
|
"sitenews": "Site announcements"
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
<ion-content>
|
||||||
|
<ion-refresher slot="fixed" [disabled]="!dataLoaded"
|
||||||
|
(ionRefresh)="doRefresh($event)">
|
||||||
|
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||||
|
</ion-refresher>
|
||||||
|
<!-- @todo <core-block-course-blocks [courseId]="siteHomeId" [downloadEnabled]="downloadEnabled">-->
|
||||||
|
<core-loading [hideUntil]="dataLoaded">
|
||||||
|
<ion-list>
|
||||||
|
<!-- Site home main contents. -->
|
||||||
|
<!-- @todo <ng-container *ngIf="section && section.hasContent">
|
||||||
|
<ion-item class="ion-text-wrap" *ngIf="section.summary">
|
||||||
|
<core-format-text [text]="section.summary" contextLevel="course" [contextInstanceId]="siteHomeId"></core-format-text>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<core-course-module *ngFor="let module of section.modules" [module]="module" [courseId]="siteHomeId" [downloadEnabled]="downloadEnabled" [section]="section"></core-course-module>
|
||||||
|
</ng-container> -->
|
||||||
|
|
||||||
|
<!-- Site home items: news, categories, courses, etc. -->
|
||||||
|
<ng-container *ngIf="items.length > 0">
|
||||||
|
<ion-item-divider *ngIf="section && section!.hasContent"></ion-item-divider>
|
||||||
|
<ng-container *ngFor="let item of items">
|
||||||
|
<ng-container [ngSwitch]="item">
|
||||||
|
<ng-container *ngSwitchCase="'LIST_OF_COURSE'">
|
||||||
|
<ng-template *ngTemplateOutlet="allCourseList"></ng-template>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="'LIST_OF_CATEGORIES'">
|
||||||
|
<ng-template *ngTemplateOutlet="categories"></ng-template>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="'COURSE_SEARCH_BOX'">
|
||||||
|
<ng-template *ngTemplateOutlet="courseSearch"></ng-template>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="'ENROLLED_COURSES'">
|
||||||
|
<ng-template *ngTemplateOutlet="enrolledCourseList"></ng-template>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="'NEWS_ITEMS'">
|
||||||
|
<ng-template *ngTemplateOutlet="news"></ng-template>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
</ion-list>
|
||||||
|
<core-empty-box *ngIf="!hasContent" icon="qr-scanner" [message]="'core.course.nocontentavailable' | translate"></core-empty-box>
|
||||||
|
</core-loading>
|
||||||
|
<!-- @todo </core-block-course-blocks> -->
|
||||||
|
</ion-content>
|
||||||
|
|
||||||
|
<ng-template #allCourseList>
|
||||||
|
<ion-item button class="ion-text-wrap" router-direction="forward" routerLink="/courses/all" detail>
|
||||||
|
<ion-icon name="fas-graduation-cap" fixed-width slot="start"></ion-icon>
|
||||||
|
<ion-label>
|
||||||
|
<h2>{{ 'core.courses.availablecourses' | translate}}</h2>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template #news>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>News (TODO)</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
<!-- @todo <core-course-module class="core-sitehome-news" *ngIf="show" [module]="module" [courseId]="siteHomeId"></core-course-module> -->
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template #categories>
|
||||||
|
<ion-item button class="ion-text-wrap" router-direction="forward" routerLink="/courses/categories" detail>
|
||||||
|
<ion-icon name="folder" slot="start"></ion-icon>
|
||||||
|
<ion-label>
|
||||||
|
<h2>{{ 'core.courses.categories' | translate}}</h2>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template #enrolledCourseList>
|
||||||
|
<ion-item button class="ion-text-wrap" router-direction="forward" routerLink="/courses/my" detail>
|
||||||
|
<ion-icon name="fa-graduation-cap" fixed-width slot="start">
|
||||||
|
</ion-icon>
|
||||||
|
<ion-label><h2>{{ 'core.courses.mycourses' | translate}}</h2></ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template #courseSearch>
|
||||||
|
<ion-item button class="ion-text-wrap" router-direction="forward" routerLink="/courses/search" detail>
|
||||||
|
<ion-icon name="search" slot="start"></ion-icon>
|
||||||
|
<ion-label><h2>{{ 'core.courses.searchcourses' | translate}}</h2></ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ng-template>
|
|
@ -0,0 +1,47 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
import { IonicModule } from '@ionic/angular';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||||
|
import { CoreComponentsModule } from '@components/components.module';
|
||||||
|
|
||||||
|
import { CoreSiteHomeIndexPage } from './index.page';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: CoreSiteHomeIndexPage,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forChild(routes),
|
||||||
|
CommonModule,
|
||||||
|
IonicModule,
|
||||||
|
TranslateModule.forChild(),
|
||||||
|
CoreDirectivesModule,
|
||||||
|
CoreComponentsModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
CoreSiteHomeIndexPage,
|
||||||
|
],
|
||||||
|
exports: [RouterModule],
|
||||||
|
})
|
||||||
|
export class CoreSiteHomeIndexPageModule {}
|
|
@ -0,0 +1,155 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { IonRefresher } from '@ionic/angular';
|
||||||
|
|
||||||
|
import { CoreSite, CoreSiteConfig } from '@classes/site';
|
||||||
|
import { CoreCourse, CoreCourseSection } from '@features/course/services/course';
|
||||||
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
import { CoreSites } from '@services/sites';
|
||||||
|
import { CoreSiteHome } from '@features/sitehome/services/sitehome';
|
||||||
|
// import { CoreCourseHelperProvider } from '@features/course/services/helper';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page that displays site home index.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'page-core-sitehome-index',
|
||||||
|
templateUrl: 'index.html',
|
||||||
|
})
|
||||||
|
export class CoreSiteHomeIndexPage implements OnInit {
|
||||||
|
|
||||||
|
// @todo @Input() downloadEnabled: boolean;
|
||||||
|
// @todo @ViewChild(CoreBlockCourseBlocksComponent) courseBlocksComponent: CoreBlockCourseBlocksComponent;
|
||||||
|
|
||||||
|
dataLoaded = false;
|
||||||
|
section?: CoreCourseSection & {
|
||||||
|
hasContent?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
hasContent = false;
|
||||||
|
items: string[] = [];
|
||||||
|
siteHomeId?: number;
|
||||||
|
currentSite?: CoreSite;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected route: ActivatedRoute,
|
||||||
|
// @todo private prefetchDelegate: CoreCourseModulePrefetchDelegate,
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page being initialized.
|
||||||
|
*/
|
||||||
|
ngOnInit(): void {
|
||||||
|
const navParams = this.route.snapshot.queryParams;
|
||||||
|
|
||||||
|
this.currentSite = CoreSites.instance.getCurrentSite()!;
|
||||||
|
this.siteHomeId = this.currentSite.getSiteHomeId();
|
||||||
|
|
||||||
|
const module = navParams['module'];
|
||||||
|
if (module) {
|
||||||
|
// @todo const modParams = navParams.get('modParams');
|
||||||
|
// courseHelper.openModule(module, this.siteHomeId, undefined, modParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loadContent().finally(() => {
|
||||||
|
this.dataLoaded = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience function to fetch the data.
|
||||||
|
*
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected async loadContent(): Promise<void> {
|
||||||
|
this.hasContent = false;
|
||||||
|
|
||||||
|
const config = this.currentSite!.getStoredConfig() || { numsections: 1, frontpageloggedin: undefined };
|
||||||
|
|
||||||
|
this.items = await CoreSiteHome.instance.getFrontPageItems(config.frontpageloggedin);
|
||||||
|
this.hasContent = this.items.length > 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const sections = await CoreCourse.instance.getSections(this.siteHomeId!, false, true);
|
||||||
|
|
||||||
|
// Check "Include a topic section" setting from numsections.
|
||||||
|
this.section = config.numsections ? sections.find((section) => section.section == 1) : undefined;
|
||||||
|
if (this.section) {
|
||||||
|
this.section.hasContent = false;
|
||||||
|
/* @todo this.section.hasContent = this.courseHelper.sectionHasContent(this.section);
|
||||||
|
this.hasContent = this.courseHelper.addHandlerDataForModules(
|
||||||
|
[this.section],
|
||||||
|
this.siteHomeId,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
|
) || this.hasContent;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add log in Moodle.
|
||||||
|
CoreCourse.instance.logView(
|
||||||
|
this.siteHomeId!,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
this.currentSite!.getInfo()?.sitename,
|
||||||
|
).catch(() => {
|
||||||
|
// Ignore errors.
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
CoreDomUtils.instance.showErrorModalDefault(error, 'core.course.couldnotloadsectioncontent', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the data.
|
||||||
|
*
|
||||||
|
* @param refresher Refresher.
|
||||||
|
*/
|
||||||
|
doRefresh(refresher?: CustomEvent<IonRefresher>): void {
|
||||||
|
const promises: Promise<unknown>[] = [];
|
||||||
|
|
||||||
|
promises.push(CoreCourse.instance.invalidateSections(this.siteHomeId!));
|
||||||
|
promises.push(this.currentSite!.invalidateConfig().then(async () => {
|
||||||
|
// Config invalidated, fetch it again.
|
||||||
|
const config: CoreSiteConfig = await this.currentSite!.getConfig();
|
||||||
|
this.currentSite!.setConfig(config);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (this.section && this.section.modules) {
|
||||||
|
// Invalidate modules prefetch data.
|
||||||
|
// @todo promises.push(this.prefetchDelegate.invalidateModules(this.section.modules, this.siteHomeId));
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo promises.push(this.courseBlocksComponent.invalidateBlocks());
|
||||||
|
|
||||||
|
Promise.all(promises).finally(async () => {
|
||||||
|
const p2: Promise<unknown>[] = [];
|
||||||
|
|
||||||
|
p2.push(this.loadContent());
|
||||||
|
// @todo p2.push(this.courseBlocksComponent.loadContent());
|
||||||
|
|
||||||
|
await Promise.all(p2).finally(() => {
|
||||||
|
refresher?.detail.complete();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Params } from '@angular/router';
|
||||||
|
import { CoreSites } from '@services/sites';
|
||||||
|
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
||||||
|
import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks.helper';
|
||||||
|
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks.delegate';
|
||||||
|
import { CoreSiteHome } from '../sitehome';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler to treat links to site home index.
|
||||||
|
*/
|
||||||
|
Injectable();
|
||||||
|
export class CoreSiteHomeIndexLinkHandler extends CoreContentLinksHandlerBase {
|
||||||
|
|
||||||
|
name = 'CoreSiteHomeIndexLinkHandler';
|
||||||
|
featureName = 'CoreMainMenuDelegate_CoreSiteHome';
|
||||||
|
pattern = /\/course\/view\.php.*([?&]id=\d+)/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of actions for a link (url).
|
||||||
|
*
|
||||||
|
* @param siteIds List of sites the URL belongs to.
|
||||||
|
* @param url The URL to treat.
|
||||||
|
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||||
|
* @param courseId Course ID related to the URL. Optional but recommended.
|
||||||
|
* @return List of (or promise resolved with list of) actions.
|
||||||
|
*/
|
||||||
|
getActions(): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||||
|
return [{
|
||||||
|
action: (siteId: string): void => {
|
||||||
|
CoreContentLinksHelper.instance.goInSite('sitehome', [], siteId);
|
||||||
|
},
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the handler is enabled for a certain site (site + user) and a URL.
|
||||||
|
* If not defined, defaults to true.
|
||||||
|
*
|
||||||
|
* @param siteId The site ID.
|
||||||
|
* @param url The URL to treat.
|
||||||
|
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||||
|
* @param courseId Course ID related to the URL. Optional but recommended.
|
||||||
|
* @return Whether the handler is enabled for the URL and site.
|
||||||
|
*/
|
||||||
|
async isEnabled(siteId: string, url: string, params: Params, courseId?: number): Promise<boolean> {
|
||||||
|
courseId = parseInt(params.id, 10);
|
||||||
|
if (!courseId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const site = await CoreSites.instance.getSite(siteId);
|
||||||
|
if (courseId != site.getSiteHomeId()) {
|
||||||
|
// The course is not site home.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CoreSiteHome.instance.isAvailable(siteId).then(() => true).catch(() => false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { CoreSites } from '@services/sites';
|
||||||
|
import { CoreHomeHandler, CoreHomeHandlerToDisplay } from '@features/mainmenu/services/home.delegate';
|
||||||
|
import { CoreSiteHome } from '../sitehome';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler to add Home into main menu.
|
||||||
|
*/
|
||||||
|
Injectable();
|
||||||
|
export class CoreSiteHomeHomeHandler implements CoreHomeHandler {
|
||||||
|
|
||||||
|
name = 'CoreSiteHomeDashboard';
|
||||||
|
priority = 1200;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the handler is enabled on a site level.
|
||||||
|
*
|
||||||
|
* @return Whether or not the handler is enabled on a site level.
|
||||||
|
*/
|
||||||
|
isEnabled(): Promise<boolean> {
|
||||||
|
return this.isEnabledForSite();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the handler is enabled on a certain site.
|
||||||
|
*
|
||||||
|
* @param siteId Site ID. If not defined, current site.
|
||||||
|
* @return Whether or not the handler is enabled on a site level.
|
||||||
|
*/
|
||||||
|
async isEnabledForSite(siteId?: string): Promise<boolean> {
|
||||||
|
return CoreSiteHome.instance.isAvailable(siteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the data needed to render the handler.
|
||||||
|
*
|
||||||
|
* @return Data needed to render the handler.
|
||||||
|
*/
|
||||||
|
getDisplayData(): CoreHomeHandlerToDisplay {
|
||||||
|
const site = CoreSites.instance.getCurrentSite();
|
||||||
|
const displaySiteHome = site?.getInfo() && site?.getInfo()?.userhomepage === 0;
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: 'core.sitehome.sitehome',
|
||||||
|
page: 'sitehome',
|
||||||
|
class: 'core-sitehome-dashboard-handler',
|
||||||
|
icon: 'fas-home',
|
||||||
|
selectPriority: displaySiteHome ? 1100 : 900,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,196 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { CoreSites } from '@services/sites';
|
||||||
|
import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
|
||||||
|
import { makeSingleton } from '@singletons/core.singletons';
|
||||||
|
import { CoreCourse, CoreCourseSection } from '../../course/services/course';
|
||||||
|
import { CoreCourses } from '../../courses/services/courses';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Items with index 1 and 3 were removed on 2.5 and not being supported in the app.
|
||||||
|
*/
|
||||||
|
export enum FrontPageItemNames {
|
||||||
|
NEWS_ITEMS = 0,
|
||||||
|
LIST_OF_CATEGORIES = 2,
|
||||||
|
COMBO_LIST = 3,
|
||||||
|
ENROLLED_COURSES = 5,
|
||||||
|
LIST_OF_COURSE = 6,
|
||||||
|
COURSE_SEARCH_BOX = 7,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service that provides some features regarding site home.
|
||||||
|
*/
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class CoreSiteHomeProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the news forum for the Site Home.
|
||||||
|
*
|
||||||
|
* @param siteHomeId Site Home ID.
|
||||||
|
* @return Promise resolved with the forum if found, rejected otherwise.
|
||||||
|
*/
|
||||||
|
getNewsForum(): void {
|
||||||
|
// @todo params and logic.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate the WS call to get the news forum for the Site Home.
|
||||||
|
*
|
||||||
|
* @param siteHomeId Site Home ID.
|
||||||
|
* @return Promise resolved when invalidated.
|
||||||
|
*/
|
||||||
|
invalidateNewsForum(): void {
|
||||||
|
// @todo params and logic.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the frontpage is available for the current site.
|
||||||
|
*
|
||||||
|
* @param siteId The site ID. If not defined, current site.
|
||||||
|
* @return Promise resolved with boolean: whether it's available.
|
||||||
|
*/
|
||||||
|
async isAvailable(siteId?: string): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const site = await CoreSites.instance.getSite(siteId);
|
||||||
|
|
||||||
|
// First check if it's disabled.
|
||||||
|
if (this.isDisabledInSite(site)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use a WS call to check if there's content in the site home.
|
||||||
|
const siteHomeId = site.getSiteHomeId();
|
||||||
|
const preSets: CoreSiteWSPreSets = { emergencyCache: false };
|
||||||
|
|
||||||
|
try {
|
||||||
|
const sections: CoreCourseSection[] =
|
||||||
|
await CoreCourse.instance.getSections(siteHomeId, false, true, preSets, site.id);
|
||||||
|
|
||||||
|
if (!sections || !sections.length) {
|
||||||
|
throw Error('No sections found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasContent = sections.some((section) => section.summary || (section.modules && section.modules.length));
|
||||||
|
|
||||||
|
if (hasContent) {
|
||||||
|
// There's a section with content.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Ignore errors.
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = site.getStoredConfig();
|
||||||
|
if (config && config.frontpageloggedin) {
|
||||||
|
const items = await this.getFrontPageItems(config.frontpageloggedin);
|
||||||
|
|
||||||
|
// There are items to show.
|
||||||
|
return items.length > 0;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Ignore errors.
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if Site Home is disabled in a certain site.
|
||||||
|
*
|
||||||
|
* @param siteId Site Id. If not defined, use current site.
|
||||||
|
* @return Promise resolved with true if disabled, rejected or resolved with false otherwise.
|
||||||
|
*/
|
||||||
|
async isDisabled(siteId?: string): Promise<boolean> {
|
||||||
|
const site = await CoreSites.instance.getSite(siteId);
|
||||||
|
|
||||||
|
return this.isDisabledInSite(site);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if Site Home is disabled in a certain site.
|
||||||
|
*
|
||||||
|
* @param site Site. If not defined, use current site.
|
||||||
|
* @return Whether it's disabled.
|
||||||
|
*/
|
||||||
|
isDisabledInSite(site: CoreSite): boolean {
|
||||||
|
site = site || CoreSites.instance.getCurrentSite();
|
||||||
|
|
||||||
|
return site.isFeatureDisabled('CoreMainMenuDelegate_CoreSiteHome');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the nams of the valid frontpage items.
|
||||||
|
*
|
||||||
|
* @param frontpageItemIds CSV string with indexes of site home components.
|
||||||
|
* @return Valid names for each item.
|
||||||
|
*/
|
||||||
|
async getFrontPageItems(frontpageItemIds?: string): Promise<string[]> {
|
||||||
|
if (!frontpageItemIds) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = frontpageItemIds.split(',');
|
||||||
|
|
||||||
|
const filteredItems: string[] = [];
|
||||||
|
|
||||||
|
for (const item of items) {
|
||||||
|
let itemNumber = parseInt(item, 10);
|
||||||
|
|
||||||
|
let add = false;
|
||||||
|
switch (itemNumber) {
|
||||||
|
case FrontPageItemNames['NEWS_ITEMS']:
|
||||||
|
// @todo
|
||||||
|
add = true;
|
||||||
|
break;
|
||||||
|
case FrontPageItemNames['LIST_OF_CATEGORIES']:
|
||||||
|
case FrontPageItemNames['COMBO_LIST']:
|
||||||
|
case FrontPageItemNames['LIST_OF_COURSE']:
|
||||||
|
add = CoreCourses.instance.isGetCoursesByFieldAvailable();
|
||||||
|
if (add && itemNumber == FrontPageItemNames['COMBO_LIST']) {
|
||||||
|
itemNumber = FrontPageItemNames['LIST_OF_CATEGORIES'];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FrontPageItemNames['ENROLLED_COURSES']:
|
||||||
|
if (!CoreCourses.instance.isMyCoursesDisabledInSite()) {
|
||||||
|
const courses = await CoreCourses.instance.getUserCourses();
|
||||||
|
|
||||||
|
add = courses.length > 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FrontPageItemNames['COURSE_SEARCH_BOX']:
|
||||||
|
add = !CoreCourses.instance.isSearchCoursesDisabledInSite();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not add an item twice.
|
||||||
|
if (add && filteredItems.indexOf(FrontPageItemNames[itemNumber]) < 0) {
|
||||||
|
filteredItems.push(FrontPageItemNames[itemNumber]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CoreSiteHome extends makeSingleton(CoreSiteHomeProvider) {}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { Routes } from '@angular/router';
|
||||||
|
|
||||||
|
import { CoreSiteHomeIndexLinkHandler } from './services/handlers/index.link';
|
||||||
|
import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks.delegate';
|
||||||
|
import { CoreSiteHomeHomeHandler } from './services/handlers/sitehome.home';
|
||||||
|
import { CoreHomeDelegate } from '@features/mainmenu/services/home.delegate';
|
||||||
|
import { CoreHomeRoutingModule } from '@features/mainmenu/pages/home/home-routing.module';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: 'sitehome',
|
||||||
|
loadChildren: () =>
|
||||||
|
import('@features/sitehome/pages/index/index.page.module').then(m => m.CoreSiteHomeIndexPageModule),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [CoreHomeRoutingModule.forChild(routes)],
|
||||||
|
exports: [CoreHomeRoutingModule],
|
||||||
|
providers: [
|
||||||
|
CoreSiteHomeIndexLinkHandler,
|
||||||
|
CoreSiteHomeHomeHandler,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class CoreSiteHomeInitModule {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
contentLinksDelegate: CoreContentLinksDelegate,
|
||||||
|
homeDelegate: CoreHomeDelegate,
|
||||||
|
siteHomeIndexLinkHandler: CoreSiteHomeIndexLinkHandler,
|
||||||
|
siteHomeDashboardHandler: CoreSiteHomeHomeHandler,
|
||||||
|
) {
|
||||||
|
contentLinksDelegate.registerHandler(siteHomeIndexLinkHandler);
|
||||||
|
homeDelegate.registerHandler(siteHomeDashboardHandler);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue