diff --git a/src/addons/mod/bigbluebuttonbn/services/handlers/module.ts b/src/addons/mod/bigbluebuttonbn/services/handlers/module.ts
index 2f543185a..ee71b6308 100644
--- a/src/addons/mod/bigbluebuttonbn/services/handlers/module.ts
+++ b/src/addons/mod/bigbluebuttonbn/services/handlers/module.ts
@@ -45,7 +45,7 @@ export class AddonModBBBModuleHandlerService extends CoreModuleHandlerBase imple
[CoreConstants.FEATURE_GRADE_OUTCOMES]: true,
[CoreConstants.FEATURE_BACKUP_MOODLE2]: true,
[CoreConstants.FEATURE_SHOW_DESCRIPTION]: true,
- [CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_OTHER,
+ [CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_COMMUNICATION,
};
/**
diff --git a/src/addons/mod/h5pactivity/services/handlers/module.ts b/src/addons/mod/h5pactivity/services/handlers/module.ts
index c6473702b..0148587d1 100644
--- a/src/addons/mod/h5pactivity/services/handlers/module.ts
+++ b/src/addons/mod/h5pactivity/services/handlers/module.ts
@@ -42,7 +42,7 @@ export class AddonModH5PActivityModuleHandlerService extends CoreModuleHandlerBa
[CoreConstants.FEATURE_GRADE_HAS_GRADE]: true,
[CoreConstants.FEATURE_GRADE_OUTCOMES]: true,
[CoreConstants.FEATURE_BACKUP_MOODLE2]: true,
- [CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_CONTENT,
+ [CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_INTERACTIVECONTENT,
};
/**
diff --git a/src/addons/mod/imscp/services/handlers/module.ts b/src/addons/mod/imscp/services/handlers/module.ts
index 369c111cc..0039e6a8f 100644
--- a/src/addons/mod/imscp/services/handlers/module.ts
+++ b/src/addons/mod/imscp/services/handlers/module.ts
@@ -42,7 +42,7 @@ export class AddonModImscpModuleHandlerService extends CoreModuleHandlerBase imp
[CoreConstants.FEATURE_GRADE_OUTCOMES]: false,
[CoreConstants.FEATURE_BACKUP_MOODLE2]: true,
[CoreConstants.FEATURE_SHOW_DESCRIPTION]: true,
- [CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_CONTENT,
+ [CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_INTERACTIVECONTENT,
};
/**
diff --git a/src/addons/mod/lesson/services/handlers/module.ts b/src/addons/mod/lesson/services/handlers/module.ts
index 897b65381..1bf2ec0f1 100644
--- a/src/addons/mod/lesson/services/handlers/module.ts
+++ b/src/addons/mod/lesson/services/handlers/module.ts
@@ -42,7 +42,7 @@ export class AddonModLessonModuleHandlerService extends CoreModuleHandlerBase im
[CoreConstants.FEATURE_GRADE_OUTCOMES]: true,
[CoreConstants.FEATURE_BACKUP_MOODLE2]: true,
[CoreConstants.FEATURE_SHOW_DESCRIPTION]: true,
- [CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_CONTENT,
+ [CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_INTERACTIVECONTENT,
};
/**
diff --git a/src/addons/mod/lti/services/handlers/module.ts b/src/addons/mod/lti/services/handlers/module.ts
index 70c8ce34a..f683c8190 100644
--- a/src/addons/mod/lti/services/handlers/module.ts
+++ b/src/addons/mod/lti/services/handlers/module.ts
@@ -44,7 +44,7 @@ export class AddonModLtiModuleHandlerService extends CoreModuleHandlerBase imple
[CoreConstants.FEATURE_GRADE_OUTCOMES]: true,
[CoreConstants.FEATURE_BACKUP_MOODLE2]: true,
[CoreConstants.FEATURE_SHOW_DESCRIPTION]: true,
- [CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_CONTENT,
+ [CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_OTHER,
};
/**
diff --git a/src/addons/mod/scorm/services/handlers/module.ts b/src/addons/mod/scorm/services/handlers/module.ts
index aacc38544..ab61d2220 100644
--- a/src/addons/mod/scorm/services/handlers/module.ts
+++ b/src/addons/mod/scorm/services/handlers/module.ts
@@ -41,7 +41,7 @@ export class AddonModScormModuleHandlerService extends CoreModuleHandlerBase imp
[CoreConstants.FEATURE_GRADE_OUTCOMES]: true,
[CoreConstants.FEATURE_BACKUP_MOODLE2]: true,
[CoreConstants.FEATURE_SHOW_DESCRIPTION]: true,
- [CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_CONTENT,
+ [CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_INTERACTIVECONTENT,
};
/**
diff --git a/src/core/classes/sites/authenticated-site.ts b/src/core/classes/sites/authenticated-site.ts
index d013a5a80..ed6f6b43d 100644
--- a/src/core/classes/sites/authenticated-site.ts
+++ b/src/core/classes/sites/authenticated-site.ts
@@ -1431,7 +1431,7 @@ export class CoreAuthenticatedSite extends CoreUnauthenticatedSite {
}
}
}
- } else if (typeof versions == 'string') {
+ } else if (typeof versions === 'string') {
// Compare with this version.
return siteVersion >= this.getVersionNumber(versions);
}
diff --git a/src/core/components/mod-icon/mod-icon.html b/src/core/components/mod-icon/mod-icon.html
index 46777347a..859b0e087 100644
--- a/src/core/components/mod-icon/mod-icon.html
+++ b/src/core/components/mod-icon/mod-icon.html
@@ -1,5 +1,7 @@
-
-
+
+
diff --git a/src/core/components/mod-icon/mod-icon.scss b/src/core/components/mod-icon/mod-icon.scss
index 37913a25e..5bf78a037 100644
--- a/src/core/components/mod-icon/mod-icon.scss
+++ b/src/core/components/mod-icon/mod-icon.scss
@@ -2,7 +2,7 @@
:host {
display: inline-block;
- --size: var(--module-icon-size, 24px);
+ --size: var(--module-icon-size, 32px);
--padding: var(--module-icon-padding, 8px);
--icon-radius: var(--module-icon-radius, var(--radius-xs));
--margin-end: 0px;
@@ -14,16 +14,43 @@
border-radius: var(--icon-radius);
padding: var(--padding);
- background-color: $gray-100;
+ background-color: transparent;
line-height: var(--size);
- @each $type, $value in $activity-icon-colors {
- &.#{$type} {
- background-color: var(--activity#{$type});
- img {
- filter: var(--filter, brightness(0) invert(1));
+ &.version_current {
+ @each $type, $value in $activity-icon-color-filters {
+ &.#{$type} {
+ --filter: var(--activity#{$type});
}
}
+
+ img {
+ filter: var(--filter, brightness(0) invert(1));
+ }
+ }
+
+ &.version_40 {
+ --size: var(--module-icon-size, 24px);
+ background-color: $gray-100;
+
+ @each $type, $value in $activity-icon-background-colors {
+ &.#{$type} {
+ background-color: var(--activity-40-#{$type});
+ img {
+ filter: var(--filter, brightness(0) invert(1));
+ }
+ }
+ }
+ }
+
+ &.version_legacy {
+ --size: var(--module-icon-size, 24px);
+ --filter: none;
+ background-color: $gray-100;
+ }
+
+ &.no-filter {
+ --filter: none !important;
}
}
@@ -41,11 +68,6 @@ img {
white-space: nowrap;
overflow: hidden;
}
-
- &.no-filter {
- --filter: none;
- }
-
}
:host-context(ion-item) {
diff --git a/src/core/components/mod-icon/mod-icon.ts b/src/core/components/mod-icon/mod-icon.ts
index db317f61b..0318d0d79 100644
--- a/src/core/components/mod-icon/mod-icon.ts
+++ b/src/core/components/mod-icon/mod-icon.ts
@@ -13,7 +13,7 @@
// limitations under the License.
import { CoreConstants, ModPurpose } from '@/core/constants';
-import { Component, ElementRef, Input, OnChanges, OnInit, SimpleChange } from '@angular/core';
+import { Component, ElementRef, HostBinding, Input, OnChanges, OnInit, SimpleChange } from '@angular/core';
import { CoreCourse } from '@features/course/services/course';
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
import { CoreSites } from '@services/sites';
@@ -23,6 +23,12 @@ import { CoreUrlUtils } from '@services/utils/url';
const assetsPath = 'assets/img/';
const fallbackModName = 'external-tool';
+const enum IconVersion {
+ LEGACY_VERSION = 'version_legacy',
+ VERSION_4_0 = 'version_40',
+ CURRENT_VERSION = 'version_current',
+}
+
/**
* Component to handle a module icon.
*/
@@ -33,6 +39,8 @@ const fallbackModName = 'external-tool';
})
export class CoreModIconComponent implements OnInit, OnChanges {
+ @HostBinding('class.no-filter') noFilter = false;
+
@Input() modname = ''; // The module name. Used also as component if set.
@Input() fallbackTranslation = ''; // Fallback translation string if cannot auto translate.
@Input() componentId?: number; // Component Id for external icons.
@@ -41,12 +49,12 @@ export class CoreModIconComponent implements OnInit, OnChanges {
@Input() purpose: ModPurpose = ModPurpose.MOD_PURPOSE_OTHER; // Purpose of the module.
icon = '';
- noFilter = false;
+
modNameTranslated = '';
isLocalUrl = true;
linkIconWithComponent = false;
- protected legacyIcon = true; // @deprecatedonmoodle since 3.11.
+ @HostBinding('class') iconVersion = 'legacy';
constructor(protected el: ElementRef) { }
@@ -54,22 +62,35 @@ export class CoreModIconComponent implements OnInit, OnChanges {
* @inheritdoc
*/
async ngOnInit(): Promise {
+ this.iconVersion = this.getIconVersion();
+
if (!this.modname && this.modicon) {
// Guess module from the icon url.
this.modname = this.getComponentNameFromIconUrl(this.modicon);
}
this.modNameTranslated = CoreCourse.translateModuleName(this.modname, this.fallbackTranslation);
- if (CoreSites.getCurrentSite()?.isVersionGreaterEqualThan('4.0')) {
- this.legacyIcon = false;
+ if (this.iconVersion !== IconVersion.LEGACY_VERSION) {
- const purposeClass =
+ let purposeClass =
CoreCourseModuleDelegate.supportsFeature(
this.modname || '',
CoreConstants.FEATURE_MOD_PURPOSE,
this.purpose,
);
+ if (this.iconVersion === IconVersion.VERSION_4_0) {
+ if (purposeClass === ModPurpose.MOD_PURPOSE_INTERACTIVECONTENT) {
+ // Interactive content was introduced on 4.4, on previous versions CONTENT is used instead.
+ purposeClass = ModPurpose.MOD_PURPOSE_CONTENT;
+ }
+
+ if (this.modname === 'lti') {
+ // LTI had content purpose with 4.0 icons.
+ purposeClass = ModPurpose.MOD_PURPOSE_CONTENT;
+ }
+ }
+
if (purposeClass) {
const element: HTMLElement = this.el.nativeElement;
element.classList.add(purposeClass);
@@ -129,13 +150,13 @@ export class CoreModIconComponent implements OnInit, OnChanges {
*/
protected async getIconNoFilter(): Promise {
// Earlier 4.0, icons were never filtered.
- if (this.legacyIcon) {
+ if (this.iconVersion === IconVersion.LEGACY_VERSION) {
return true;
}
// No icon or local icon (not legacy), filter it.
if (!this.icon || this.isLocalUrl) {
- return false;
+ return await CoreCourseModuleDelegate.moduleIconIsBranded(this.modname);
}
this.icon = CoreTextUtils.decodeHTMLEntities(this.icon);
@@ -192,4 +213,23 @@ export class CoreModIconComponent implements OnInit, OnChanges {
return component;
}
+ /**
+ * Get the icon version depending on site version.
+ *
+ * @returns Icon version.
+ */
+ protected getIconVersion(): IconVersion {
+ if (!CoreSites.getCurrentSite()?.isVersionGreaterEqualThan('4.0')) {
+ // @deprecatedonmoodle since 3.11.
+ return IconVersion.LEGACY_VERSION;
+ }
+
+ if (!CoreSites.getCurrentSite()?.isVersionGreaterEqualThan('4.4')) {
+ // @deprecatedonmoodle since 4.3.
+ return IconVersion.VERSION_4_0;
+ }
+
+ return IconVersion.CURRENT_VERSION;
+ }
+
}
diff --git a/src/core/constants.ts b/src/core/constants.ts
index e3a6ce330..25504259b 100644
--- a/src/core/constants.ts
+++ b/src/core/constants.ts
@@ -41,7 +41,8 @@ export const enum ModPurpose {
MOD_PURPOSE_COLLABORATION = 'collaboration',
MOD_PURPOSE_CONTENT = 'content',
MOD_PURPOSE_ADMINISTRATION = 'administration',
- MOD_PURPOSE_INTERFACE = 'interface',
+ MOD_PURPOSE_INTERFACE = 'interface', // @deprecatedonmoodle since 4.4.
+ MOD_PURPOSE_INTERACTIVECONTENT = 'interactivecontent',
MOD_PURPOSE_OTHER = 'other',
}
diff --git a/src/core/features/course/components/module-info/core-course-module-info.html b/src/core/features/course/components/module-info/core-course-module-info.html
index 244e2d406..b72768c72 100644
--- a/src/core/features/course/components/module-info/core-course-module-info.html
+++ b/src/core/features/course/components/module-info/core-course-module-info.html
@@ -1,5 +1,5 @@
-
+
+ [fallbackTranslation]="module.modplural" [purpose]="module.purpose" />
{{moduleNameTranslated}}
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 d4f3da3c6..cbcfd1daa 100644
--- a/src/core/features/course/components/module/core-course-module.html
+++ b/src/core/features/course/components/module/core-course-module.html
@@ -8,7 +8,7 @@
+ [componentId]="module.instance" [fallbackTranslation]="module.modplural" [purpose]="module.purpose" />
;
+
+ /**
+ * Whether the activity is branded.
+ * This information is used, for instance, to decide if a filter should be applied to the icon or not.
+ *
+ * @returns bool True if the activity is branded, false otherwise.
+ */
+ isBranded?(): Promise;
}
/**
diff --git a/src/theme/globals.variables.scss b/src/theme/globals.variables.scss
index ba409da53..ede99747b 100644
--- a/src/theme/globals.variables.scss
+++ b/src/theme/globals.variables.scss
@@ -115,8 +115,8 @@ $core-user-hide-siteinfo: $core-more-hide-siteinfo !default;
$core-user-hide-sitename: $core-more-hide-sitename !default;
$core-user-hide-siteurl: $core-more-hide-siteurl !default;
-// Activity icon background colors.
-$activity-icon-colors: (
+// Activity icon background colors. Only used on 4.0-4.3. @deprecatedonmoodle since 4.4.
+$activity-icon-background-colors: (
administration: #5d63f6,
assessment: #eb66a2,
collaboration: #f7634d,
@@ -125,6 +125,25 @@ $activity-icon-colors: (
interface: #a378ff
) !default;
+// Moodle 4.4 onwards.
+$activity-icon-colors: (
+ administration: #da58ef,
+ assessment: #f90086,
+ collaboration: #5b40ff,
+ communication: #eb6200,
+ content: #0099ad,
+ interactivecontent: #8d3d1b
+) !default;
+
+$activity-icon-color-filters: (
+ administration: invert(45%) sepia(46%) saturate(3819%) hue-rotate(260deg) brightness(101%) contrast(87%),
+ assessment: invert(36%) sepia(98%) saturate(6969%) hue-rotate(315deg) brightness(90%) contrast(119%),
+ collaboration: invert(25%) sepia(54%) saturate(6226%) hue-rotate(245deg) brightness(100%) contrast(102%),
+ communication: invert(48%) sepia(74%) saturate(4887%) hue-rotate(11deg) brightness(102%) contrast(101%),
+ content: invert(49%) sepia(52%) saturate(4675%) hue-rotate(156deg) brightness(89%) contrast(102%),
+ interactivecontent: invert(25%) sepia(63%) saturate(1152%) hue-rotate(344deg) brightness(94%) contrast(91%)
+) !default;
+
$calendar-event-category-category: #8e24aa !default;
$calendar-event-category-course: $red !default;
$calendar-event-category-group: $yellow !default;
diff --git a/src/theme/theme.light.scss b/src/theme/theme.light.scss
index 79cb58582..b87a21c3f 100644
--- a/src/theme/theme.light.scss
+++ b/src/theme/theme.light.scss
@@ -404,10 +404,15 @@ html {
}
// Make activtity colours available for custom modules.
- @each $type, $value in $activity-icon-colors {
+ @each $type, $value in $activity-icon-color-filters {
--activity#{$type}: #{$value};
}
+ // Make activtity colours available for custom modules.
+ @each $type, $value in $activity-icon-background-colors {
+ --activity-40-#{$type}: #{$value};
+ }
+
--core-mainpage-sitename-display: none;
--core-mainpage-headerlogo-display: none;
--core-mainpage-headerlogo-maxheight: calc(var(--core-header-toolbar-height) - 16px);