diff --git a/src/addons/block/activitymodules/components/activitymodules/addon-block-activitymodules.html b/src/addons/block/activitymodules/components/activitymodules/addon-block-activitymodules.html index 1f39261b4..2306e3b4b 100644 --- a/src/addons/block/activitymodules/components/activitymodules/addon-block-activitymodules.html +++ b/src/addons/block/activitymodules/components/activitymodules/addon-block-activitymodules.html @@ -6,7 +6,8 @@ - + + {{ entry.name }} diff --git a/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html b/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html index 4990142ad..73e52969f 100644 --- a/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html +++ b/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html @@ -17,7 +17,9 @@ - + + {{ item.iconTitle }} diff --git a/src/addons/block/timeline/components/events/addon-block-timeline-events.html b/src/addons/block/timeline/components/events/addon-block-timeline-events.html index 022dcc211..0622e2e0b 100644 --- a/src/addons/block/timeline/components/events/addon-block-timeline-events.html +++ b/src/addons/block/timeline/components/events/addon-block-timeline-events.html @@ -5,10 +5,10 @@ - + + - - {{ event.iconTitle }}

diff --git a/src/addons/block/timeline/components/events/events.ts b/src/addons/block/timeline/components/events/events.ts index bf77da586..b0db9c8a0 100644 --- a/src/addons/block/timeline/components/events/events.ts +++ b/src/addons/block/timeline/components/events/events.ts @@ -104,7 +104,8 @@ export class AddonBlockTimelineEventsComponent implements OnChanges { return start <= event.timesort; }).map(async (event) => { event.iconUrl = await CoreCourse.getModuleIconSrc(event.icon.component); - event.iconTitle = event.modulename && CoreCourse.translateModuleName(event.modulename); + event.modulename = event.modulename || event.icon.component; + event.iconTitle = CoreCourse.translateModuleName(event.modulename); return event; })); diff --git a/src/addons/calendar/calendar-common.scss b/src/addons/calendar/calendar-common.scss index 771f1987e..8fdaaeefe 100644 --- a/src/addons/calendar/calendar-common.scss +++ b/src/addons/calendar/calendar-common.scss @@ -9,6 +9,10 @@ padding: 6px; } + > core-mod-icon { + padding: 6px; + } + &.addon-calendar-eventtype-category > ion-icon { background-color: var(--addon-calendar-event-category-color); } @@ -25,4 +29,5 @@ background-color: var(--addon-calendar-event-site-color); } } -} + +} \ No newline at end of file diff --git a/src/addons/calendar/components/calendar/addon-calendar-calendar.html b/src/addons/calendar/components/calendar/addon-calendar-calendar.html index 93d477d00..570926c23 100644 --- a/src/addons/calendar/components/calendar/addon-calendar-calendar.html +++ b/src/addons/calendar/components/calendar/addon-calendar-calendar.html @@ -88,8 +88,9 @@ {{ event.timestart * 1000 | coreFormatDate: timeFormat }} - + + {{ 'addon.calendar.type' + event.formattedType | translate }} diff --git a/src/addons/calendar/components/calendar/calendar.scss b/src/addons/calendar/components/calendar/calendar.scss index 4d9303f3b..acbcccf6b 100644 --- a/src/addons/calendar/components/calendar/calendar.scss +++ b/src/addons/calendar/components/calendar/calendar.scss @@ -144,15 +144,15 @@ } } - .core-module-icon { + core-mod-icon { margin-right: 1px; margin-left: 1px; --size: 16px; display: inline-block; vertical-align: bottom; - } - .core-module-icon[slot="start"] { - padding: 6px; + ::ng-deep img { + display: block; + } } } diff --git a/src/addons/calendar/components/upcoming-events/addon-calendar-upcoming-events.html b/src/addons/calendar/components/upcoming-events/addon-calendar-upcoming-events.html index 315e8e624..30c9c2224 100644 --- a/src/addons/calendar/components/upcoming-events/addon-calendar-upcoming-events.html +++ b/src/addons/calendar/components/upcoming-events/addon-calendar-upcoming-events.html @@ -6,8 +6,8 @@ - + diff --git a/src/addons/calendar/pages/day/day.html b/src/addons/calendar/pages/day/day.html index 9f4b23431..c0e8bb1d7 100644 --- a/src/addons/calendar/pages/day/day.html +++ b/src/addons/calendar/pages/day/day.html @@ -61,8 +61,9 @@ - + + diff --git a/src/addons/calendar/pages/event/event.html b/src/addons/calendar/pages/event/event.html index 6244bc546..493b41712 100644 --- a/src/addons/calendar/pages/event/event.html +++ b/src/addons/calendar/pages/event/event.html @@ -4,7 +4,8 @@

- + diff --git a/src/addons/calendar/pages/event/event.scss b/src/addons/calendar/pages/event/event.scss index bc2bb8cb3..5403de162 100644 --- a/src/addons/calendar/pages/event/event.scss +++ b/src/addons/calendar/pages/event/event.scss @@ -2,8 +2,9 @@ ion-card ion-note { font-size: 1.6rem; } - h1 ion-icon, h1 img { + h1 ion-icon, h1 img, h1 core-mod-icon { margin-left: 10px; margin-right: 10px; + display: inline-block; } } diff --git a/src/addons/competency/pages/competency/competency.html b/src/addons/competency/pages/competency/competency.html index 0406897e2..cc34b86b0 100644 --- a/src/addons/competency/pages/competency/competency.html +++ b/src/addons/competency/pages/competency/competency.html @@ -77,8 +77,7 @@

- + diff --git a/src/addons/competency/pages/coursecompetencies/coursecompetencies.html b/src/addons/competency/pages/coursecompetencies/coursecompetencies.html index de2b0bb59..a0e2f63e3 100644 --- a/src/addons/competency/pages/coursecompetencies/coursecompetencies.html +++ b/src/addons/competency/pages/coursecompetencies/coursecompetencies.html @@ -114,8 +114,8 @@

- + + diff --git a/src/addons/mod/lti/services/handlers/module.ts b/src/addons/mod/lti/services/handlers/module.ts index 6213d8c9a..1692ec173 100644 --- a/src/addons/mod/lti/services/handlers/module.ts +++ b/src/addons/mod/lti/services/handlers/module.ts @@ -17,13 +17,8 @@ import { Injectable, Type } from '@angular/core'; import { CoreConstants } from '@/core/constants'; import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate'; import { CoreCourseModule } from '@features/course/services/course-helper'; -import { CoreApp } from '@services/app'; -import { CoreFilepool } from '@services/filepool'; -import { CoreSites } from '@services/sites'; -import { CoreUtils } from '@services/utils/utils'; -import { DomSanitizer, makeSingleton } from '@singletons'; +import { makeSingleton } from '@singletons'; import { AddonModLtiHelper } from '../lti-helper'; -import { AddonModLti, AddonModLtiProvider } from '../lti'; import { AddonModLtiIndexComponent } from '../../components/index'; import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler'; @@ -62,6 +57,9 @@ export class AddonModLtiModuleHandlerService extends CoreModuleHandlerBase imple const data = await super.getData(module, courseId, sectionId, forCoursePage); data.showDownloadButton = false; + // Handle custom icons. + data.icon = module.modicon; + data.buttons = [{ icon: 'fas-external-link-alt', label: 'addon.mod_lti.launchactivity', @@ -71,49 +69,9 @@ export class AddonModLtiModuleHandlerService extends CoreModuleHandlerBase imple }, }]; - // Handle custom icons. - CoreUtils.ignoreErrors(this.loadCustomIcon(module, courseId, data)); - return data; } - /** - * Load the custom icon. - * - * @param module Module. - * @param courseId Course ID. - * @param data Handler data. - * @return Promise resolved when done. - */ - protected async loadCustomIcon( - module: CoreCourseModule, - courseId: number, - handlerData: CoreCourseModuleHandlerData, - ): Promise { - const lti = await AddonModLti.getLti(courseId, module.id); - - const icon = lti.secureicon || lti.icon; - if (!icon) { - return; - } - - const siteId = CoreSites.getCurrentSiteId(); - - try { - await CoreFilepool.downloadUrl(siteId, icon, false, AddonModLtiProvider.COMPONENT, module.id); - - // Get the internal URL. - const url = await CoreFilepool.getSrcByUrl(siteId, icon, AddonModLtiProvider.COMPONENT, module.id); - - handlerData.icon = DomSanitizer.bypassSecurityTrustUrl(url); - } catch { - // Error downloading. If we're online we'll set the online url. - if (CoreApp.isOnline()) { - handlerData.icon = DomSanitizer.bypassSecurityTrustUrl(icon); - } - } - } - /** * @inheritdoc */ diff --git a/src/addons/mod/resource/services/handlers/module.ts b/src/addons/mod/resource/services/handlers/module.ts index 3c6030331..69a3d2ce8 100644 --- a/src/addons/mod/resource/services/handlers/module.ts +++ b/src/addons/mod/resource/services/handlers/module.ts @@ -15,7 +15,7 @@ import { CoreConstants } from '@/core/constants'; import { Injectable, Type } from '@angular/core'; import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler'; -import { CoreCourse, CoreCourseModuleContentFile } from '@features/course/services/course'; +import { CoreCourse } from '@features/course/services/course'; import { CoreCourseModule } from '@features/course/services/course-helper'; import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate'; import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate'; @@ -23,7 +23,6 @@ import { CoreFileHelper } from '@services/file-helper'; import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreTextUtils } from '@services/utils/text'; import { CoreTimeUtils } from '@services/utils/time'; -import { CoreWSFile } from '@services/ws'; import { makeSingleton, Translate } from '@singletons'; import { AddonModResourceIndexComponent } from '../../components/index'; import { AddonModResource, AddonModResourceCustomData } from '../resource'; @@ -94,7 +93,7 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase }]; this.getResourceData(module, courseId, handlerData).then((data) => { - handlerData.icon = handlerData.icon || data.icon; + handlerData.icon = data.icon; handlerData.extraBadge = data.extra; handlerData.extraBadgeColor = 'light'; @@ -136,7 +135,6 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase handlerData: CoreCourseModuleHandlerData, ): Promise { const promises: Promise[] = []; - let infoFiles: CoreWSFile[] = []; let options: AddonModResourceCustomData = {}; // Check if the button needs to be shown or not. @@ -150,12 +148,11 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase return; })); - if ('customdata' in module && typeof module.customdata != 'undefined') { + if ('customdata' in module && module.customdata !== undefined) { options = CoreTextUtils.unserialize(CoreTextUtils.parseJSON(module.customdata)); } else { // Get the resource data. promises.push(AddonModResource.getResourceData(courseId, module.id).then((info) => { - infoFiles = info.contentfiles; options = CoreTextUtils.unserialize(info.displayoptions); return; @@ -164,28 +161,22 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase await Promise.all(promises); - const files: (CoreCourseModuleContentFile | CoreWSFile)[] = module.contents && module.contents.length - ? module.contents - : infoFiles; - - const resourceData: AddonResourceHandlerData = { - icon: '', - extra: '', - }; + let mimetypeIcon = ''; const extra: string[] = []; if ('contentsinfo' in module && module.contentsinfo) { // No need to use the list of files. const mimetype = module.contentsinfo.mimetypes[0]; if (mimetype) { - resourceData.icon = CoreMimetypeUtils.getMimetypeIcon(mimetype); + mimetypeIcon = CoreMimetypeUtils.getMimetypeIcon(mimetype); } - resourceData.extra = CoreTextUtils.cleanTags(module.afterlink); + extra.push(CoreTextUtils.cleanTags(module.afterlink)); - } else if (files && files.length) { + } else if (module.contents && module.contents[0]) { + const files = module.contents; const file = files[0]; - resourceData.icon = CoreMimetypeUtils.getFileIcon(file.filename || ''); + mimetypeIcon = CoreMimetypeUtils.getFileIcon(file.filename || ''); if (options.showsize) { const size = options.filedetails @@ -227,16 +218,12 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase )); } } - - resourceData.extra += extra.join(' '); } - // No previously set, just set the icon. - if (resourceData.icon == '') { - resourceData.icon = await CoreCourse.getModuleIconSrc(module.modname, module.modicon); - } - - return resourceData; + return { + icon: await CoreCourse.getModuleIconSrc(module.modname, module.modicon, mimetypeIcon), + extra: extra.join(' '), + }; } /** diff --git a/src/addons/mod/url/services/handlers/module.ts b/src/addons/mod/url/services/handlers/module.ts index b1cdfaf9e..e6257f845 100644 --- a/src/addons/mod/url/services/handlers/module.ts +++ b/src/addons/mod/url/services/handlers/module.ts @@ -119,9 +119,10 @@ export class AddonModUrlModuleHandlerService extends CoreModuleHandlerBase imple handlerData.buttons[0].hidden = hideButton; if (module.contents && module.contents[0]) { + const icon = AddonModUrl.guessIcon(module.contents[0].fileurl); + // Calculate the icon to use. - handlerData.icon = await CoreCourse.getModuleIconSrc(module.modname, module.modicon) || - AddonModUrl.guessIcon(module.contents[0].fileurl); + handlerData.icon = await CoreCourse.getModuleIconSrc(module.modname, module.modicon, icon); } return; diff --git a/src/addons/storagemanager/pages/course-storage/course-storage.html b/src/addons/storagemanager/pages/course-storage/course-storage.html index 1220ca816..a2417b7ac 100644 --- a/src/addons/storagemanager/pages/course-storage/course-storage.html +++ b/src/addons/storagemanager/pages/course-storage/course-storage.html @@ -45,8 +45,9 @@ - + +

{{ module.name }} diff --git a/src/addons/storagemanager/pages/course-storage/course-storage.ts b/src/addons/storagemanager/pages/course-storage/course-storage.ts index 752059a7a..e52ddb0e0 100644 --- a/src/addons/storagemanager/pages/course-storage/course-storage.ts +++ b/src/addons/storagemanager/pages/course-storage/course-storage.ts @@ -63,7 +63,6 @@ export class AddonStorageManagerCourseStoragePage implements OnInit { section.modules.forEach((module) => { module.parentSection = section; module.totalSize = 0; - module.modNameTranslated = CoreCourse.translateModuleName(module.modname) || ''; // Note: This function only gets the size for modules which are downloadable. // For other modules it always returns 0, even if they have downloaded some files. @@ -235,5 +234,4 @@ type AddonStorageManagerCourseSection = Omit & { type AddonStorageManagerModule = CoreCourseModule & { parentSection?: AddonStorageManagerCourseSection; totalSize?: number; - modNameTranslated?: string; }; diff --git a/src/core/components/components.module.ts b/src/core/components/components.module.ts index ee3d02b2e..b055bad15 100644 --- a/src/core/components/components.module.ts +++ b/src/core/components/components.module.ts @@ -40,6 +40,7 @@ import { CoreInputErrorsComponent } from './input-errors/input-errors'; import { CoreLoadingComponent } from './loading/loading'; import { CoreLocalFileComponent } from './local-file/local-file'; import { CoreMarkRequiredComponent } from './mark-required/mark-required'; +import { CoreModIconComponent } from './mod-icon/mod-icon'; import { CoreNavBarButtonsComponent } from './navbar-buttons/navbar-buttons'; import { CoreNavigationBarComponent } from './navigation-bar/navigation-bar'; import { CoreProgressBarComponent } from './progress-bar/progress-bar'; @@ -81,6 +82,7 @@ import { CoreButtonWithSpinnerComponent } from './button-with-spinner/button-wit CoreLoadingComponent, CoreLocalFileComponent, CoreMarkRequiredComponent, + CoreModIconComponent, CoreNavBarButtonsComponent, CoreNavigationBarComponent, CoreProgressBarComponent, @@ -128,6 +130,7 @@ import { CoreButtonWithSpinnerComponent } from './button-with-spinner/button-wit CoreLoadingComponent, CoreLocalFileComponent, CoreMarkRequiredComponent, + CoreModIconComponent, CoreNavBarButtonsComponent, CoreNavigationBarComponent, CoreProgressBarComponent, diff --git a/src/core/components/mod-icon/mod-icon.html b/src/core/components/mod-icon/mod-icon.html new file mode 100644 index 000000000..4ce9eef5c --- /dev/null +++ b/src/core/components/mod-icon/mod-icon.html @@ -0,0 +1,19 @@ + + \ No newline at end of file diff --git a/src/core/components/mod-icon/mod-icon.scss b/src/core/components/mod-icon/mod-icon.scss new file mode 100644 index 000000000..e8cbb5754 --- /dev/null +++ b/src/core/components/mod-icon/mod-icon.scss @@ -0,0 +1,37 @@ +:host { + --size: var(--module-icon-size); + --margin-end: 0px; + --margin-vertical: 0px; + + margin-top: var(--margin-vertical); + margin-bottom: var(--margin-vertical); + margin-right: var(--margin-end); +} + +img { + width: var(--size); + height: var(--size); + max-width: var(--size); + max-height: var(--size); + + &[alt] { + text-indent: -999999px; + white-space: nowrap; + overflow: hidden; + } +} + +:host-context(ion-item) { + --margin-vertical: 12px; + --margin-end: 32px; +} + +:host-context(ion-card ion-item) { + --margin-vertical: 12px; + --margin-end: 12px; +} + +:host-context([dir=rtl]) { + margin-right: unset; + margin-left: var(--margin-end); +} \ No newline at end of file diff --git a/src/core/components/mod-icon/mod-icon.ts b/src/core/components/mod-icon/mod-icon.ts new file mode 100644 index 000000000..eba805215 --- /dev/null +++ b/src/core/components/mod-icon/mod-icon.ts @@ -0,0 +1,88 @@ +// (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, Input, OnChanges, OnInit, SimpleChange } from '@angular/core'; +import { CoreCourse } from '@features/course/services/course'; + +const assetsPath = 'assets/img/mod/'; +const fallbackModName = 'external-tool'; + +/** + * Component to handle a module icon. + */ +@Component({ + selector: 'core-mod-icon', + templateUrl: 'mod-icon.html', + styleUrls: ['mod-icon.scss'], +}) +export class CoreModIconComponent implements OnInit, OnChanges { + + @Input() modname?; // The module name. Used also as component if set. + @Input() componentId?; // Component Id for external icons. + @Input() modicon?: string; // Module icon url or local url. + @Input() showAlt = true; // Show alt otherwise it's only presentation icon. + + icon = ''; + modNameTranslated = ''; + isLocalUrl = true; + linkIconWithComponent = false; + + /** + * @inheritdoc + */ + async ngOnInit(): Promise { + this.modNameTranslated = this.modname ? CoreCourse.translateModuleName(this.modname) || '' : ''; + + this.setIcon(); + } + + /** + * @inheritdoc + */ + ngOnChanges(changes: { [name: string]: SimpleChange }): void { + if (changes && changes.modicon && changes.modicon.previousValue) { + this.setIcon(); + } + } + + /** + * Set icon. + */ + setIcon(): void { + this.icon = this.modicon || this.icon; + this.isLocalUrl = this.icon.startsWith(assetsPath); + + // Cache icon if the url is not the theme generic one. + // If modname is not set icon won't be cached. + // Also if the url matches the regexp (the theme will manage the image so it's not cached). + this.linkIconWithComponent = + this.modname && + this.componentId && + !this.isLocalUrl && + !this.icon.match('/theme/image.php/[^/]+/' + this.modname + '/[-0-9]*/'); + } + + /** + * Icon to load on error. + */ + loadFallbackIcon(): void { + this.isLocalUrl = true; + const moduleName = !this.modname || CoreCourse.CORE_MODULES.indexOf(this.modname) < 0 + ? fallbackModName + : this.modname; + + this.icon = assetsPath + moduleName + '.svg'; + } + +} diff --git a/src/core/components/user-avatar/user-avatar.scss b/src/core/components/user-avatar/user-avatar.scss index 6ae01b259..5d99ba41d 100644 --- a/src/core/components/user-avatar/user-avatar.scss +++ b/src/core/components/user-avatar/user-avatar.scss @@ -79,3 +79,8 @@ left: 0; right: unset; } + +:host-context(ion-item) { + margin-top: 12px; + margin-bottom: 12px; +} \ No newline at end of file diff --git a/src/core/directives/external-content.ts b/src/core/directives/external-content.ts index 4dd8f719f..4d84f6845 100644 --- a/src/core/directives/external-content.ts +++ b/src/core/directives/external-content.ts @@ -113,8 +113,7 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges { * Get the URL that should be handled and, if valid, handle it. */ protected async checkAndHandleExternalContent(): Promise { - const currentSite = CoreSites.getCurrentSite(); - const siteId = this.siteId || currentSite?.getId(); + const siteId = this.siteId || CoreSites.getRequiredCurrentSite().getId(); const tagName = this.element.tagName.toUpperCase(); let targetAttr; let url; diff --git a/src/core/features/course/components/module/core-course-module.html b/src/core/features/course/components/module/core-course-module.html index bbfebb68c..630c19e11 100644 --- a/src/core/features/course/components/module/core-course-module.html +++ b/src/core/features/course/components/module/core-course-module.html @@ -13,8 +13,9 @@ [button]="module.handlerData.action && module.uservisible" detail="false"> - + +

diff --git a/src/core/features/course/services/course.ts b/src/core/features/course/services/course.ts index 0e7f38649..81505df14 100644 --- a/src/core/features/course/services/course.ts +++ b/src/core/features/course/services/course.ts @@ -83,7 +83,7 @@ export class CoreCourseProvider { static readonly COMPONENT = 'CoreCourse'; - protected readonly CORE_MODULES = [ + readonly CORE_MODULES = [ 'assign', 'assignment', 'book', 'chat', 'choice', 'data', 'database', 'date', 'external-tool', 'feedback', 'file', 'folder', 'forum', 'glossary', 'ims', 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop', 'h5pactivity', @@ -402,15 +402,16 @@ export class CoreCourseProvider { ): Promise => { const params: CoreCourseGetContentsParams = { courseid: courseId!, - options: [], }; + params.options = []; + const preSets: CoreSiteWSPreSets = { omitExpires: preferCache, updateFrequency: CoreSite.FREQUENCY_RARELY, }; if (includeStealth) { - params.options!.push({ + params.options.push({ name: 'includestealthmodules', value: true, }); @@ -418,13 +419,13 @@ export class CoreCourseProvider { // If modName is set, retrieve all modules of that type. Otherwise get only the module. if (modName) { - params.options!.push({ + params.options.push({ name: 'modname', value: modName, }); preSets.cacheKey = this.getModuleByModNameCacheKey(modName); } else { - params.options!.push({ + params.options.push({ name: 'cmid', value: moduleId, }); @@ -630,7 +631,11 @@ export class CoreCourseProvider { * @param modicon The mod icon string to use in case we are not using a core activity. * @return The IMG src. */ - async getModuleIconSrc(moduleName: string, modicon?: string): Promise { + async getModuleIconSrc(moduleName: string, modicon?: string, mimetypeIcon = ''): Promise { + if (mimetypeIcon) { + return mimetypeIcon; + } + if (this.CORE_MODULES.indexOf(moduleName) < 0) { if (modicon) { return modicon; @@ -1489,7 +1494,7 @@ export type CoreCourseWSModule = { label: string; timestamp: number; }[]; // @since 3.11. Activity dates. - contentsinfo?: { // Contents summary information. + contentsinfo?: { // @since v3.7.6 Contents summary information. filescount: number; // Total number of files. filessize: number; // Total files size. lastmodified: number; // Last time files were modified. diff --git a/src/core/features/course/services/module-delegate.ts b/src/core/features/course/services/module-delegate.ts index 9ff01b011..f967c89a5 100644 --- a/src/core/features/course/services/module-delegate.ts +++ b/src/core/features/course/services/module-delegate.ts @@ -20,7 +20,7 @@ import { CoreSite } from '@classes/site'; import { CoreCourseModuleDefaultHandler } from './handlers/default-module'; import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate'; import { CoreCourseAnyCourseData } from '@features/courses/services/courses'; -import { CoreCourse, CoreCourseAnyModuleData, CoreCourseWSModule } from './course'; +import { CoreCourse, CoreCourseWSModule } from './course'; import { CoreSites } from '@services/sites'; import { makeSingleton } from '@singletons'; import { CoreCourseModule } from './course-helper'; diff --git a/src/core/features/grades/pages/course/course.html b/src/core/features/grades/pages/course/course.html index c4d8ee0fd..3883ca2d3 100644 --- a/src/core/features/grades/pages/course/course.html +++ b/src/core/features/grades/pages/course/course.html @@ -52,8 +52,11 @@ > - + + diff --git a/src/core/features/grades/pages/course/course.page.ts b/src/core/features/grades/pages/course/course.page.ts index ee13e8248..224d9369b 100644 --- a/src/core/features/grades/pages/course/course.page.ts +++ b/src/core/features/grades/pages/course/course.page.ts @@ -114,7 +114,7 @@ export class CoreGradesCoursePage implements AfterViewInit, OnDestroy { * Update the table of grades. */ private async fetchGrades(): Promise { - const table = await CoreGrades.getCourseGradesTable(this.grades.courseId!, this.grades.userId); + const table = await CoreGrades.getCourseGradesTable(this.grades.courseId, this.grades.userId); const formattedTable = await CoreGradesHelper.formatGradesTable(table); this.grades.setTable(formattedTable); @@ -192,7 +192,7 @@ class CoreGradesCourseManager extends CorePageItemsListManager { - await CoreGrades.logCourseGradesView(this.courseId!, this.userId!); + await CoreGrades.logCourseGradesView(this.courseId, this.userId); } /** diff --git a/src/core/features/grades/pages/course/course.scss b/src/core/features/grades/pages/course/course.scss index aca518a0f..2f0239c09 100644 --- a/src/core/features/grades/pages/course/course.scss +++ b/src/core/features/grades/pages/course/course.scss @@ -82,6 +82,11 @@ height: 16px; } + core-mod-icon { + --size: 16px; + } + + ion-icon { color: var(--icon-color); } @@ -119,6 +124,11 @@ background-color: var(--cell-hover); } } + + th, td { + height: var(--a11y-min-target-size); + vertical-align: middle; + } } } diff --git a/src/core/features/grades/pages/grade/grade.html b/src/core/features/grades/pages/grade/grade.html index 4b3198ee2..9abe2b1f3 100644 --- a/src/core/features/grades/pages/grade/grade.html +++ b/src/core/features/grades/pages/grade/grade.html @@ -17,8 +17,9 @@ - + + +

@@ -27,7 +28,9 @@ - + + +

diff --git a/src/core/features/tag/components/feed/core-tag-feed.html b/src/core/features/tag/components/feed/core-tag-feed.html index b0f626f67..1be13ee74 100644 --- a/src/core/features/tag/components/feed/core-tag-feed.html +++ b/src/core/features/tag/components/feed/core-tag-feed.html @@ -3,8 +3,8 @@ - + +

{{ item.heading }}

{{ text }}

diff --git a/src/theme/theme.base.scss b/src/theme/theme.base.scss index ef149d2ca..0253a989c 100644 --- a/src/theme/theme.base.scss +++ b/src/theme/theme.base.scss @@ -527,36 +527,10 @@ img[core-external-content]:not([src]) { visibility: hidden; } -// Activity modules -.core-module-icon { - --size: var(--module-icon-size); - width: var(--size); - height: var(--size); - max-width: var(--size); - max-height: var(--size); -} - -ion-item img.core-module-icon[slot="start"] { - margin-top: 12px; - margin-bottom: 12px; - margin-right: 32px; -} - -ion-card ion-item img.core-module-icon[slot="start"] { - margin-top: 12px; - margin-bottom: 12px; - margin-right: 12px; -} - ion-card ion-item:only-child { --inner-border-width: 0; } -[dir=rtl] ion-item img.core-module-icon[slot="start"] { - margin-right: unset; - margin-left: 32px; -} - .core-course-module-handler:not(.addon-mod-label-handler) .item-heading .filter_mathjaxloader_equation div { display: inline !important; }