MOBILE-3625 blocks: Activity modules block

main
Pau Ferrer Ocaña 2021-02-01 17:03:48 +01:00
parent 12db2a63f7
commit fd67797ff1
9 changed files with 295 additions and 2 deletions

View File

@ -0,0 +1,38 @@
// (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 { APP_INITIALIZER, NgModule } from '@angular/core';
import { IonicModule } from '@ionic/angular';
import { TranslateModule } from '@ngx-translate/core';
import { CoreBlockDelegate } from '@features/block/services/block-delegate';
import { AddonBlockActivityModulesHandler } from './services/block-handler';
import { AddonBlockActivityModulesComponentsModule } from './components/components.module';
@NgModule({
imports: [
IonicModule,
AddonBlockActivityModulesComponentsModule,
TranslateModule.forChild(),
],
providers: [
{
provide: APP_INITIALIZER,
multi: true,
useValue: () => {
CoreBlockDelegate.instance.registerHandler(AddonBlockActivityModulesHandler.instance);
},
},
],
})
export class AddonBlockActivityModulesModule {}

View File

@ -0,0 +1,149 @@
// (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 { CoreCourse } from '@features/course/services/course';
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
import { CoreBlockBaseComponent } from '@features/block/classes/base-block-component';
import { CoreSites } from '@services/sites';
import { ContextLevel, CoreConstants } from '@/core/constants';
import { Translate } from '@singletons';
import { CoreUtils } from '@services/utils/utils';
import { CoreNavigator } from '@services/navigator';
/**
* Component to render an "activity modules" block.
*/
@Component({
selector: 'addon-block-activitymodules',
templateUrl: 'addon-block-activitymodules.html',
})
export class AddonBlockActivityModulesComponent extends CoreBlockBaseComponent implements OnInit {
entries: AddonBlockActivityModuleEntry[] = [];
protected fetchContentDefaultError = 'Error getting activity modules data.';
constructor() {
super('AddonBlockActivityModulesComponent');
}
/**
* Perform the invalidate content function.
*
* @return Resolved when done.
*/
protected async invalidateContent(): Promise<void> {
await CoreCourse.instance.invalidateSections(this.instanceId);
}
/**
* Fetch the data to render the block.
*
* @return Promise resolved when done.
*/
protected async fetchContent(): Promise<void> {
const sections = await CoreCourse.instance.getSections(this.getCourseId(), false, true);
this.entries = [];
const archetypes: Record<string, number> = {};
const modIcons: Record<string, string> = {};
let modFullNames: Record<string, string> = {};
sections.forEach((section) => {
if (!section.modules) {
return;
}
section.modules.forEach((mod) => {
if (mod.uservisible === false || !CoreCourse.instance.moduleHasView(mod) ||
typeof modFullNames[mod.modname] != 'undefined') {
// Ignore this module.
return;
}
// Get the archetype of the module type.
if (typeof archetypes[mod.modname] == 'undefined') {
archetypes[mod.modname] = CoreCourseModuleDelegate.instance.supportsFeature<number>(
mod.modname,
CoreConstants.FEATURE_MOD_ARCHETYPE,
CoreConstants.MOD_ARCHETYPE_OTHER,
);
}
// Get the full name of the module type.
if (archetypes[mod.modname] == CoreConstants.MOD_ARCHETYPE_RESOURCE) {
// All resources are gathered in a single "Resources" option.
if (!modFullNames['resources']) {
modFullNames['resources'] = Translate.instance.instant('core.resources');
}
} else {
modFullNames[mod.modname] = mod.modplural;
}
modIcons[mod.modname] = mod.modicon;
});
});
// Sort the modnames alphabetically.
modFullNames = CoreUtils.instance.sortValues(modFullNames);
for (const modName in modFullNames) {
let icon: string;
if (modName === 'resources') {
icon = CoreCourse.instance.getModuleIconSrc('page', modIcons['page']);
} else {
icon = CoreCourseModuleDelegate.instance.getModuleIconSrc(modName, modIcons[modName]);
}
this.entries.push({
icon: icon,
name: modFullNames[modName],
modName,
});
}
}
/**
* Obtain the appropiate course id for the block.
*
* @return Course id.
*/
protected getCourseId(): number {
if (this.contextLevel == ContextLevel.COURSE) {
return this.instanceId;
}
return CoreSites.instance.getCurrentSiteHomeId();
}
/**
* Navigate to the activity list.
*
* @param entry Selected entry.
*/
gotoCoureListModType(entry: AddonBlockActivityModuleEntry): void {
CoreNavigator.instance.navigateToSitePath('course/list-mod-type', {
params: {
courseId: this.getCourseId(),
modName: entry.modName,
title: entry.name,
},
});
}
}
type AddonBlockActivityModuleEntry = {
icon: string;
name: string;
modName: string;
};

View File

@ -0,0 +1,11 @@
<ion-item-divider sticky="true">
<ion-label>
<h2>{{ 'addon.block_activitymodules.pluginname' | translate }}</h2>
</ion-label>
</ion-item-divider>
<core-loading [hideUntil]="loaded" class="core-loading-center">
<ion-item class="ion-text-wrap item-media" *ngFor="let entry of entries" detail="false" (click)="gotoCoureListModType(entry)">
<img slot="start" [src]="entry.icon" alt="" role="presentation" class="core-module-icon">
<ion-label>{{ entry.name }}</ion-label>
</ion-item>
</core-loading>

View File

@ -0,0 +1,43 @@
// (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 { IonicModule } from '@ionic/angular';
import { FormsModule } from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
import { CoreSharedModule } from '@/core/shared.module';
import { AddonBlockActivityModulesComponent } from './activitymodules/activitymodules';
@NgModule({
declarations: [
AddonBlockActivityModulesComponent,
],
imports: [
CommonModule,
IonicModule,
FormsModule,
TranslateModule.forChild(),
CoreSharedModule,
],
exports: [
AddonBlockActivityModulesComponent,
],
entryComponents: [
AddonBlockActivityModulesComponent,
],
})
export class AddonBlockActivityModulesComponentsModule {}

View File

@ -0,0 +1,3 @@
{
"pluginname": "Activities"
}

View File

@ -0,0 +1,46 @@
// (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 { CoreBlockHandlerData } from '@features/block/services/block-delegate';
import { AddonBlockActivityModulesComponent } from '../components/activitymodules/activitymodules';
import { CoreBlockBaseHandler } from '@features/block/classes/base-block-handler';
import { makeSingleton } from '@singletons';
/**
* Block handler.
*/
@Injectable({ providedIn: 'root' })
export class AddonBlockActivityModulesHandlerService extends CoreBlockBaseHandler {
name = 'AddonBlockActivityModules';
blockName = 'activity_modules';
/**
* Returns the data needed to render the block.
*
* @return Data or promise resolved with the data.
*/
getDisplayData(): CoreBlockHandlerData {
return {
title: 'addon.block_activitymodules.pluginname',
class: 'addon-block-activitymodules',
component: AddonBlockActivityModulesComponent,
};
}
}
export class AddonBlockActivityModulesHandler extends makeSingleton(AddonBlockActivityModulesHandlerService) {}

View File

@ -36,6 +36,7 @@ import { AddonBlockSelfCompletionModule } from './selfcompletion/selfcompletion.
import { AddonBlockSiteMainMenuModule } from './sitemainmenu/sitemainmenu.module';
import { AddonBlockStarredCoursesModule } from './starredcourses/starredcourses.module';
import { AddonBlockTagsModule } from './tags/tags.module';
import { AddonBlockActivityModulesModule } from './activitymodules/activitymodules.module';
@NgModule({
declarations: [],
@ -62,6 +63,7 @@ import { AddonBlockTagsModule } from './tags/tags.module';
AddonBlockSiteMainMenuModule,
AddonBlockStarredCoursesModule,
AddonBlockTagsModule,
AddonBlockActivityModulesModule,
],
providers: [],
exports: [],

View File

@ -20,6 +20,7 @@ import { CoreTextUtils } from '@services/utils/text';
import { CoreCourseBlock } from '../../course/services/course';
import { IonRefresher } from '@ionic/angular';
import { Params } from '@angular/router';
import { ContextLevel } from '@/core/constants';
/**
* Template class to easily create components for blocks.
@ -31,7 +32,7 @@ export abstract class CoreBlockBaseComponent implements OnInit {
@Input() title!: string; // The block title.
@Input() block!: CoreCourseBlock; // The block to render.
@Input() contextLevel!: string; // The context where the block will be used.
@Input() contextLevel!: ContextLevel; // The context where the block will be used.
@Input() instanceId!: number; // The instance ID associated with the context level.
@Input() link?: string; // Link to go when clicked.
@Input() linkParams?: Params; // Link params to go when clicked.

View File

@ -32,7 +32,7 @@ const routes: Routes = [
},
{
path: 'list-mod-type',
loadChildren: () => import('./pages/list-mod-type/list-mod-type').then( m => m.CoreCourseListModTypePage),
loadChildren: () => import('./pages/list-mod-type/list-mod-type.module').then(m => m.CoreCourseListModTypePageModule),
},
];