forked from EVOgeek/Vmeda.Online
		
	
						commit
						56a3287aff
					
				| @ -0,0 +1,13 @@ | |||||||
|  | :host { | ||||||
|  |     --mod-icon-filter: brightness(0); | ||||||
|  | 
 | ||||||
|  |     core-mod-icon { | ||||||
|  |         background: transparent; | ||||||
|  |         margin: 0; | ||||||
|  |         --filter: var(--mod-icon-filter); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | :host-context(body.dark) { | ||||||
|  |     --mod-icon-filter: brightness(0) invert(1); | ||||||
|  | } | ||||||
| @ -28,6 +28,7 @@ import { CoreNavigator } from '@services/navigator'; | |||||||
| @Component({ | @Component({ | ||||||
|     selector: 'addon-block-activitymodules', |     selector: 'addon-block-activitymodules', | ||||||
|     templateUrl: 'addon-block-activitymodules.html', |     templateUrl: 'addon-block-activitymodules.html', | ||||||
|  |     styleUrls: ['activitymodules.scss'], | ||||||
| }) | }) | ||||||
| export class AddonBlockActivityModulesComponent extends CoreBlockBaseComponent implements OnInit { | export class AddonBlockActivityModulesComponent extends CoreBlockBaseComponent implements OnInit { | ||||||
| 
 | 
 | ||||||
| @ -96,16 +97,13 @@ export class AddonBlockActivityModulesComponent extends CoreBlockBaseComponent i | |||||||
|         // Sort the modnames alphabetically.
 |         // Sort the modnames alphabetically.
 | ||||||
|         modFullNames = CoreUtils.sortValues(modFullNames); |         modFullNames = CoreUtils.sortValues(modFullNames); | ||||||
|         for (const modName in modFullNames) { |         for (const modName in modFullNames) { | ||||||
|             let icon: string; |             const iconModName = modName === 'resources' ? 'page' : modName; | ||||||
| 
 | 
 | ||||||
|             if (modName === 'resources') { |             const icon = await CoreCourseModuleDelegate.getModuleIconSrc(iconModName, modIcons[iconModName]); | ||||||
|                 icon = await CoreCourse.getModuleIconSrc('page', modIcons['page']); |  | ||||||
|             } else { |  | ||||||
|                 icon = await CoreCourseModuleDelegate.getModuleIconSrc(modName, modIcons[modName]); |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             this.entries.push({ |             this.entries.push({ | ||||||
|                 icon: icon, |                 icon, | ||||||
|  |                 iconModName, | ||||||
|                 name: modFullNames[modName], |                 name: modFullNames[modName], | ||||||
|                 modName, |                 modName, | ||||||
|             }); |             }); | ||||||
| @ -145,4 +143,5 @@ type AddonBlockActivityModuleEntry = { | |||||||
|     icon: string; |     icon: string; | ||||||
|     name: string; |     name: string; | ||||||
|     modName: string; |     modName: string; | ||||||
|  |     iconModName: string; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ | |||||||
| </ion-item-divider> | </ion-item-divider> | ||||||
| <core-loading [hideUntil]="loaded" [fullscreen]="false"> | <core-loading [hideUntil]="loaded" [fullscreen]="false"> | ||||||
|     <ion-item class="ion-text-wrap" *ngFor="let entry of entries" detail="true" button (click)="gotoCoureListModType(entry)"> |     <ion-item class="ion-text-wrap" *ngFor="let entry of entries" detail="true" button (click)="gotoCoureListModType(entry)"> | ||||||
|         <core-mod-icon slot="start" [modicon]="entry.icon" [modname]="entry.modName" [showAlt]="false"> |         <core-mod-icon slot="start" [modicon]="entry.icon" [modname]="entry.iconModName" [showAlt]="false"> | ||||||
|         </core-mod-icon> |         </core-mod-icon> | ||||||
|         <ion-label>{{ entry.name }}</ion-label> |         <ion-label>{{ entry.name }}</ion-label> | ||||||
|     </ion-item> |     </ion-item> | ||||||
|  | |||||||
| @ -23,6 +23,7 @@ import { CoreConstants, ModPurpose } from '@/core/constants'; | |||||||
| import { AddonModForumIndexComponent } from '../../components/index'; | import { AddonModForumIndexComponent } from '../../components/index'; | ||||||
| import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler'; | import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler'; | ||||||
| import { CoreCourseModuleData } from '@features/course/services/course-helper'; | import { CoreCourseModuleData } from '@features/course/services/course-helper'; | ||||||
|  | import { CoreIonicColorNames } from '@singletons/colors'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Handler to support forum modules. |  * Handler to support forum modules. | ||||||
| @ -58,7 +59,7 @@ export class AddonModForumModuleHandlerService extends CoreModuleHandlerBase imp | |||||||
|         const data = await super.getData(module, courseId); |         const data = await super.getData(module, courseId); | ||||||
| 
 | 
 | ||||||
|         if ('afterlink' in module && !!module.afterlink) { |         if ('afterlink' in module && !!module.afterlink) { | ||||||
|             data.extraBadgeColor = ''; |             data.extraBadgeColor = undefined; | ||||||
|             const match = />(\d+)[^<]+/.exec(module.afterlink); |             const match = />(\d+)[^<]+/.exec(module.afterlink); | ||||||
|             data.extraBadge = match ? Translate.instant('addon.mod_forum.unreadpostsnumber', { $a : match[1] }) : ''; |             data.extraBadge = match ? Translate.instant('addon.mod_forum.unreadpostsnumber', { $a : match[1] }) : ''; | ||||||
|         } else { |         } else { | ||||||
| @ -112,7 +113,7 @@ export class AddonModForumModuleHandlerService extends CoreModuleHandlerBase imp | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         data.extraBadge = Translate.instant('core.loading'); |         data.extraBadge = Translate.instant('core.loading'); | ||||||
|         data.extraBadgeColor = 'light'; |         data.extraBadgeColor = CoreIonicColorNames.DARK; | ||||||
| 
 | 
 | ||||||
|         await CoreUtils.ignoreErrors(AddonModForum.invalidateForumData(courseId)); |         await CoreUtils.ignoreErrors(AddonModForum.invalidateForumData(courseId)); | ||||||
| 
 | 
 | ||||||
| @ -120,7 +121,7 @@ export class AddonModForumModuleHandlerService extends CoreModuleHandlerBase imp | |||||||
|             // Handle unread posts.
 |             // Handle unread posts.
 | ||||||
|             const forum = await AddonModForum.getForum(courseId, moduleId, { siteId }); |             const forum = await AddonModForum.getForum(courseId, moduleId, { siteId }); | ||||||
| 
 | 
 | ||||||
|             data.extraBadgeColor = ''; |             data.extraBadgeColor = undefined; | ||||||
|             data.extraBadge = forum.unreadpostscount |             data.extraBadge = forum.unreadpostscount | ||||||
|                 ? Translate.instant( |                 ? Translate.instant( | ||||||
|                     'addon.mod_forum.unreadpostsnumber', |                     'addon.mod_forum.unreadpostsnumber', | ||||||
| @ -129,7 +130,7 @@ export class AddonModForumModuleHandlerService extends CoreModuleHandlerBase imp | |||||||
|                 : ''; |                 : ''; | ||||||
|         } catch { |         } catch { | ||||||
|             // Ignore errors.
 |             // Ignore errors.
 | ||||||
|             data.extraBadgeColor = ''; |             data.extraBadgeColor = undefined; | ||||||
|             data.extraBadge = ''; |             data.extraBadge = ''; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -109,7 +109,7 @@ | |||||||
|                         <ion-item class="ion-text-wrap addon-mod_h5pactivity-result-table-header"> |                         <ion-item class="ion-text-wrap addon-mod_h5pactivity-result-table-header"> | ||||||
|                             <ion-label> |                             <ion-label> | ||||||
|                                 <ion-row class="ion-align-items-center"> |                                 <ion-row class="ion-align-items-center"> | ||||||
|                                     <ion-col class="ion-text-center">{{ result.optionslabel }}</ion-col> |                                     <ion-col class="ion-text-start">{{ result.optionslabel }}</ion-col> | ||||||
|                                     <ion-col class="ion-text-center">{{ result.correctlabel }}</ion-col> |                                     <ion-col class="ion-text-center">{{ result.correctlabel }}</ion-col> | ||||||
|                                     <ion-col class="ion-text-center">{{ result.answerlabel }}</ion-col> |                                     <ion-col class="ion-text-center">{{ result.answerlabel }}</ion-col> | ||||||
|                                 </ion-row> |                                 </ion-row> | ||||||
| @ -118,7 +118,7 @@ | |||||||
|                         <ion-item *ngFor="let option of result.options" class="ion-text-wrap addon-mod_h5pactivity-result-table-row"> |                         <ion-item *ngFor="let option of result.options" class="ion-text-wrap addon-mod_h5pactivity-result-table-row"> | ||||||
|                             <ion-label> |                             <ion-label> | ||||||
|                                 <ion-row class="ion-align-items-center"> |                                 <ion-row class="ion-align-items-center"> | ||||||
|                                     <ion-col class="ion-text-center"> |                                     <ion-col class="ion-text-start"> | ||||||
|                                         <core-format-text [text]="option.description" [component]="component" [componentId]="cmId" |                                         <core-format-text [text]="option.description" [component]="component" [componentId]="cmId" | ||||||
|                                             contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId"> |                                             contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId"> | ||||||
|                                         </core-format-text> |                                         </core-format-text> | ||||||
|  | |||||||
| @ -20,6 +20,7 @@ import { CoreCourseModuleData } from '@features/course/services/course-helper'; | |||||||
| import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate'; | import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate'; | ||||||
| import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate'; | import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate'; | ||||||
| import { CoreFileHelper } from '@services/file-helper'; | import { CoreFileHelper } from '@services/file-helper'; | ||||||
|  | import { CoreSites } from '@services/sites'; | ||||||
| import { CoreMimetypeUtils } from '@services/utils/mimetype'; | import { CoreMimetypeUtils } from '@services/utils/mimetype'; | ||||||
| import { CoreTextUtils } from '@services/utils/text'; | import { CoreTextUtils } from '@services/utils/text'; | ||||||
| import { CoreTimeUtils } from '@services/utils/time'; | import { CoreTimeUtils } from '@services/utils/time'; | ||||||
| @ -95,7 +96,14 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase | |||||||
| 
 | 
 | ||||||
|         this.getResourceData(module, courseId, handlerData).then((extra) => { |         this.getResourceData(module, courseId, handlerData).then((extra) => { | ||||||
|             handlerData.extraBadge = extra; |             handlerData.extraBadge = extra; | ||||||
|             handlerData.extraBadgeColor = ''; | 
 | ||||||
|  |             return; | ||||||
|  |         }).catch(() => { | ||||||
|  |             // Ignore errors.
 | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         this.getIconSrc(module).then((icon) => { | ||||||
|  |             handlerData.icon = icon; | ||||||
| 
 | 
 | ||||||
|             return; |             return; | ||||||
|         }).catch(() => { |         }).catch(() => { | ||||||
| @ -214,6 +222,36 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase | |||||||
|         return extra.join(' '); |         return extra.join(' '); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     async getIconSrc(module?: CoreCourseModuleData): Promise<string | undefined> { | ||||||
|  |         if (!module) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (CoreSites.getCurrentSite()?.isVersionGreaterEqualThan('4.0')) { | ||||||
|  |             return await CoreCourse.getModuleIconSrc(module.modname, module.modicon); | ||||||
|  |         } | ||||||
|  |         let mimetypeIcon = ''; | ||||||
|  | 
 | ||||||
|  |         if (module.contentsinfo) { | ||||||
|  |             // No need to use the list of files.
 | ||||||
|  |             const mimetype = module.contentsinfo.mimetypes[0]; | ||||||
|  |             if (mimetype) { | ||||||
|  |                 mimetypeIcon = CoreMimetypeUtils.getMimetypeIcon(mimetype); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |         } else if (module.contents && module.contents[0]) { | ||||||
|  |             const files = module.contents; | ||||||
|  |             const file = files[0]; | ||||||
|  | 
 | ||||||
|  |             mimetypeIcon = CoreMimetypeUtils.getFileIcon(file.filename || ''); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return await CoreCourse.getModuleIconSrc(module.modname, module.modicon, mimetypeIcon); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * @inheritdoc |      * @inheritdoc | ||||||
|      */ |      */ | ||||||
|  | |||||||
| @ -1,7 +1,6 @@ | |||||||
| @import "~theme/globals"; | @import "~theme/globals"; | ||||||
| 
 | 
 | ||||||
| :host { | :host { | ||||||
|     --core-format-text-background-gradient-rgb: var(--background-rgb, #{$ion-item-background-rgb}); |  | ||||||
|     --course-storage-max-activity-height: 120px; |     --course-storage-max-activity-height: 120px; | ||||||
| 
 | 
 | ||||||
|     ion-card.section ion-card-header { |     ion-card.section ion-card-header { | ||||||
| @ -23,8 +22,8 @@ | |||||||
|             min-height: var(--course-storage-max-activity-height); |             min-height: var(--course-storage-max-activity-height); | ||||||
|             position: absolute; |             position: absolute; | ||||||
|             @include position(0, 0, null, 0); |             @include position(0, 0, null, 0); | ||||||
|             background: -webkit-linear-gradient(top, rgba(var(--core-format-text-background-gradient-rgb), 0) calc(100% - 30px), rgba(var(--core-format-text-background-gradient-rgb), 1) calc(100% - 20px)); |             background: -webkit-linear-gradient(top, rgba(var(--background-gradient-rgb), 0) calc(100% - 30px), rgba(var(--background-gradient-rgb), 1) calc(100% - 20px)); | ||||||
|             background: linear-gradient(to bottom, rgba(var(--core-format-text-background-gradient-rgb), 0) calc(100% - 30px), rgba(var(--core-format-text-background-gradient-rgb), 1) calc(100% - 20px)); |             background: linear-gradient(to bottom, rgba(var(--background-gradient-rgb), 0) calc(100% - 30px), rgba(var(--background-gradient-rgb), 1) calc(100% - 20px)); | ||||||
|             z-index: 6; |             z-index: 6; | ||||||
|             pointer-events: none; |             pointer-events: none; | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -1,62 +0,0 @@ | |||||||
| // (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 { CoreCourseOptionsMenuHandler, CoreCourseOptionsMenuHandlerData } from '@features/course/services/course-options-delegate'; |  | ||||||
| import { CoreCourseAnyCourseDataWithOptions } from '@features/courses/services/courses'; |  | ||||||
| import { makeSingleton } from '@singletons'; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Handler to inject an option into course menu so that user can get to the manage storage page. |  | ||||||
|  */ |  | ||||||
| @Injectable( { providedIn: 'root' }) |  | ||||||
| export class AddonStorageManagerCourseMenuHandlerService implements CoreCourseOptionsMenuHandler { |  | ||||||
| 
 |  | ||||||
|     name = 'AddonStorageManager'; |  | ||||||
|     priority = 500; |  | ||||||
|     isMenuHandler = true; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * @inheritdoc |  | ||||||
|      */ |  | ||||||
|     async isEnabledForCourse(): Promise<boolean> { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * @inheritdoc |  | ||||||
|      */ |  | ||||||
|     async isEnabled(): Promise<boolean> { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * @inheritdoc |  | ||||||
|      */ |  | ||||||
|     getMenuDisplayData( |  | ||||||
|         course: CoreCourseAnyCourseDataWithOptions, |  | ||||||
|     ): CoreCourseOptionsMenuHandlerData { |  | ||||||
|         return { |  | ||||||
|             icon: 'fas-cloud-download-alt', |  | ||||||
|             title: 'addon.storagemanager.coursedownloads', |  | ||||||
|             page: 'storage/' + course.id, |  | ||||||
|             pageParams: { |  | ||||||
|                 title: course.displayname ?? course.fullname, |  | ||||||
|             }, |  | ||||||
|             class: 'addon-storagemanager-coursemenu-handler', |  | ||||||
|         }; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| export const AddonStorageManagerCourseMenuHandler = makeSingleton(AddonStorageManagerCourseMenuHandlerService); |  | ||||||
| @ -14,12 +14,10 @@ | |||||||
| 
 | 
 | ||||||
| import { NgModule, APP_INITIALIZER } from '@angular/core'; | import { NgModule, APP_INITIALIZER } from '@angular/core'; | ||||||
| import { Routes } from '@angular/router'; | import { Routes } from '@angular/router'; | ||||||
| import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate'; |  | ||||||
| import { CoreMainMenuRoutingModule } from '@features/mainmenu/mainmenu-routing.module'; | import { CoreMainMenuRoutingModule } from '@features/mainmenu/mainmenu-routing.module'; | ||||||
| import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; | import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; | ||||||
| import { CoreSitePreferencesRoutingModule } from '@features/settings/pages/site/site-routing'; | import { CoreSitePreferencesRoutingModule } from '@features/settings/pages/site/site-routing'; | ||||||
| import { CoreSettingsDelegate } from '@features/settings/services/settings-delegate'; | import { CoreSettingsDelegate } from '@features/settings/services/settings-delegate'; | ||||||
| import { AddonStorageManagerCourseMenuHandler } from './services/handlers/course-menu'; |  | ||||||
| import { AddonStorageManagerSettingsHandler } from './services/handlers/settings'; | import { AddonStorageManagerSettingsHandler } from './services/handlers/settings'; | ||||||
| 
 | 
 | ||||||
| const routes: Routes = [ | const routes: Routes = [ | ||||||
| @ -41,7 +39,6 @@ const routes: Routes = [ | |||||||
|             provide: APP_INITIALIZER, |             provide: APP_INITIALIZER, | ||||||
|             multi: true, |             multi: true, | ||||||
|             useValue: () => { |             useValue: () => { | ||||||
|                 CoreCourseOptionsDelegate.registerHandler(AddonStorageManagerCourseMenuHandler.instance); |  | ||||||
|                 CoreSettingsDelegate.registerHandler(AddonStorageManagerSettingsHandler.instance); |                 CoreSettingsDelegate.registerHandler(AddonStorageManagerSettingsHandler.instance); | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| <div [class.core-loading-container]="loading || !safeUrl" [ngStyle]="{'width': iframeWidth, 'height': iframeHeight}"> | <div [class.core-loading-container]="loading || !safeUrl" [ngStyle]="{'width': iframeWidth, 'height': iframeHeight}"> | ||||||
| 
 | 
 | ||||||
|     <core-navbar-buttons slot="end" append *ngIf="initialized && showFullscreenOnToolbar"> |     <core-navbar-buttons slot="end" prepend *ngIf="initialized && showFullscreenOnToolbar"> | ||||||
|         <ion-button fill="clear" (click)="toggleFullscreen()" |         <ion-button fill="clear" (click)="toggleFullscreen()" | ||||||
|             [attr.aria-label]="(fullscreen ? 'core.disablefullscreen' : 'core.fullscreen') | translate"> |             [attr.aria-label]="(fullscreen ? 'core.disablefullscreen' : 'core.fullscreen') | translate"> | ||||||
|             <ion-icon *ngIf="!fullscreen" name="fas-expand" slot="icon-only" aria-hidden="true"></ion-icon> |             <ion-icon *ngIf="!fullscreen" name="fas-expand" slot="icon-only" aria-hidden="true"></ion-icon> | ||||||
|  | |||||||
| @ -64,8 +64,8 @@ export class CoreCollapsibleItemDirective implements OnInit { | |||||||
|         } |         } | ||||||
|         this.maxHeight = this.maxHeight < defaultMaxHeight ? defaultMaxHeight : this.maxHeight; |         this.maxHeight = this.maxHeight < defaultMaxHeight ? defaultMaxHeight : this.maxHeight; | ||||||
| 
 | 
 | ||||||
|         if (!this.maxHeight || (window.innerWidth > 576 && window.innerHeight > 576)) { |         if (!this.maxHeight) { | ||||||
|             // Do not collapse on big screens.
 |             // Do not collapse.
 | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -91,9 +91,6 @@ export class CoreCollapsibleItemDirective implements OnInit { | |||||||
|      */ |      */ | ||||||
|     protected calculateHeight(): void { |     protected calculateHeight(): void { | ||||||
|         // @todo: Work on calculate this height better.
 |         // @todo: Work on calculate this height better.
 | ||||||
|         if (!this.maxHeight) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         // Remove max-height (if any) to calculate the real height.
 |         // Remove max-height (if any) to calculate the real height.
 | ||||||
|         const initialMaxHeight = this.element.style.maxHeight; |         const initialMaxHeight = this.element.style.maxHeight; | ||||||
| @ -118,6 +115,10 @@ export class CoreCollapsibleItemDirective implements OnInit { | |||||||
|         this.element.classList.toggle('collapsible-enabled', enable); |         this.element.classList.toggle('collapsible-enabled', enable); | ||||||
| 
 | 
 | ||||||
|         if (!enable || this.element.querySelector('ion-button.collapsible-toggle')) { |         if (!enable || this.element.querySelector('ion-button.collapsible-toggle')) { | ||||||
|  |             this.element.style.maxHeight = !enable || this.expanded | ||||||
|  |                 ? '' | ||||||
|  |                 : this.maxHeight + 'px'; | ||||||
|  | 
 | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -128,6 +129,7 @@ export class CoreCollapsibleItemDirective implements OnInit { | |||||||
| 
 | 
 | ||||||
|         const toggleText = document.createElement('span'); |         const toggleText = document.createElement('span'); | ||||||
|         toggleText.classList.add('collapsible-toggle-text'); |         toggleText.classList.add('collapsible-toggle-text'); | ||||||
|  |         toggleText.classList.add('sr-only'); | ||||||
|         toggleButton.appendChild(toggleText); |         toggleButton.appendChild(toggleText); | ||||||
| 
 | 
 | ||||||
|         const expandArrow = document.createElement('span'); |         const expandArrow = document.createElement('span'); | ||||||
|  | |||||||
| @ -279,23 +279,28 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|      */ |      */ | ||||||
|     protected setExpandButtonEnabled(enable: boolean): void { |     protected setExpandButtonEnabled(enable: boolean): void { | ||||||
|         this.toggleExpandEnabled = enable; |         this.toggleExpandEnabled = enable; | ||||||
|         this.element.classList.toggle('core-text-formatted', enable); |         this.element.classList.toggle('collapsible-enabled', enable); | ||||||
|  | 
 | ||||||
|  |         if (!enable || this.element.querySelector('ion-button.collapsible-toggle'))  { | ||||||
|  |             this.element.style.maxHeight = !enable || this.expanded | ||||||
|  |                 ? '' | ||||||
|  |                 : this.maxHeight + 'px'; | ||||||
| 
 | 
 | ||||||
|         if (!enable || this.element.querySelector('ion-button.core-format-text-toggle'))  { |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Add expand/collapse buttons
 |         // Add expand/collapse buttons
 | ||||||
|         const toggleButton = document.createElement('ion-button'); |         const toggleButton = document.createElement('ion-button'); | ||||||
|         toggleButton.classList.add('core-format-text-toggle'); |         toggleButton.classList.add('collapsible-toggle'); | ||||||
|         toggleButton.setAttribute('fill', 'clear'); |         toggleButton.setAttribute('fill', 'clear'); | ||||||
| 
 | 
 | ||||||
|         const toggleText = document.createElement('span'); |         const toggleText = document.createElement('span'); | ||||||
|         toggleText.classList.add('core-format-text-toggle-text'); |         toggleText.classList.add('collapsible-toggle-text'); | ||||||
|  |         toggleText.classList.add('sr-only'); | ||||||
|         toggleButton.appendChild(toggleText); |         toggleButton.appendChild(toggleText); | ||||||
| 
 | 
 | ||||||
|         const expandArrow = document.createElement('span'); |         const expandArrow = document.createElement('span'); | ||||||
|         expandArrow.classList.add('core-format-text-arrow'); |         expandArrow.classList.add('collapsible-toggle-arrow'); | ||||||
|         toggleButton.appendChild(expandArrow); |         toggleButton.appendChild(expandArrow); | ||||||
| 
 | 
 | ||||||
|         this.element.appendChild(toggleButton); |         this.element.appendChild(toggleButton); | ||||||
| @ -313,12 +318,12 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|             expand = !this.expanded; |             expand = !this.expanded; | ||||||
|         } |         } | ||||||
|         this.expanded = expand; |         this.expanded = expand; | ||||||
|         this.element.classList.toggle('core-text-format-expanded', expand); |         this.element.classList.toggle('collapsible-expanded', expand); | ||||||
|         this.element.classList.toggle('core-text-format-collapsed', !expand); |         this.element.classList.toggle('collapsible-collapsed', !expand); | ||||||
|         this.element.style.maxHeight = expand ? '' : this.maxHeight + 'px'; |         this.element.style.maxHeight = expand ? '' : this.maxHeight + 'px'; | ||||||
| 
 | 
 | ||||||
|         const toggleButton = this.element.querySelector('ion-button.core-format-text-toggle'); |         const toggleButton = this.element.querySelector('ion-button.collapsible-toggle'); | ||||||
|         const toggleText = toggleButton?.querySelector('.core-format-text-toggle-text'); |         const toggleText = toggleButton?.querySelector('.collapsible-toggle-text'); | ||||||
|         if (!toggleButton || !toggleText) { |         if (!toggleButton || !toggleText) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @ -396,8 +401,7 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|         this.element.classList.add('core-disable-media-adapt'); |         this.element.classList.add('core-disable-media-adapt'); | ||||||
| 
 | 
 | ||||||
|         this.contentSpan.innerHTML = ''; // Remove current contents.
 |         this.contentSpan.innerHTML = ''; // Remove current contents.
 | ||||||
|         if (this.maxHeight && result.div.innerHTML != '' && |         if (this.maxHeight && result.div.innerHTML != '') { | ||||||
|                 (window.innerWidth < 576 || window.innerHeight < 576)) { // Don't collapse in big screens.
 |  | ||||||
| 
 | 
 | ||||||
|             // Move the children to the current element to be able to calculate the height.
 |             // Move the children to the current element to be able to calculate the height.
 | ||||||
|             CoreDomUtils.moveChildren(result.div, this.contentSpan); |             CoreDomUtils.moveChildren(result.div, this.contentSpan); | ||||||
|  | |||||||
| @ -33,16 +33,35 @@ ion-item.item.item-current { | |||||||
|     --background: var(--primary); |     --background: var(--primary); | ||||||
|     --color: var(--primary-contrast); |     --color: var(--primary-contrast); | ||||||
|     border: 0; |     border: 0; | ||||||
| 
 |  | ||||||
|     ion-badge { |  | ||||||
|         border: 1px solid var(--primary-contrast); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     ::ng-deep ion-icon { |  | ||||||
|         color: var(--primary-contrast); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ion-icon.restricted { | ion-icon.restricted { | ||||||
|     font-size: 14px; |     font-size: 14px; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | ion-item.item.divider.section { | ||||||
|  |     --padding-start: 0px; | ||||||
|  | 
 | ||||||
|  |     &.item-current { | ||||||
|  |         ion-badge { | ||||||
|  |             border: 1px solid var(--primary-contrast); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         ion-icon.expandable-status-icon { | ||||||
|  |             color: var(--primary-contrast); | ||||||
|  | 
 | ||||||
|  |             &:hover { | ||||||
|  |                 background: var(--primary-shade); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ion-icon.expandable-status-icon { | ||||||
|  |         padding: 13px; | ||||||
|  |         margin: 3px; | ||||||
|  |         border-radius: 50%; | ||||||
|  |         &:hover { | ||||||
|  |             background: var(--gray-300); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | |||||||
| @ -5,21 +5,24 @@ | |||||||
| 
 | 
 | ||||||
|             <ng-container *ngIf="completion.istrackeduser"> |             <ng-container *ngIf="completion.istrackeduser"> | ||||||
|                 <ng-container *ngFor="let rule of details"> |                 <ng-container *ngFor="let rule of details"> | ||||||
|                     <ion-chip *ngIf="rule.statuscomplete" color="success" role="listitem" [attr.aria-label]="rule.accessibleDescription"> |                     <ion-chip *ngIf="rule.statuscomplete" color="success" role="listitem" [attr.aria-label]="rule.accessibleDescription" | ||||||
|  |                         class="completioninfo completion_complete"> | ||||||
|                         <ion-icon name="fas-check" [attr.aria-label]="'core.course.completion_automatic:done' | translate "></ion-icon> |                         <ion-icon name="fas-check" [attr.aria-label]="'core.course.completion_automatic:done' | translate "></ion-icon> | ||||||
|                         <ion-label> |                         <ion-label> | ||||||
|                             {{ rule.rulevalue.description }} |                             {{ rule.rulevalue.description }} | ||||||
|                         </ion-label> |                         </ion-label> | ||||||
|                     </ion-chip> |                     </ion-chip> | ||||||
| 
 | 
 | ||||||
|                     <ion-chip *ngIf="rule.statuscompletefail" color="danger" role="listitem" [attr.aria-label]="rule.accessibleDescription"> |                     <ion-chip *ngIf="rule.statuscompletefail" color="danger" role="listitem" [attr.aria-label]="rule.accessibleDescription" | ||||||
|  |                         class="completioninfo completion_fail"> | ||||||
|                         <ion-icon name="fas-times" [attr.aria-label]="'core.course.completion_automatic:failed' | translate "></ion-icon> |                         <ion-icon name="fas-times" [attr.aria-label]="'core.course.completion_automatic:failed' | translate "></ion-icon> | ||||||
|                         <ion-label> |                         <ion-label> | ||||||
|                             {{ rule.rulevalue.description }} |                             {{ rule.rulevalue.description }} | ||||||
|                         </ion-label> |                         </ion-label> | ||||||
|                     </ion-chip> |                     </ion-chip> | ||||||
| 
 | 
 | ||||||
|                     <ion-chip *ngIf="rule.statusincomplete" color="dark" role="listitem" [attr.aria-label]="rule.accessibleDescription"> |                     <ion-chip *ngIf="rule.statusincomplete" color="dark" role="listitem" [attr.aria-label]="rule.accessibleDescription" | ||||||
|  |                         class="completioninfo completion_incomplete"> | ||||||
|                         <ion-icon name="fas-edit" [attr.aria-label]="'core.course.completion_automatic:todo' | translate "></ion-icon> |                         <ion-icon name="fas-edit" [attr.aria-label]="'core.course.completion_automatic:todo' | translate "></ion-icon> | ||||||
|                         <ion-label> |                         <ion-label> | ||||||
|                             {{ rule.rulevalue.description }} |                             {{ rule.rulevalue.description }} | ||||||
| @ -29,7 +32,7 @@ | |||||||
|             </ng-container> |             </ng-container> | ||||||
| 
 | 
 | ||||||
|             <ng-container *ngIf="!completion.istrackeduser"> |             <ng-container *ngIf="!completion.istrackeduser"> | ||||||
|                 <ion-chip *ngFor="let rule of details" role="listitem"> |                 <ion-chip *ngFor="let rule of details" role="listitem" class="core-module-completion-todo"> | ||||||
|                     <ion-icon name="fas-edit" [attr.aria-label]="'core.course.completion_automatic:todo' | translate "></ion-icon> |                     <ion-icon name="fas-edit" [attr.aria-label]="'core.course.completion_automatic:todo' | translate "></ion-icon> | ||||||
|                     <ion-label> |                     <ion-label> | ||||||
|                         {{ rule.rulevalue.description }} |                         {{ rule.rulevalue.description }} | ||||||
|  | |||||||
| @ -1,12 +0,0 @@ | |||||||
| :host { |  | ||||||
|     .core-module-automatic-completion-conditions { |  | ||||||
|         ion-badge { |  | ||||||
|             font-weight: normal; |  | ||||||
|             margin-right: 5px; |  | ||||||
| 
 |  | ||||||
|             &[color="medium"] { |  | ||||||
|                 color: black; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -36,7 +36,6 @@ import { Translate } from '@singletons'; | |||||||
| @Component({ | @Component({ | ||||||
|     selector: 'core-course-module-completion', |     selector: 'core-course-module-completion', | ||||||
|     templateUrl: 'core-course-module-completion.html', |     templateUrl: 'core-course-module-completion.html', | ||||||
|     styleUrls: ['module-completion.scss'], |  | ||||||
| }) | }) | ||||||
| export class CoreCourseModuleCompletionComponent extends CoreCourseModuleCompletionBaseComponent { | export class CoreCourseModuleCompletionComponent extends CoreCourseModuleCompletionBaseComponent { | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -37,7 +37,7 @@ | |||||||
|                     {{ 'core.course' | translate}} |                     {{ 'core.course' | translate}} | ||||||
|                 </p> |                 </p> | ||||||
|                 <p> |                 <p> | ||||||
|                     <core-format-text [text]="course.displayname || course.fullname" contextLevel="course" [contextInstanceId]="courseId"> |                     <core-format-text [text]="course.fullname" contextLevel="course" [contextInstanceId]="courseId"> | ||||||
|                     </core-format-text> |                     </core-format-text> | ||||||
|                 </p> |                 </p> | ||||||
|             </ion-label> |             </ion-label> | ||||||
| @ -58,7 +58,7 @@ | |||||||
|             <ion-item lines="full" class="ion-text-wrap"> |             <ion-item lines="full" class="ion-text-wrap"> | ||||||
|                 <ion-label> |                 <ion-label> | ||||||
|                     <h2> |                     <h2> | ||||||
|                         <ion-icon name="fam-cloud-done" aria-hidden="true"></ion-icon> |                         <ion-icon name="fas-cloud-download-alt" aria-hidden="true"></ion-icon> | ||||||
|                         {{ 'addon.storagemanager.downloads' | translate }} |                         {{ 'addon.storagemanager.downloads' | translate }} | ||||||
|                     </h2> |                     </h2> | ||||||
|                 </ion-label> |                 </ion-label> | ||||||
| @ -81,7 +81,7 @@ | |||||||
|             </ion-item> |             </ion-item> | ||||||
|             <ion-button fill="outline" expand="block" *ngIf="canPrefetch && displayOptions.displayPrefetch" class="ion-text-wrap" |             <ion-button fill="outline" expand="block" *ngIf="canPrefetch && displayOptions.displayPrefetch" class="ion-text-wrap" | ||||||
|                 (click)="prefetch()" color="primary" [disabled]="prefetchDisabled"> |                 (click)="prefetch()" color="primary" [disabled]="prefetchDisabled"> | ||||||
|                 <ion-icon *ngIf="!prefetchLoading" name="fam-cloud-done" slot="start" aria-hidden="true"></ion-icon> |                 <ion-icon *ngIf="!prefetchLoading" name="fas-cloud-download-alt" slot="start" aria-hidden="true"></ion-icon> | ||||||
|                 <ion-spinner *ngIf="prefetchLoading" slot="start" aria-hidden="true"></ion-spinner> |                 <ion-spinner *ngIf="prefetchLoading" slot="start" aria-hidden="true"></ion-spinner> | ||||||
|                 <ion-label> |                 <ion-label> | ||||||
|                     {{ 'core.download' | translate }} |                     {{ 'core.download' | translate }} | ||||||
|  | |||||||
| @ -249,7 +249,13 @@ export class CoreCourseModuleSummaryComponent implements OnInit, OnDestroy { | |||||||
|      * Fetch course. |      * Fetch course. | ||||||
|      */ |      */ | ||||||
|     protected async fetchCourse(): Promise<void> { |     protected async fetchCourse(): Promise<void> { | ||||||
|  |         // Fix that.
 | ||||||
|  |         try { | ||||||
|             this.course = await CoreCourses.getUserCourse(this.courseId, true); |             this.course = await CoreCourses.getUserCourse(this.courseId, true); | ||||||
|  |         } catch { | ||||||
|  |             // The user is not enrolled in the course. Use getCourses to see if it's an admin/manager and can see the course.
 | ||||||
|  |             this.course = await CoreCourses.getCourse(this.courseId); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -71,7 +71,7 @@ | |||||||
|                 </core-format-text> |                 </core-format-text> | ||||||
| 
 | 
 | ||||||
|                 <!-- Module completion. Only auto conditions--> |                 <!-- Module completion. Only auto conditions--> | ||||||
|                 <core-course-module-completion *ngIf="module.completiondata && module.uservisible" [completion]="module.completiondata" |                 <core-course-module-completion *ngIf="autoCompletionTodo && module.uservisible" [completion]="module.completiondata" | ||||||
|                     [moduleName]="module.name" [moduleId]="module.id" [showCompletionConditions]="showCompletionConditions"> |                     [moduleName]="module.name" [moduleId]="module.id" [showCompletionConditions]="showCompletionConditions"> | ||||||
|                 </core-course-module-completion> |                 </core-course-module-completion> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,10 +2,14 @@ | |||||||
| 
 | 
 | ||||||
| :host { | :host { | ||||||
|     --horizontal-margin: 10px; |     --horizontal-margin: 10px; | ||||||
|  |     --vertical-margin: 10px; | ||||||
| 
 | 
 | ||||||
|     ion-card { |     ion-card { | ||||||
|         margin-left: var(--horizontal-margin); |         margin: var(--vertical-margin) var(--horizontal-margin); | ||||||
|         margin-right: var(--horizontal-margin); |     } | ||||||
|  | 
 | ||||||
|  |     ion-item { | ||||||
|  |         --padding-start: 12px; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ion-item.core-module-main-item { |     ion-item.core-module-main-item { | ||||||
| @ -84,4 +88,7 @@ | |||||||
|         @include margin-horizontal(null, 8px); |         @include margin-horizontal(null, 8px); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     .core-course-module-info ::ng-deep core-course-module-completion .core-module-automatic-completion-conditions .completioninfo.completion_complete { | ||||||
|  |         display: none; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -20,7 +20,7 @@ import { | |||||||
|     CoreCourseModuleCompletionData, |     CoreCourseModuleCompletionData, | ||||||
|     CoreCourseSection, |     CoreCourseSection, | ||||||
| } from '@features/course/services/course-helper'; | } from '@features/course/services/course-helper'; | ||||||
| import { CoreCourse } from '@features/course/services/course'; | import { CoreCourse, CoreCourseModuleCompletionStatus, CoreCourseModuleCompletionTracking } from '@features/course/services/course'; | ||||||
| import { CoreCourseModuleDelegate, CoreCourseModuleHandlerButton } from '@features/course/services/module-delegate'; | import { CoreCourseModuleDelegate, CoreCourseModuleHandlerButton } from '@features/course/services/module-delegate'; | ||||||
| import { | import { | ||||||
|     CoreCourseModulePrefetchDelegate, |     CoreCourseModulePrefetchDelegate, | ||||||
| @ -55,6 +55,8 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { | |||||||
|     showManualCompletion = false; // Whether to show manual completion when completion conditions are disabled.
 |     showManualCompletion = false; // Whether to show manual completion when completion conditions are disabled.
 | ||||||
|     prefetchStatusIcon = ''; // Module prefetch status icon.
 |     prefetchStatusIcon = ''; // Module prefetch status icon.
 | ||||||
|     prefetchStatusText = ''; // Module prefetch status text.
 |     prefetchStatusText = ''; // Module prefetch status text.
 | ||||||
|  |     autoCompletionTodo = false; | ||||||
|  | 
 | ||||||
|     protected prefetchHandler?: CoreCourseModulePrefetchHandler; |     protected prefetchHandler?: CoreCourseModulePrefetchHandler; | ||||||
| 
 | 
 | ||||||
|     protected moduleStatusObserver?: CoreEventObserver; |     protected moduleStatusObserver?: CoreEventObserver; | ||||||
| @ -73,10 +75,18 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { | |||||||
| 
 | 
 | ||||||
|         this.module.handlerData.a11yTitle = this.module.handlerData.a11yTitle ?? this.module.handlerData.title; |         this.module.handlerData.a11yTitle = this.module.handlerData.a11yTitle ?? this.module.handlerData.title; | ||||||
| 
 | 
 | ||||||
|  |         const completionStatus = this.showCompletionConditions && this.module.completiondata?.isautomatic && | ||||||
|  |             this.module.completiondata.tracking == CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC | ||||||
|  |             ? this.module.completiondata.state | ||||||
|  |             : undefined; | ||||||
|  | 
 | ||||||
|  |         this.autoCompletionTodo = completionStatus == CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE || | ||||||
|  |             completionStatus == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_FAIL; | ||||||
|  | 
 | ||||||
|         this.hasInfo = !!( |         this.hasInfo = !!( | ||||||
|             this.module.description || |             this.module.description || | ||||||
|             (this.showActivityDates && this.module.dates && this.module.dates.length) || |             (this.showActivityDates && this.module.dates && this.module.dates.length) || | ||||||
|             (this.module.completiondata && this.showCompletionConditions && this.module.completiondata.isautomatic) || |             (this.autoCompletionTodo) || | ||||||
|             (this.module.visible === 0 && (!this.section || this.section.visible)) || |             (this.module.visible === 0 && (!this.section || this.section.visible)) || | ||||||
|             (this.module.visible !== 0 && this.module.isStealth) || |             (this.module.visible !== 0 && this.module.isStealth) || | ||||||
|             (this.module.availabilityinfo) |             (this.module.availabilityinfo) | ||||||
|  | |||||||
| @ -1,4 +1,7 @@ | |||||||
| <core-navbar-buttons slot="end"> | <core-navbar-buttons slot="end" prepend> | ||||||
|  |     <ion-button fill="clear" (click)="gotoCourseDownloads()" [attr.aria-label]="'addon.storagemanager.coursedownloads' | translate"> | ||||||
|  |         <ion-icon name="fas-cloud-download-alt" slot="icon-only" aria-hidden="true"></ion-icon> | ||||||
|  |     </ion-button> | ||||||
| </core-navbar-buttons> | </core-navbar-buttons> | ||||||
| <ion-content> | <ion-content> | ||||||
|     <ion-refresher slot="fixed" [disabled]="!dataLoaded || !displayRefresher" (ionRefresh)="doRefresh($event.target)"> |     <ion-refresher slot="fixed" [disabled]="!dataLoaded || !displayRefresher" (ionRefresh)="doRefresh($event.target)"> | ||||||
|  | |||||||
| @ -29,7 +29,6 @@ import { | |||||||
| } from '@features/course/services/course-helper'; | } from '@features/course/services/course-helper'; | ||||||
| import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate'; | import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate'; | ||||||
| import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate'; | import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate'; | ||||||
| import { CoreCourseOptionsMenuHandlerToDisplay } from '@features/course/services/course-options-delegate'; |  | ||||||
| import { CoreCourseSync, CoreCourseSyncProvider } from '@features/course/services/sync'; | import { CoreCourseSync, CoreCourseSyncProvider } from '@features/course/services/sync'; | ||||||
| import { CoreCourseFormatComponent } from '../../components/course-format/course-format'; | import { CoreCourseFormatComponent } from '../../components/course-format/course-format'; | ||||||
| import { | import { | ||||||
| @ -54,7 +53,6 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy { | |||||||
|     sections?: CoreCourseSection[]; |     sections?: CoreCourseSection[]; | ||||||
|     sectionId?: number; |     sectionId?: number; | ||||||
|     sectionNumber?: number; |     sectionNumber?: number; | ||||||
|     courseMenuHandlers: CoreCourseOptionsMenuHandlerToDisplay[] = []; |  | ||||||
|     dataLoaded = false; |     dataLoaded = false; | ||||||
|     downloadCourseEnabled = false; |     downloadCourseEnabled = false; | ||||||
|     moduleId?: number; |     moduleId?: number; | ||||||
| @ -368,8 +366,16 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     gotoCourseDownloads(): void { | ||||||
|  |         CoreNavigator.navigateToSitePath( | ||||||
|  |             `storage/${this.course.id}`, | ||||||
|  |             { params: { title: this.course.fullname } }, | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * Page destroyed. |      * @inheritdoc | ||||||
|      */ |      */ | ||||||
|     ngOnDestroy(): void { |     ngOnDestroy(): void { | ||||||
|         this.isDestroyed = true; |         this.isDestroyed = true; | ||||||
|  | |||||||
| @ -26,14 +26,23 @@ | |||||||
|         <ng-container *ngIf="course"> |         <ng-container *ngIf="course"> | ||||||
|             <ion-item class="ion-text-wrap"> |             <ion-item class="ion-text-wrap"> | ||||||
|                 <ion-label> |                 <ion-label> | ||||||
|                     <p *ngIf="course.categoryname"> |                     <p *ngIf="course.displayname && course.shortname && course.fullname != course.displayname" | ||||||
|                         <core-format-text [text]="course.categoryname" contextLevel="coursecat" [contextInstanceId]="course.categoryid"> |                         class="core-course-shortname"> | ||||||
|  |                         <core-format-text [text]="course.shortname" contextLevel="course" [contextInstanceId]="course.id"> | ||||||
|                         </core-format-text> |                         </core-format-text> | ||||||
|                     </p> |                     </p> | ||||||
|                     <h2> |                     <h2> | ||||||
|  |                         <span class="sr-only">{{ 'core.courses.aria:coursename' | translate }}</span> | ||||||
|                         <core-format-text [text]="course.fullname" contextLevel="course" [contextInstanceId]="course.id"> |                         <core-format-text [text]="course.fullname" contextLevel="course" [contextInstanceId]="course.id"> | ||||||
|                         </core-format-text> |                         </core-format-text> | ||||||
|                     </h2> |                     </h2> | ||||||
|  |                     <ion-chip color="brand" *ngIf="course.categoryname" class="core-course-category ion-text-nowrap"> | ||||||
|  |                         <span class="sr-only">{{ 'core.courses.aria:coursecategory' | translate }}</span> | ||||||
|  |                         <ion-label> | ||||||
|  |                             <core-format-text [text]="course.categoryname" contextLevel="coursecat" [contextInstanceId]="course.categoryid"> | ||||||
|  |                             </core-format-text> | ||||||
|  |                         </ion-label> | ||||||
|  |                     </ion-chip> | ||||||
| 
 | 
 | ||||||
|                     <div class="core-course-progress" *ngIf="progress !== undefined"> |                     <div class="core-course-progress" *ngIf="progress !== undefined"> | ||||||
|                         <core-progress-bar [progress]="progress" a11yText="core.course.aria:sectionprogress"> |                         <core-progress-bar [progress]="progress" a11yText="core.course.aria:sectionprogress"> | ||||||
|  | |||||||
| @ -21,10 +21,6 @@ | |||||||
|         <img [src]="imageThumb" core-external-content alt="" /> |         <img [src]="imageThumb" core-external-content alt="" /> | ||||||
|     </ion-avatar> |     </ion-avatar> | ||||||
|     <ion-label> |     <ion-label> | ||||||
|         <p *ngIf="category"> |  | ||||||
|             <core-format-text [text]="category" contextLevel="coursecat" [contextInstanceId]="course!.categoryid"> |  | ||||||
|             </core-format-text> |  | ||||||
|         </p> |  | ||||||
|         <h1>{{ title }}</h1> |         <h1>{{ title }}</h1> | ||||||
|         <div class="core-course-progress" *ngIf="progress !== undefined"> |         <div class="core-course-progress" *ngIf="progress !== undefined"> | ||||||
|             <core-progress-bar [progress]="progress" a11yText="core.course.aria:sectionprogress"> |             <core-progress-bar [progress]="progress" a11yText="core.course.aria:sectionprogress"> | ||||||
|  | |||||||
| @ -238,7 +238,6 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy { | |||||||
| 
 | 
 | ||||||
|         // Get the title to display initially.
 |         // Get the title to display initially.
 | ||||||
|         this.title = CoreCourseFormatDelegate.getCourseTitle(this.course); |         this.title = CoreCourseFormatDelegate.getCourseTitle(this.course); | ||||||
|         this.category = 'categoryname' in this.course ? this.course.categoryname : ''; |  | ||||||
| 
 | 
 | ||||||
|         if ('overviewfiles' in this.course) { |         if ('overviewfiles' in this.course) { | ||||||
|             this.imageThumb = this.course.overviewfiles?.[0]?.fileurl; |             this.imageThumb = this.course.overviewfiles?.[0]?.fileurl; | ||||||
|  | |||||||
| @ -25,6 +25,7 @@ import { CoreSites } from '@services/sites'; | |||||||
| import { makeSingleton } from '@singletons'; | import { makeSingleton } from '@singletons'; | ||||||
| import { CoreCourseModuleData } from './course-helper'; | import { CoreCourseModuleData } from './course-helper'; | ||||||
| import { CoreNavigationOptions } from '@services/navigator'; | import { CoreNavigationOptions } from '@services/navigator'; | ||||||
|  | import { CoreIonicColorNames } from '@singletons/colors'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Interface that all course module handlers must implement. |  * Interface that all course module handlers must implement. | ||||||
| @ -146,7 +147,7 @@ export interface CoreCourseModuleHandlerData { | |||||||
|     /** |     /** | ||||||
|      * The color of the extra badge. Default: primary. |      * The color of the extra badge. Default: primary. | ||||||
|      */ |      */ | ||||||
|     extraBadgeColor?: string; |     extraBadgeColor?: CoreIonicColorNames; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Whether to display a button to download/refresh the module if it's downloadable. |      * Whether to display a button to download/refresh the module if it's downloadable. | ||||||
|  | |||||||
| @ -70,7 +70,8 @@ | |||||||
|                     class="core-course-category core-course-additional-info ion-text-nowrap"> |                     class="core-course-category core-course-additional-info ion-text-nowrap"> | ||||||
|                     <span class="sr-only">{{ 'core.courses.aria:coursecategory' | translate }}</span> |                     <span class="sr-only">{{ 'core.courses.aria:coursecategory' | translate }}</span> | ||||||
|                     <ion-label> |                     <ion-label> | ||||||
|                         <core-format-text [text]="course.categoryname"></core-format-text> |                         <core-format-text [text]="course.categoryname" contextLevel="coursecat" [contextInstanceId]="course.categoryid"> | ||||||
|  |                         </core-format-text> | ||||||
|                     </ion-label> |                     </ion-label> | ||||||
|                 </ion-chip> |                 </ion-chip> | ||||||
|             </div> |             </div> | ||||||
|  | |||||||
| @ -34,6 +34,10 @@ | |||||||
|         margin-bottom: 16px; |         margin-bottom: 16px; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     form .core-username.ios { | ||||||
|  |         --inner-border-width: 0 0 1px 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     form .item, |     form .item, | ||||||
|     form .item ion-label { |     form .item ion-label { | ||||||
|         --background: var(--core-login-input-background); |         --background: var(--core-login-input-background); | ||||||
|  | |||||||
| @ -15,7 +15,7 @@ | |||||||
|     <core-loading [hideUntil]="userLoaded"> |     <core-loading [hideUntil]="userLoaded"> | ||||||
|         <ion-list *ngIf="user"> |         <ion-list *ngIf="user"> | ||||||
|             <ion-item class="ion-text-center core-user-profile-maininfo ion-text-wrap" lines="full"> |             <ion-item class="ion-text-center core-user-profile-maininfo ion-text-wrap" lines="full"> | ||||||
|                 <core-user-avatar [user]="user" [userId]="user.id" [linkProfile]="false" [checkOnline]="true"> |                 <core-user-avatar [user]="user" [userId]="user.id" [linkProfile]="false" [checkOnline]="!canChangeProfilePicture"> | ||||||
|                     <ion-button class="edit-avatar" *ngIf="canChangeProfilePicture" (click)="changeProfilePicture()" |                     <ion-button class="edit-avatar" *ngIf="canChangeProfilePicture" (click)="changeProfilePicture()" | ||||||
|                         [attr.aria-label]="'core.user.newpicture' | translate" fill="clear" color="dark"> |                         [attr.aria-label]="'core.user.newpicture' | translate" fill="clear" color="dark"> | ||||||
|                         <ion-icon slot="icon-only" name="fas-pen" aria-hidden="true"></ion-icon> |                         <ion-icon slot="icon-only" name="fas-pen" aria-hidden="true"></ion-icon> | ||||||
|  | |||||||
| @ -4,13 +4,11 @@ | |||||||
| 
 | 
 | ||||||
| core-format-text { | core-format-text { | ||||||
|     --core-format-text-background: var(--background, var(--ion-item-background)); |     --core-format-text-background: var(--background, var(--ion-item-background)); | ||||||
|     --core-format-text-background-gradient-rgb: var(--background-rgb, #{$ion-item-background-rgb}); |  | ||||||
|     --core-format-text-viewer-icon-background: rgba(255, 255, 255, .5); |     --core-format-text-viewer-icon-background: rgba(255, 255, 255, .5); | ||||||
|     --core-format-text-loader-shine: 251,251,251; |     --core-format-text-loader-shine: 251,251,251; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| body.dark core-format-text { | body.dark core-format-text { | ||||||
|     --core-format-text-background-gradient-rgb: var(--background-rgb, #{$ion-item-background-dark-rgb}); |  | ||||||
|     --core-format-text-viewer-icon-background: rgba(0, 0, 0, .5); |     --core-format-text-viewer-icon-background: rgba(0, 0, 0, .5); | ||||||
|     --core-format-text-loader-shine: 90,90,90; |     --core-format-text-loader-shine: 90,90,90; | ||||||
| } | } | ||||||
| @ -51,12 +49,12 @@ core-format-text { | |||||||
|             display: inline; |             display: inline; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         .core-format-text-toggle { |         .collapsible-toggle { | ||||||
|             display: none !important; |             display: none !important; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     .core-format-text-toggle { |     .collapsible-toggle { | ||||||
|         display: none; |         display: none; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -84,81 +82,21 @@ core-format-text { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // This is to allow clicks in radio/checkbox content. |         // This is to allow clicks in radio/checkbox content. | ||||||
|         &.core-text-formatted { |         &.collapsible-enabled { | ||||||
|             cursor: pointer; |             cursor: pointer; | ||||||
|             pointer-events: auto; |             pointer-events: auto; | ||||||
| 
 | 
 | ||||||
|             .core-format-text-toggle { |             @include collapsible-item(); | ||||||
|                 display: block; |  | ||||||
|                 position: absolute; |  | ||||||
|                 bottom: 0; |  | ||||||
|                 left: 0; |  | ||||||
|                 right: 0; |  | ||||||
|                 text-align: center; |  | ||||||
|                 z-index: 7; |  | ||||||
|                 text-transform: none; |  | ||||||
|                 text-align: end; |  | ||||||
|                 font-size: 14px; |  | ||||||
|                 background-color: var(--core-format-text-background); |  | ||||||
|                 color: var(--text-color); |  | ||||||
|                 margin: 0; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|                 .core-format-text-arrow { |  | ||||||
|                     width: var(--a11y-min-target-size); |  | ||||||
|                     height: var(--a11y-min-target-size); |  | ||||||
| 
 |  | ||||||
|                     background-position: center; |  | ||||||
|                     background-repeat: no-repeat; |  | ||||||
|                     background-size: 14px 14px; |  | ||||||
|                     @include core-transition(transform, 500ms); |  | ||||||
| 
 |  | ||||||
|                     @include push-arrow-color(626262, true); |  | ||||||
| 
 |  | ||||||
|                     @include darkmode() { |  | ||||||
|                         @include push-arrow-color(ffffff, true); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             &.core-text-format-collapsed { |  | ||||||
|                 overflow: hidden; |  | ||||||
|                 min-height: 50px; |  | ||||||
| 
 |  | ||||||
|                 .core-format-text-arrow { |  | ||||||
|                     transform: rotate(90deg); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 &:before { |  | ||||||
|                     content: ''; |  | ||||||
|                     height: 100%; |  | ||||||
|                     position: absolute; |  | ||||||
|                     @include position(null, 0, 0, 0); |  | ||||||
|                     background: -webkit-linear-gradient(top, rgba(var(--core-format-text-background-gradient-rgb), 0) calc(100% - 60px), rgba(var(--core-format-text-background-gradient-rgb), 1) calc(100% - 40px)); |  | ||||||
|                     background: linear-gradient(to bottom, rgba(var(--core-format-text-background-gradient-rgb), 0) calc(100% - 60px), rgba(var(--core-format-text-background-gradient-rgb), 1) calc(100% - 40px)); |  | ||||||
|                     z-index: 6; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             &.core-text-format-expanded { |  | ||||||
|                 max-height: none !important; |  | ||||||
| 
 |  | ||||||
|                 padding-bottom: 50px; // So the Show less button can fit. |  | ||||||
| 
 |  | ||||||
|                 .core-format-text-arrow { |  | ||||||
|                     transform: rotate(-90deg); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @if ($core-format-text-never-shorten) { |     @if ($core-format-text-never-shorten) { | ||||||
|         &[maxHeight], |         &[maxHeight], | ||||||
|         &[ng-reflect-max-height] { |         &[ng-reflect-max-height] { | ||||||
|             &.core-text-formatted.core-text-format-expanded { |             &.collapsible-enabled.collapsible-expanded { | ||||||
|                 max-height: none !important; |                 max-height: none !important; | ||||||
| 
 | 
 | ||||||
|                 .core-format-text-toggle { |                 .collapsible-toggle { | ||||||
|                     display: none !important; |                     display: none !important; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -219,9 +219,84 @@ | |||||||
|             --horizontal-margin: 6px; |             --horizontal-margin: 6px; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @mixin collapsible-item() { | ||||||
|  |     --display-toggle: none; | ||||||
|  |     .collapsible-toggle { | ||||||
|  |         display: var(--display-toggle); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @include media-breakpoint-down(sm) { | ||||||
|  |         &.collapsible-enabled { | ||||||
|  |             position:relative; | ||||||
|  |             --display-toggle: block; | ||||||
|  | 
 | ||||||
|  |             .collapsible-toggle { | ||||||
|  |                 position: absolute; | ||||||
|  |                 @include position (null, 0, 0, null); | ||||||
|  |                 text-align: center; | ||||||
|  |                 z-index: 7; | ||||||
|  |                 text-transform: none; | ||||||
|  |                 font-size: 14px; | ||||||
|  |                 font-weight: normal; | ||||||
|  |                 background-color: var(--collapsible-toggle-background); | ||||||
|  |                 color: var(--collapsible-toggle-text); | ||||||
|  |                 min-height: var(--a11y-min-target-size); | ||||||
|  |                 min-width: var(--a11y-min-target-size); | ||||||
|  |                 --border-radius: var(--huge-radius); | ||||||
|  |                 border-radius: var(--border-radius); | ||||||
|  |                 --padding-start: 0px; | ||||||
|  |                 --padding-end: 0px; | ||||||
|  |                 margin: 0px; | ||||||
|  | 
 | ||||||
|  |                 .collapsible-toggle-arrow { | ||||||
|  |                     width: var(--a11y-min-target-size); | ||||||
|  |                     height: var(--a11y-min-target-size); | ||||||
|  | 
 | ||||||
|  |                     background-position: center; | ||||||
|  |                     background-repeat: no-repeat; | ||||||
|  |                     background-size: 14px 14px; | ||||||
|  |                     @include core-transition(transform, 500ms); | ||||||
|  | 
 | ||||||
|  |                     @include push-arrow-color(626262, true); | ||||||
|  | 
 | ||||||
|  |                     @include darkmode() { | ||||||
|  |                         @include push-arrow-color(ffffff, true); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             &.collapsible-collapsed { | ||||||
|  |                 overflow: hidden; | ||||||
|  |                 min-height: calc(var(--collapsible-min-button-height) + 12px); | ||||||
|  | 
 | ||||||
|  |                 .collapsible-toggle-arrow { | ||||||
|  |                     transform: rotate(90deg); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 &:before { | ||||||
|  |                     content: ''; | ||||||
|  |                     height: 100%; | ||||||
|  |                     position: absolute; | ||||||
|  |                     @include position(null, 0, 0, 0); | ||||||
|  |                     background: -webkit-linear-gradient(top, rgba(var(--background-gradient-rgb), 0) calc(100% - 56px), rgba(var(--background-gradient-rgb), 1) calc(100% - 5px)); | ||||||
|  |                     background: linear-gradient(to bottom, rgba(var(--background-gradient-rgb), 0) calc(100% - 56px), rgba(var(--background-gradient-rgb), 1) calc(100% - 5px)); | ||||||
|  |                     z-index: 6; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             &.collapsible-expanded { | ||||||
|  |                 max-height: none !important; | ||||||
|  |                 padding-bottom: var(--collapsible-min-button-height); // So the Show less button can fit. | ||||||
|  | 
 | ||||||
|  |                 .collapsible-toggle-arrow { | ||||||
|  |                     transform: rotate(-90deg); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| // Color mixins. | // Color mixins. | ||||||
| @function get_brightness($color) { | @function get_brightness($color) { | ||||||
|  | |||||||
| @ -164,6 +164,9 @@ ion-header { | |||||||
|             --ion-toolbar-color: var(--core-header-toolbar-color); |             --ion-toolbar-color: var(--core-header-toolbar-color); | ||||||
|             --border-radius: var(--huge-radius); |             --border-radius: var(--huge-radius); | ||||||
|         } |         } | ||||||
|  |         ion-back-button::part(text) { | ||||||
|  |             display: none; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         .button.button-clear, |         .button.button-clear, | ||||||
|         .button.button-solid { |         .button.button-solid { | ||||||
| @ -813,6 +816,7 @@ ion-card { | |||||||
|     border-color: var(--border-color); |     border-color: var(--border-color); | ||||||
|     box-shadow: var(--box-shadow); |     box-shadow: var(--box-shadow); | ||||||
|     border-radius: var(--border-radius); |     border-radius: var(--border-radius); | ||||||
|  |     margin: var(--ion-card-vertical-margin) var(--ion-card-horizontal-margin); | ||||||
| 
 | 
 | ||||||
|     ion-item:only-child { |     ion-item:only-child { | ||||||
|         --inner-border-width: 0px; |         --inner-border-width: 0px; | ||||||
| @ -983,6 +987,12 @@ ion-chip { | |||||||
|     min-height: 24px; |     min-height: 24px; | ||||||
|     height: auto; |     height: auto; | ||||||
| 
 | 
 | ||||||
|  |     // Chips are not currently clickable. | ||||||
|  |     &.ion-activatable { | ||||||
|  |         cursor: auto; | ||||||
|  |         pointer-events: none; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     &.ion-color { |     &.ion-color { | ||||||
|         background: var(--ion-color-tint); |         background: var(--ion-color-tint); | ||||||
|         &.chip-outline { |         &.chip-outline { | ||||||
| @ -1145,6 +1155,10 @@ ion-item.item-lines-inset { | |||||||
|     --border-width: 0px; |     --border-width: 0px; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | ion-item.item-input.ios { | ||||||
|  |     --inner-border-width: 0 0 1px 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Fake item. | // Fake item. | ||||||
| div.fake-ion-item { | div.fake-ion-item { | ||||||
|     position: relative; |     position: relative; | ||||||
| @ -1425,77 +1439,7 @@ ion-grid.core-no-grid > ion-row { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| [collapsible-item] { | [collapsible-item] { | ||||||
|     --collapsible-display-toggle: none; |     @include collapsible-item(); | ||||||
|     --collapsible-toggle-background: var(--ion-item-background); |  | ||||||
|     --collapsible-min-button-height: 44px; |  | ||||||
| 
 |  | ||||||
|     .collapsible-toggle { |  | ||||||
|         display: var(--collapsible-display-toggle); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     &.collapsible-enabled { |  | ||||||
|         --collapsible-display-toggle: block; |  | ||||||
| 
 |  | ||||||
|         .collapsible-toggle { |  | ||||||
|             display: var(--collapsible-display-toggle); |  | ||||||
|             position: absolute; |  | ||||||
|             bottom: 0; |  | ||||||
|             left: 0; |  | ||||||
|             right: 0; |  | ||||||
|             text-align: center; |  | ||||||
|             z-index: 7; |  | ||||||
|             text-transform: none; |  | ||||||
|             text-align: end; |  | ||||||
|             font-size: 14px; |  | ||||||
|             background-color: var(--collapsible-toggle-background); |  | ||||||
|             color: var(--text-color); |  | ||||||
|             margin: 0; |  | ||||||
| 
 |  | ||||||
|             .collapsible-toggle-arrow { |  | ||||||
|                 width: var(--a11y-min-target-size); |  | ||||||
|                 height: var(--a11y-min-target-size); |  | ||||||
| 
 |  | ||||||
|                 background-position: center; |  | ||||||
|                 background-repeat: no-repeat; |  | ||||||
|                 background-size: 14px 14px; |  | ||||||
|                 @include core-transition(transform, 500ms); |  | ||||||
| 
 |  | ||||||
|                 @include push-arrow-color(626262, true); |  | ||||||
| 
 |  | ||||||
|                 @include darkmode() { |  | ||||||
|                     @include push-arrow-color(ffffff, true); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         &.collapsible-collapsed { |  | ||||||
|             overflow: hidden; |  | ||||||
|             min-height: calc(var(--collapsible-min-button-height) + 12); |  | ||||||
| 
 |  | ||||||
|             .collapsible-toggle-arrow { |  | ||||||
|                 transform: rotate(90deg); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             &:before { |  | ||||||
|                 content: ''; |  | ||||||
|                 height: 100%; |  | ||||||
|                 position: absolute; |  | ||||||
|                 @include position(null, 0, 0, 0); |  | ||||||
|                 background: -webkit-linear-gradient(top, rgba(var(--core-format-text-background-gradient-rgb), 0) calc(100% - 60px), rgba(var(--core-format-text-background-gradient-rgb), 1) calc(100% - 40px)); |  | ||||||
|                 background: linear-gradient(to bottom, rgba(var(--core-format-text-background-gradient-rgb), 0) calc(100% - 60px), rgba(var(--core-format-text-background-gradient-rgb), 1) calc(100% - 40px)); |  | ||||||
|                 z-index: 6; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         &.collapsible-expanded { |  | ||||||
|             max-height: none !important; |  | ||||||
|             padding-bottom: var(--collapsible-min-button-height); // So the Show less button can fit. |  | ||||||
| 
 |  | ||||||
|             .collapsible-toggle-arrow { |  | ||||||
|                 transform: rotate(-90deg); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ion-header.no-title { | ion-header.no-title { | ||||||
|  | |||||||
| @ -97,6 +97,10 @@ | |||||||
|     --core-combobox-color: var(--text-color); |     --core-combobox-color: var(--text-color); | ||||||
|     --core-combobox-border-color: var(--core-input-stroke); |     --core-combobox-border-color: var(--core-input-stroke); | ||||||
| 
 | 
 | ||||||
|  |     --collapsible-toggle-background: var(--light); | ||||||
|  | 
 | ||||||
|  |     --background-gradient-rgb: #{$ion-item-background-dark-rgb}; | ||||||
|  | 
 | ||||||
|     --core-login-background: var(--gray-900); |     --core-login-background: var(--gray-900); | ||||||
|     --core-login-text-color: var(--white); |     --core-login-text-color: var(--white); | ||||||
|     --core-login-input-background: var(--core-login-background); |     --core-login-input-background: var(--core-login-background); | ||||||
|  | |||||||
| @ -88,6 +88,8 @@ | |||||||
|     --subdued-text-color: var(--gray-700); |     --subdued-text-color: var(--gray-700); | ||||||
| 
 | 
 | ||||||
|     --ion-card-color: var(--text-color); |     --ion-card-color: var(--text-color); | ||||||
|  |     --ion-card-vertical-margin: 10px; | ||||||
|  |     --ion-card-horizontal-margin: 10px; | ||||||
|     ion-card { |     ion-card { | ||||||
|         --border-width: 1px; |         --border-width: 1px; | ||||||
|         --border-style: solid; |         --border-style: solid; | ||||||
| @ -286,6 +288,12 @@ | |||||||
|     --selected-item-color: var(--primary); |     --selected-item-color: var(--primary); | ||||||
|     --selected-item-border-width: 5px; |     --selected-item-border-width: 5px; | ||||||
| 
 | 
 | ||||||
|  |     --collapsible-toggle-background: var(--light); | ||||||
|  |     --collapsible-min-button-height: 44px; | ||||||
|  |     --collapsible-toggle-text: var(--text-color); | ||||||
|  | 
 | ||||||
|  |     --background-gradient-rgb: #{$ion-item-background-rgb}; | ||||||
|  | 
 | ||||||
|     --core-login-background: var(--white); |     --core-login-background: var(--white); | ||||||
|     --core-login-text-color: var(--gray-900); |     --core-login-text-color: var(--gray-900); | ||||||
|     --core-login-input-background: var(--white); |     --core-login-input-background: var(--white); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user