forked from EVOgeek/Vmeda.Online
		
	
						commit
						9f0de18eaa
					
				| @ -5,7 +5,7 @@ | |||||||
|         </core-horizontal-scroll-controls> |         </core-horizontal-scroll-controls> | ||||||
|     </div> |     </div> | ||||||
| </ion-item-divider> | </ion-item-divider> | ||||||
| <core-loading [hideUntil]="loaded" [fullscreen]="false" class="safe-area-page margin"> | <core-loading [hideUntil]="loaded" [fullscreen]="false" class="safe-area-page"> | ||||||
|     <div |     <div | ||||||
|         [id]="scrollElementId" |         [id]="scrollElementId" | ||||||
|         [hidden]="!items || items.length === 0" |         [hidden]="!items || items.length === 0" | ||||||
|  | |||||||
| @ -8,4 +8,7 @@ | |||||||
|     .core-course-module-handler { |     .core-course-module-handler { | ||||||
|         --inner-border-width: 0; |         --inner-border-width: 0; | ||||||
|     } |     } | ||||||
|  |     core-loading { | ||||||
|  |         --loading-inline-min-height: 102px; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -53,7 +53,7 @@ | |||||||
|             </ion-item> |             </ion-item> | ||||||
|         </ion-card> |         </ion-card> | ||||||
| 
 | 
 | ||||||
|         <core-empty-box *ngIf="!filteredEvents || !filteredEvents.length" icon="fas-calendar" inline="true" |         <core-empty-box *ngIf="!filteredEvents || !filteredEvents.length" icon="fas-calendar" | ||||||
|             [message]="'addon.calendar.noevents' | translate"> |             [message]="'addon.calendar.noevents' | translate"> | ||||||
|         </core-empty-box> |         </core-empty-box> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -96,7 +96,7 @@ | |||||||
|                             <core-user-avatar slot="start" [user]="members[message.useridfrom]" [linkProfile]="false" |                             <core-user-avatar slot="start" [user]="members[message.useridfrom]" [linkProfile]="false" | ||||||
|                                 aria-hidden="true"> |                                 aria-hidden="true"> | ||||||
|                             </core-user-avatar> |                             </core-user-avatar> | ||||||
|                             {{ members[message.useridfrom].fullname }} |                             <div>{{ members[message.useridfrom].fullname }}</div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div *ngIf="!message.showUserData" class="sr-only"> |                         <div *ngIf="!message.showUserData" class="sr-only"> | ||||||
|                             {{ message.useridfrom == currentUserId |                             {{ message.useridfrom == currentUserId | ||||||
|  | |||||||
| @ -8,7 +8,6 @@ | |||||||
|             <h2>{{ user!.fullname }}</h2> |             <h2>{{ user!.fullname }}</h2> | ||||||
|             <ng-container *ngTemplateOutlet="submissionStatus"></ng-container> |             <ng-container *ngTemplateOutlet="submissionStatus"></ng-container> | ||||||
|         </ion-label> |         </ion-label> | ||||||
|         <ng-container *ngTemplateOutlet="submissionStatusBadges"></ng-container> |  | ||||||
|     </ion-item> |     </ion-item> | ||||||
| 
 | 
 | ||||||
|     <!-- Status of the submission if user is blinded. --> |     <!-- Status of the submission if user is blinded. --> | ||||||
| @ -17,7 +16,6 @@ | |||||||
|             <h2>{{ 'addon.mod_assign.hiddenuser' | translate }} {{blindId}}</h2> |             <h2>{{ 'addon.mod_assign.hiddenuser' | translate }} {{blindId}}</h2> | ||||||
|             <ng-container *ngTemplateOutlet="submissionStatus"></ng-container> |             <ng-container *ngTemplateOutlet="submissionStatus"></ng-container> | ||||||
|         </ion-label> |         </ion-label> | ||||||
|         <ng-container *ngTemplateOutlet="submissionStatusBadges"></ng-container> |  | ||||||
|     </ion-item> |     </ion-item> | ||||||
| 
 | 
 | ||||||
|     <!-- Status of the submission in the rest of cases. --> |     <!-- Status of the submission in the rest of cases. --> | ||||||
| @ -26,7 +24,6 @@ | |||||||
|             <h2>{{ 'addon.mod_assign.submissionstatus' | translate }}</h2> |             <h2>{{ 'addon.mod_assign.submissionstatus' | translate }}</h2> | ||||||
|             <ng-container *ngTemplateOutlet="submissionStatus"></ng-container> |             <ng-container *ngTemplateOutlet="submissionStatus"></ng-container> | ||||||
|         </ion-label> |         </ion-label> | ||||||
|         <ng-container *ngTemplateOutlet="submissionStatusBadges"></ng-container> |  | ||||||
|     </ion-item> |     </ion-item> | ||||||
| 
 | 
 | ||||||
|     <!-- Tabs: see the submission or grade it. --> |     <!-- Tabs: see the submission or grade it. --> | ||||||
| @ -385,12 +382,12 @@ | |||||||
|             {{ 'addon.mod_assign.defaultteam' | translate }} |             {{ 'addon.mod_assign.defaultteam' | translate }} | ||||||
|         </p> |         </p> | ||||||
|     </ng-container> |     </ng-container> | ||||||
| </ng-template> |     <p> | ||||||
| <ng-template #submissionStatusBadges> |         <ion-badge *ngIf="statusTranslated" [color]="statusColor"> | ||||||
|     <ion-badge slot="end" *ngIf="statusTranslated" [color]="statusColor"> |  | ||||||
|             {{ statusTranslated }} |             {{ statusTranslated }} | ||||||
|         </ion-badge> |         </ion-badge> | ||||||
|     <ion-badge slot="end" *ngIf="gradingStatusTranslationId" [color]="gradingColor"> |         <ion-badge class="ion-margin-start" *ngIf="gradingStatusTranslationId" [color]="gradingColor"> | ||||||
|             {{ gradingStatusTranslationId | translate }} |             {{ gradingStatusTranslationId | translate }} | ||||||
|         </ion-badge> |         </ion-badge> | ||||||
|  |     </p> | ||||||
| </ng-template> | </ng-template> | ||||||
|  | |||||||
| @ -43,10 +43,10 @@ | |||||||
|     </ion-card> |     </ion-card> | ||||||
| 
 | 
 | ||||||
|     <ng-container *ngIf="chat"> |     <ng-container *ngIf="chat"> | ||||||
|         <ion-button class="ion-margin" expand="block" color="primary" (click)="enterChat()"> |         <ion-button class="ion-margin ion-text-wrap" expand="block" color="primary" (click)="enterChat()"> | ||||||
|             {{ 'addon.mod_chat.enterchat' | translate }} |             {{ 'addon.mod_chat.enterchat' | translate }} | ||||||
|         </ion-button> |         </ion-button> | ||||||
|         <ion-button class="ion-margin" expand="block" color="light" *ngIf="sessionsAvailable" (click)="viewSessions()"> |         <ion-button class="ion-margin ion-text-wrap" expand="block" color="light" *ngIf="sessionsAvailable" (click)="viewSessions()"> | ||||||
|             {{ 'addon.mod_chat.viewreport' | translate }} |             {{ 'addon.mod_chat.viewreport' | translate }} | ||||||
|         </ion-button> |         </ion-button> | ||||||
|     </ng-container> |     </ng-container> | ||||||
|  | |||||||
| @ -10,11 +10,13 @@ | |||||||
|         <core-context-menu-item *ngIf="blog" |         <core-context-menu-item *ngIf="blog" | ||||||
|             [priority]="750" content="{{'addon.blog.blog' | translate}}" [iconAction]="'far-newspaper'" (action)="gotoBlog()"> |             [priority]="750" content="{{'addon.blog.blog' | translate}}" [iconAction]="'far-newspaper'" (action)="gotoBlog()"> | ||||||
|         </core-context-menu-item> |         </core-context-menu-item> | ||||||
|         <core-context-menu-item *ngIf="discussions.loaded && !(hasOffline || hasOfflineRatings) && isOnline" |         <core-context-menu-item | ||||||
|  |             *ngIf="discussions.onlineLoaded && discussions.loaded && !(hasOffline || hasOfflineRatings) && isOnline" | ||||||
|             [priority]="700" [content]="'addon.mod_forum.refreshdiscussions' | translate" [iconAction]="refreshIcon" [closeOnClick]="false" |             [priority]="700" [content]="'addon.mod_forum.refreshdiscussions' | translate" [iconAction]="refreshIcon" [closeOnClick]="false" | ||||||
|             (action)="doRefresh(null, $event)"> |             (action)="doRefresh(null, $event)"> | ||||||
|         </core-context-menu-item> |         </core-context-menu-item> | ||||||
|         <core-context-menu-item *ngIf="discussions.loaded && (hasOffline || hasOfflineRatings) && isOnline" |         <core-context-menu-item | ||||||
|  |             *ngIf="discussions.onlineLoaded && discussions.loaded && (hasOffline || hasOfflineRatings) && isOnline" | ||||||
|             [priority]="600" [content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false" |             [priority]="600" [content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false" | ||||||
|             (action)="doRefresh(null, $event, true)"> |             (action)="doRefresh(null, $event, true)"> | ||||||
|         </core-context-menu-item> |         </core-context-menu-item> | ||||||
| @ -37,11 +39,11 @@ | |||||||
| 
 | 
 | ||||||
| <!-- Content. --> | <!-- Content. --> | ||||||
| <core-split-view> | <core-split-view> | ||||||
|     <ion-refresher slot="fixed" [disabled]="!discussions.loaded" (ionRefresh)="doRefresh($event.target)"> |     <ion-refresher slot="fixed" [disabled]="!discussions.onlineLoaded || !discussions.loaded" (ionRefresh)="doRefresh($event.target)"> | ||||||
|         <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content> |         <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content> | ||||||
|     </ion-refresher> |     </ion-refresher> | ||||||
| 
 | 
 | ||||||
|     <core-loading [hideUntil]="discussions.loaded"> |     <core-loading [hideUntil]="discussions.onlineLoaded && discussions.loaded"> | ||||||
|         <!-- Activity info. --> |         <!-- Activity info. --> | ||||||
|         <core-course-module-info *ngIf="showCompletion" [module]="module" [showManualCompletion]="true" |         <core-course-module-info *ngIf="showCompletion" [module]="module" [showManualCompletion]="true" | ||||||
|             (completionChanged)="onCompletionChange()"> |             (completionChanged)="onCompletionChange()"> | ||||||
|  | |||||||
| @ -49,7 +49,7 @@ | |||||||
|         [autoFocus]="true" [lengthCheck]="2" (onClear)="toggleSearch()" searchArea="AddonModGlossary-{{module.id}}"> |         [autoFocus]="true" [lengthCheck]="2" (onClear)="toggleSearch()" searchArea="AddonModGlossary-{{module.id}}"> | ||||||
|     </core-search-box> |     </core-search-box> | ||||||
| 
 | 
 | ||||||
|     <core-loading [hideUntil]="entries.loaded"> |     <core-loading [hideUntil]="loaded"> | ||||||
|         <!-- Activity info. --> |         <!-- Activity info. --> | ||||||
|         <core-course-module-info *ngIf="showCompletion" [module]="module" [showManualCompletion]="true" |         <core-course-module-info *ngIf="showCompletion" [module]="module" [showManualCompletion]="true" | ||||||
|             (completionChanged)="onCompletionChange()"> |             (completionChanged)="onCompletionChange()"> | ||||||
|  | |||||||
| @ -47,12 +47,8 @@ export class AddonModGlossaryEditLinkHandlerService extends CoreContentLinksHand | |||||||
|                     const module = await CoreCourse.getModuleBasicInfo(cmId, siteId); |                     const module = await CoreCourse.getModuleBasicInfo(cmId, siteId); | ||||||
| 
 | 
 | ||||||
|                     await CoreNavigator.navigateToSitePath( |                     await CoreNavigator.navigateToSitePath( | ||||||
|                         AddonModGlossaryModuleHandlerService.PAGE_NAME + '/edit/0', |                         AddonModGlossaryModuleHandlerService.PAGE_NAME + `/${module.course}/${module.id}/edit/0`, | ||||||
|                         { |                         { | ||||||
|                             params: { |  | ||||||
|                                 cmId: module.id, |  | ||||||
|                                 courseId: module.course, |  | ||||||
|                             }, |  | ||||||
|                             siteId, |                             siteId, | ||||||
|                         }, |                         }, | ||||||
|                     ); |                     ); | ||||||
|  | |||||||
| @ -52,12 +52,8 @@ export class AddonModGlossaryEntryLinkHandlerService extends CoreContentLinksHan | |||||||
|                     ); |                     ); | ||||||
| 
 | 
 | ||||||
|                     await CoreNavigator.navigateToSitePath( |                     await CoreNavigator.navigateToSitePath( | ||||||
|                         AddonModGlossaryModuleHandlerService.PAGE_NAME + `/entry/${entryId}`, |                         AddonModGlossaryModuleHandlerService.PAGE_NAME + `/${module.course}/${module.id}/entry/${entryId}`, | ||||||
|                         { |                         { | ||||||
|                             params: { |  | ||||||
|                                 cmId: module.id, |  | ||||||
|                                 courseId: module.course, |  | ||||||
|                             }, |  | ||||||
|                             siteId, |                             siteId, | ||||||
|                         }, |                         }, | ||||||
|                     ); |                     ); | ||||||
|  | |||||||
| @ -144,15 +144,36 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft | |||||||
| 
 | 
 | ||||||
|         this.tabBarHeight = this.tabBarElement.offsetHeight; |         this.tabBarHeight = this.tabBarElement.offsetHeight; | ||||||
| 
 | 
 | ||||||
|         if (this.tabsShown) { |         this.applyScroll(this.tabsShown, this.lastScroll); | ||||||
|             // Smooth translation.
 |  | ||||||
|             this.tabBarElement.style.top = - this.lastScroll + 'px'; |  | ||||||
|             this.tabBarElement.style.height = 'calc(100% + ' + scroll + 'px'; |  | ||||||
|         } else { |  | ||||||
|             this.tabBarElement.classList.add('tabs-hidden'); |  | ||||||
|             this.tabBarElement.style.top = '0'; |  | ||||||
|             this.tabBarElement.style.height = ''; |  | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Apply scroll to hiding tabs. | ||||||
|  |      * | ||||||
|  |      * @param showTabs Show or completely hide tabs. | ||||||
|  |      * @param scroll Scroll position. | ||||||
|  |      */ | ||||||
|  |     protected applyScroll(showTabs: boolean, scroll?: number): void { | ||||||
|  |         if (!this.tabBarElement || !this.tabBarHeight) { | ||||||
|  | 
 | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (showTabs) { | ||||||
|  |             // Smooth translation.
 | ||||||
|  |             this.tabBarElement!.classList.remove('tabs-hidden'); | ||||||
|  |             if (scroll === 0) { | ||||||
|  |                 this.tabBarElement!.style.height = ''; | ||||||
|  |                 this.lastScroll = 0; | ||||||
|  |             } else if (scroll !== undefined) { | ||||||
|  |                 this.tabBarElement!.style.height = (this.tabBarHeight - scroll) + 'px'; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             this.tabBarElement!.classList.add('tabs-hidden'); | ||||||
|  |             this.tabBarElement!.style.height = ''; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         this.tabsShown = showTabs; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -478,11 +499,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft | |||||||
| 
 | 
 | ||||||
|         if (scrollTop <= 0) { |         if (scrollTop <= 0) { | ||||||
|             // Ensure tabbar is shown.
 |             // Ensure tabbar is shown.
 | ||||||
|             this.tabsElement.style.top = '0'; |             this.applyScroll(true, 0); | ||||||
|             this.tabsElement.style.height = ''; |  | ||||||
|             this.tabBarElement.classList.remove('tabs-hidden'); |  | ||||||
|             this.tabsShown = true; |  | ||||||
|             this.lastScroll = 0; |  | ||||||
| 
 | 
 | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @ -493,22 +510,17 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (this.tabsShown && scrollTop > this.tabBarHeight) { |         if (this.tabsShown && scrollTop > this.tabBarHeight) { | ||||||
|             this.tabsShown = false; |  | ||||||
| 
 |  | ||||||
|             // Hide tabs.
 |             // Hide tabs.
 | ||||||
|             this.tabBarElement.classList.add('tabs-hidden'); |             this.applyScroll(false); | ||||||
|             this.tabsElement.style.top = '0'; |  | ||||||
|             this.tabsElement.style.height = ''; |  | ||||||
|         } else if (!this.tabsShown && scrollTop <= this.tabBarHeight) { |         } else if (!this.tabsShown && scrollTop <= this.tabBarHeight) { | ||||||
|             this.tabsShown = true; |             this.applyScroll(true); | ||||||
|             this.tabBarElement.classList.remove('tabs-hidden'); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (this.tabsShown && scrollElement.scrollHeight > scrollElement.clientHeight + (this.tabBarHeight - scrollTop)) { |         if (this.tabsShown && scrollElement.scrollHeight > scrollElement.clientHeight + (this.tabBarHeight - scrollTop)) { | ||||||
|             // Smooth translation.
 |             // Smooth translation.
 | ||||||
|             this.tabsElement.style.top = - scrollTop + 'px'; |             this.applyScroll(true, scrollTop); | ||||||
|             this.tabsElement.style.height = 'calc(100% + ' + scrollTop + 'px'; |  | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|         // Use lastScroll after moving the tabs to avoid flickering.
 |         // Use lastScroll after moving the tabs to avoid flickering.
 | ||||||
|         this.lastScroll = scrollTop; |         this.lastScroll = scrollTop; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -13,7 +13,6 @@ | |||||||
|         --color: var(--core-combobox-color); |         --color: var(--core-combobox-color); | ||||||
|         --color-activated: var(--core-combobox-color); |         --color-activated: var(--core-combobox-color); | ||||||
|         --border-color: var(--core-combobox-border-color); |         --border-color: var(--core-combobox-border-color); | ||||||
|         --border-width: 0 0 var(--core-combobox-border-width) 0; |  | ||||||
|         --border-style: solid; |         --border-style: solid; | ||||||
|         --color-focused: currentcolor; |         --color-focused: currentcolor; | ||||||
|         --color-hover: currentcolor; |         --color-hover: currentcolor; | ||||||
| @ -53,9 +52,7 @@ ion-button { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ion-select { | ion-select { | ||||||
|     border-color: var(--border-color); |     border-bottom: var(--core-combobox-border-width) var(--border-style) var(--border-color); | ||||||
|     border-width: var(--border-width); |  | ||||||
|     border-style: var(--border-style); |  | ||||||
| 
 | 
 | ||||||
|     &::part(icon) { |     &::part(icon) { | ||||||
|         margin: var(--icon-margin); |         margin: var(--icon-margin); | ||||||
| @ -84,6 +81,8 @@ ion-select { | |||||||
| 
 | 
 | ||||||
| ion-button { | ion-button { | ||||||
|     --border-radius: 0; |     --border-radius: 0; | ||||||
|  |     --border-width: 0 0 var(--core-combobox-border-width) 0; | ||||||
|  | 
 | ||||||
|     flex: 1; |     flex: 1; | ||||||
|     min-height: 45px; |     min-height: 45px; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,21 +2,24 @@ | |||||||
| 
 | 
 | ||||||
| :host { | :host { | ||||||
|     --loading-background: var(--ion-background-color); |     --loading-background: var(--ion-background-color); | ||||||
|  |     --loading-background-inline: var(--ion-background-color-rgb); | ||||||
|     --loading-spinner: var(--ion-color-primary); |     --loading-spinner: var(--ion-color-primary); | ||||||
|     --loading-text-color: var(--ion-text-color); |     --loading-text-color: var(--ion-text-color); | ||||||
|     --loading-inline-margin: 0; |     --loading-inline-margin: 0; | ||||||
|     --loading-inline-min-height: 28px; |     --loading-inline-min-height: 28px; | ||||||
|  |     --internal-loading-inline-min-height: var(--loading-inline-min-height); | ||||||
| 
 | 
 | ||||||
|     position: static; |     position: static; | ||||||
|     color: var(--loading-text-color); |     color: var(--loading-text-color); | ||||||
|  |     @include core-transition(all, 200ms); | ||||||
| 
 | 
 | ||||||
|     &.margin { |     &.margin { | ||||||
|         --loading-inline-margin: 10px; |         --loading-inline-margin: 10px; | ||||||
|  |         --internal-loading-inline-min-height: calc(var(--loading-inline-min-height) + var(--loading-inline-margin) + var(--loading-inline-margin)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     &.core-loading-loaded { |     &.core-loading-loaded { | ||||||
|         --loading-inline-margin: 0; |         --internal-loading-inline-min-height: 0; | ||||||
|         --loading-inline-min-height: 0; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ion-spinner { |     ion-spinner { | ||||||
| @ -27,17 +30,17 @@ | |||||||
|     .core-loading-container { |     .core-loading-container { | ||||||
|         position: absolute; |         position: absolute; | ||||||
|         @include position(0, 0, 0, 0); |         @include position(0, 0, 0, 0); | ||||||
|         display: flex; |  | ||||||
|         height: 100%; |         height: 100%; | ||||||
|         width: 100%; |         width: 100%; | ||||||
|         justify-content: center; |  | ||||||
|         align-items: center; |  | ||||||
|         flex-direction: column; |  | ||||||
|         z-index: 3; |         z-index: 3; | ||||||
|         margin: 0; |         margin: 0; | ||||||
|         padding: 0; |         padding: 0; | ||||||
|         background-color: var(--loading-background); |         background-color: var(--loading-background); | ||||||
|         @include core-transition(all, 200ms); |         @include core-transition(all, 200ms); | ||||||
|  |         display: flex; | ||||||
|  |         justify-content: center; | ||||||
|  |         align-items: center; | ||||||
|  |         flex-direction: column; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     .core-loading-message { |     .core-loading-message { | ||||||
| @ -54,15 +57,14 @@ | |||||||
| 
 | 
 | ||||||
|     &.core-loading-loaded { |     &.core-loading-loaded { | ||||||
|         position: unset; |         position: unset; | ||||||
|  |         display: contents; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     &.core-loading-inline { |     &.core-loading-inline { | ||||||
|         --loading-background: transparent; |         --loading-background: rgba(var(--loading-background-inline), 0.5); | ||||||
|         position: relative; |         position: relative; | ||||||
|         display: block; |         display: block; | ||||||
|         min-height: var(--loading-inline-min-height); |         min-height: var(--internal-loading-inline-min-height); | ||||||
|         margin-top: var(--loading-inline-margin); |  | ||||||
|         margin-bottom: var(--loading-inline-margin); |  | ||||||
| 
 | 
 | ||||||
|         .core-loading-message { |         .core-loading-message { | ||||||
|             @include margin(0, 0, 0, 10px); |             @include margin(0, 0, 0, 10px); | ||||||
|  | |||||||
| @ -22,6 +22,8 @@ | |||||||
|         -webkit-filter: drop-shadow(0px 3px 3px rgba(var(--drop-shadow))); |         -webkit-filter: drop-shadow(0px 3px 3px rgba(var(--drop-shadow))); | ||||||
|         filter: drop-shadow(0px 3px 3px rgba(var(--drop-shadow))); |         filter: drop-shadow(0px 3px 3px rgba(var(--drop-shadow))); | ||||||
|         border: 0; |         border: 0; | ||||||
|  |         display: flex; | ||||||
|  |         align-items: flex-end; | ||||||
| 
 | 
 | ||||||
|         ion-row { |         ion-row { | ||||||
|             width: 100%; |             width: 100%; | ||||||
|  | |||||||
| @ -72,6 +72,7 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|     @Input() wsNotFiltered?: boolean | string; // If true it means the WS didn't filter the text for some reason.
 |     @Input() wsNotFiltered?: boolean | string; // If true it means the WS didn't filter the text for some reason.
 | ||||||
|     @Input() captureLinks?: boolean; // Whether links should tried to be opened inside the app. Defaults to true.
 |     @Input() captureLinks?: boolean; // Whether links should tried to be opened inside the app. Defaults to true.
 | ||||||
|     @Input() openLinksInApp?: boolean; // Whether links should be opened in InAppBrowser.
 |     @Input() openLinksInApp?: boolean; // Whether links should be opened in InAppBrowser.
 | ||||||
|  |     @Input() hideIfEmpty = false; // If true, the tag will contain nothing if text is empty.
 | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Max height in pixels to render the content box. It should be 50 at least to make sense. |      * Max height in pixels to render the content box. It should be 50 at least to make sense. | ||||||
| @ -86,6 +87,8 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|     protected element: HTMLElement; |     protected element: HTMLElement; | ||||||
|     protected showMoreDisplayed = false; |     protected showMoreDisplayed = false; | ||||||
|     protected loadingChangedListener?: CoreEventObserver; |     protected loadingChangedListener?: CoreEventObserver; | ||||||
|  |     protected emptyText = ''; | ||||||
|  |     protected contentSpan: HTMLElement; | ||||||
| 
 | 
 | ||||||
|     constructor( |     constructor( | ||||||
|         element: ElementRef, |         element: ElementRef, | ||||||
| @ -93,9 +96,20 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|         protected viewContainerRef: ViewContainerRef, |         protected viewContainerRef: ViewContainerRef, | ||||||
|         protected sanitizer: DomSanitizer, |         protected sanitizer: DomSanitizer, | ||||||
|     ) { |     ) { | ||||||
| 
 |  | ||||||
|         this.element = element.nativeElement; |         this.element = element.nativeElement; | ||||||
|         this.element.classList.add('opacity-hide'); // Hide contents until they're treated.
 |         this.element.classList.add('core-format-text-loading'); // Hide contents until they're treated.
 | ||||||
|  | 
 | ||||||
|  |         const placeholder = document.createElement('span'); | ||||||
|  |         placeholder.classList.add('core-format-text-loader'); | ||||||
|  |         this.element.appendChild(placeholder); | ||||||
|  | 
 | ||||||
|  |         this.contentSpan = document.createElement('span'); | ||||||
|  |         this.contentSpan.classList.add('core-format-text-content'); | ||||||
|  |         this.element.appendChild(this.contentSpan); | ||||||
|  | 
 | ||||||
|  |         this.emptyText = this.hideIfEmpty ? '' : ' '; | ||||||
|  |         this.contentSpan.innerHTML = this.emptyText; | ||||||
|  | 
 | ||||||
|         this.afterRender = new EventEmitter<void>(); |         this.afterRender = new EventEmitter<void>(); | ||||||
| 
 | 
 | ||||||
|         this.element.addEventListener('click', this.elementClicked.bind(this)); |         this.element.addEventListener('click', this.elementClicked.bind(this)); | ||||||
| @ -183,7 +197,7 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|      * Add magnifying glass icons to view adapted images at full size. |      * Add magnifying glass icons to view adapted images at full size. | ||||||
|      */ |      */ | ||||||
|     addMagnifyingGlasses(): void { |     addMagnifyingGlasses(): void { | ||||||
|         const imgs = Array.from(this.element.querySelectorAll('.core-adapted-img-container > img')); |         const imgs = Array.from(this.contentSpan.querySelectorAll('.core-adapted-img-container > img')); | ||||||
|         if (!imgs.length) { |         if (!imgs.length) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @ -339,7 +353,7 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|      */ |      */ | ||||||
|     protected finishRender(): void { |     protected finishRender(): void { | ||||||
|         // Show the element again.
 |         // Show the element again.
 | ||||||
|         this.element.classList.remove('opacity-hide'); |         this.element.classList.remove('core-format-text-loading'); | ||||||
|         // Emit the afterRender output.
 |         // Emit the afterRender output.
 | ||||||
|         this.afterRender.emit(); |         this.afterRender.emit(); | ||||||
|     } |     } | ||||||
| @ -349,7 +363,7 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|      */ |      */ | ||||||
|     protected async formatAndRenderContents(): Promise<void> { |     protected async formatAndRenderContents(): Promise<void> { | ||||||
|         if (!this.text) { |         if (!this.text) { | ||||||
|             this.element.innerHTML = ''; // Remove current contents.
 |             this.contentSpan.innerHTML = this.emptyText; // Remove current contents.
 | ||||||
|             this.finishRender(); |             this.finishRender(); | ||||||
| 
 | 
 | ||||||
|             return; |             return; | ||||||
| @ -370,12 +384,12 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|         // Disable media adapt to correctly calculate the height.
 |         // Disable media adapt to correctly calculate the height.
 | ||||||
|         this.element.classList.add('core-disable-media-adapt'); |         this.element.classList.add('core-disable-media-adapt'); | ||||||
| 
 | 
 | ||||||
|         this.element.innerHTML = ''; // Remove current contents.
 |         this.contentSpan.innerHTML = ''; // Remove current contents.
 | ||||||
|         if (this.maxHeight && result.div.innerHTML != '' && |         if (this.maxHeight && result.div.innerHTML != '' && | ||||||
|                 (this.fullOnClick || (window.innerWidth < 576 || window.innerHeight < 576))) { // Don't collapse in big screens.
 |                 (this.fullOnClick || (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.element); |             CoreDomUtils.moveChildren(result.div, this.contentSpan); | ||||||
| 
 | 
 | ||||||
|             // Calculate the height now.
 |             // Calculate the height now.
 | ||||||
|             this.calculateHeight(); |             this.calculateHeight(); | ||||||
| @ -396,7 +410,7 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|                     }); |                     }); | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             CoreDomUtils.moveChildren(result.div, this.element); |             CoreDomUtils.moveChildren(result.div, this.contentSpan); | ||||||
| 
 | 
 | ||||||
|             // Add magnifying glasses to images.
 |             // Add magnifying glasses to images.
 | ||||||
|             this.addMagnifyingGlasses(); |             this.addMagnifyingGlasses(); | ||||||
| @ -405,7 +419,7 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|         if (result.options.filter) { |         if (result.options.filter) { | ||||||
|             // Let filters handle HTML. We do it here because we don't want them to block the render of the text.
 |             // Let filters handle HTML. We do it here because we don't want them to block the render of the text.
 | ||||||
|             CoreFilterDelegate.handleHtml( |             CoreFilterDelegate.handleHtml( | ||||||
|                 this.element, |                 this.contentSpan, | ||||||
|                 result.filters, |                 result.filters, | ||||||
|                 this.viewContainerRef, |                 this.viewContainerRef, | ||||||
|                 result.options, |                 result.options, | ||||||
|  | |||||||
| @ -66,7 +66,7 @@ describe('CoreFormatTextDirective', () => { | |||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|         // Assert
 |         // Assert
 | ||||||
|         const text = fixture.nativeElement.querySelector('core-format-text'); |         const text = fixture.nativeElement.querySelector('core-format-text .core-format-text-content'); | ||||||
|         expect(text).not.toBeNull(); |         expect(text).not.toBeNull(); | ||||||
|         expect(text.innerHTML).toEqual(sentence); |         expect(text.innerHTML).toEqual(sentence); | ||||||
|     }); |     }); | ||||||
|  | |||||||
| @ -142,7 +142,10 @@ | |||||||
|         </ion-item-divider> |         </ion-item-divider> | ||||||
| 
 | 
 | ||||||
|         <ion-item class="ion-text-wrap" *ngIf="section.summary"> |         <ion-item class="ion-text-wrap" *ngIf="section.summary"> | ||||||
|             <core-format-text [text]="section.summary" contextLevel="course" [contextInstanceId]="course?.id"></core-format-text> |             <ion-label> | ||||||
|  |                 <core-format-text [text]="section.summary" contextLevel="course" [contextInstanceId]="course?.id"> | ||||||
|  |                 </core-format-text> | ||||||
|  |             </ion-label> | ||||||
|         </ion-item> |         </ion-item> | ||||||
| 
 | 
 | ||||||
|         <ng-container *ngFor="let module of section.modules"> |         <ng-container *ngFor="let module of section.modules"> | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								src/theme/bootstrap.scss
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								src/theme/bootstrap.scss
									
									
									
									
										vendored
									
									
								
							| @ -9,6 +9,7 @@ | |||||||
|     clip: rect(0, 0, 0, 0); |     clip: rect(0, 0, 0, 0); | ||||||
|     white-space: nowrap; |     white-space: nowrap; | ||||||
|     border: 0; |     border: 0; | ||||||
|  |     display: block !important; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .sr-only-focusable:active, .sr-only-focusable:focus { | .sr-only-focusable:active, .sr-only-focusable:focus { | ||||||
|  | |||||||
| @ -2,22 +2,70 @@ | |||||||
| /** Styles of elements inside the directive should be placed in format-text.scss */ | /** Styles of elements inside the directive should be placed in format-text.scss */ | ||||||
| @import "~theme/globals"; | @import "~theme/globals"; | ||||||
| 
 | 
 | ||||||
| :root { | core-format-text { | ||||||
|     --background: var(--background, #{$ion-item-background}); |     --core-format-text-background: var(--background, #{$ion-item-background}); | ||||||
|     --background-gradient-rgb: var(--background-rgb, #{color-to-rgb-list($ion-item-background)}); |     --core-format-text-background-gradient-rgb: var(--background-rgb, #{color-to-rgb-list($ion-item-background)}); | ||||||
|     --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; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| :root body.dark { | body.dark core-format-text { | ||||||
|     --background: var(--background, #{$ion-item-background-dark}); |     --core-format-text-background: var(--background, #{$ion-item-background-dark}); | ||||||
|     --background-gradient-rgb: var(--background-rgb, #{color-to-rgb-list($ion-item-background-dark)}); |     --core-format-text-background-gradient-rgb: var(--background-rgb, #{color-to-rgb-list($ion-item-background-dark)}); | ||||||
|     --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 { | core-format-text { | ||||||
|  |     display: contents; | ||||||
|  | 
 | ||||||
|  |     .core-format-text-loader { | ||||||
|  |         opacity: 0; | ||||||
|  |         @include core-transition(opacity, 200ms); | ||||||
|  |         display: contents; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     &.core-format-text-loading { | ||||||
|  |         position: relative; | ||||||
|  |         width: 100%; | ||||||
|  |         height: 100%; | ||||||
|  |         opacity: 1; | ||||||
|  |         background-color: rgba(0,0,0,.1); | ||||||
|  |         overflow: hidden; | ||||||
|  |         border-radius: 5px; | ||||||
|  |         display: block; | ||||||
|  | 
 | ||||||
|  |         .core-format-text-loader { | ||||||
|  |             position: absolute; | ||||||
|  |             left: -45%; | ||||||
|  |             height: 100%; | ||||||
|  |             width: 45%; | ||||||
|  |             background-image: -webkit-linear-gradient(to left, rgba(var(--core-format-text-loader-shine), .05), rgba(var(--core-format-text-loader-shine), .3), rgba(var(--core-format-text-loader-shine), .6), rgba(var(--core-format-text-loader-shine), .3), rgba(var(--core-format-text-loader-shine), .05)); | ||||||
|  |             background-image: linear-gradient(to left, rgba(var(--core-format-text-loader-shine), .05), rgba(var(--core-format-text-loader-shine), .3), rgba(var(--core-format-text-loader-shine), .6), rgba(var(--core-format-text-loader-shine), .3), rgba(var(--core-format-text-loader-shine), .05)); | ||||||
|  |             animation: loading 1s infinite; | ||||||
|  |             opacity: 1; | ||||||
|  |             display: inline; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .core-format-text-content { | ||||||
|  |             opacity: 0; | ||||||
|  |             display: inline; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .core-show-more { | ||||||
|  |             display: none !important; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .core-format-text-content { | ||||||
|  |         opacity: 1; | ||||||
|  |         @include core-transition(opacity, 200ms); | ||||||
|  | 
 | ||||||
|  |         display: contents; | ||||||
|         user-select: text; |         user-select: text; | ||||||
|         word-break: break-word; |         word-break: break-word; | ||||||
|         word-wrap: break-word; |         word-wrap: break-word; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     &[maxHeight], |     &[maxHeight], | ||||||
|     &[ng-reflect-max-height] { |     &[ng-reflect-max-height] { | ||||||
| @ -57,7 +105,7 @@ core-format-text { | |||||||
|                     position: absolute; |                     position: absolute; | ||||||
|                     @include position(null, 0, 0, null); |                     @include position(null, 0, 0, null); | ||||||
|                     z-index: 7; |                     z-index: 7; | ||||||
|                     background-color: var(--background); |                     background-color: var(--core-format-text-background); | ||||||
|                     color: var(--text-color); |                     color: var(--text-color); | ||||||
|                     @include padding(null, null, null, 10px); |                     @include padding(null, null, null, 10px); | ||||||
|                     margin: 0; |                     margin: 0; | ||||||
| @ -68,10 +116,8 @@ core-format-text { | |||||||
|                     height: 100%; |                     height: 100%; | ||||||
|                     position: absolute; |                     position: absolute; | ||||||
|                     @include position(null, 0, 0, 0); |                     @include position(null, 0, 0, 0); | ||||||
|                     background: -moz-linear-gradient(top, rgba(var(--background-gradient-rgb), 0) calc(100% - 50px), rgba(var(--background-gradient-rgb), 1) calc(100% - 15px)); |                     background: -webkit-linear-gradient(top, rgba(var(--core-format-text-background-gradient-rgb), 0) calc(100% - 50px), rgba(var(--core-format-text-background-gradient-rgb), 1) calc(100% - 15px)); | ||||||
|                     background: -webkit-gradient(left top, left bottom, color-stop(calc(100% - 50px), rgba(var(--background-gradient-rgb), 0)), color-stop(calc(100% - 15px), rgba(var(--background-gradient-rgb), 1))); |                     background: linear-gradient(to bottom, rgba(var(--core-format-text-background-gradient-rgb), 0) calc(100% - 50px), rgba(var(--core-format-text-background-gradient-rgb), 1) calc(100% - 15px)); | ||||||
|                     background: -webkit-linear-gradient(top, rgba(var(--background-gradient-rgb), 0) calc(100% - 50px), rgba(var(--background-gradient-rgb), 1) calc(100% - 15px)); |  | ||||||
|                     background: linear-gradient(to bottom, rgba(var(--background-gradient-rgb), 0) calc(100% - 50px), rgba(var(--background-gradient-rgb), 1) calc(100% - 15px)); |  | ||||||
|                     z-index: 6; |                     z-index: 6; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @ -115,15 +161,15 @@ core-format-text { | |||||||
|     .core-adapted-img-container { |     .core-adapted-img-container { | ||||||
|         position: relative; |         position: relative; | ||||||
|         display: inline-block; |         display: inline-block; | ||||||
|         width: 100%; |         max-width: 100%; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     .core-image-viewer-icon { |     .core-image-viewer-icon { | ||||||
|         position: absolute; |         position: absolute; | ||||||
|         @include position(null, 10px, 10px, null); |         @include position(null, 10px, 10px, null); | ||||||
|         color: var(--black); |         color: var(--ion-text-color); | ||||||
|         border-radius: 5px; |         border-radius: 5px; | ||||||
|         background-color: var(--viewer-icon-background); |         background-color: var(--core-format-text-viewer-icon-background); | ||||||
|         display: flex; |         display: flex; | ||||||
| 
 | 
 | ||||||
|         width: var(--a11y-min-target-size); |         width: var(--a11y-min-target-size); | ||||||
| @ -141,3 +187,13 @@ core-format-text { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @keyframes loading { | ||||||
|  |     0% { | ||||||
|  |         left: -45%; | ||||||
|  |     } | ||||||
|  |     100% { | ||||||
|  |         left: 100%; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | |||||||
| @ -685,7 +685,7 @@ audio.core-media-adapt-width { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Make links clickable when inside radio or checkbox items. Style part. | // Make links clickable when inside radio or checkbox items. Style part. | ||||||
| @media (any-hover: hover) { | @media (hover: hover) { | ||||||
|     ion-item.item-multiple-inputs:hover::part(native) { |     ion-item.item-multiple-inputs:hover::part(native) { | ||||||
|         color: var(--color-hover); |         color: var(--color-hover); | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user