diff --git a/src/addons/calendar/calendar-common.scss b/src/addons/calendar/calendar-common.scss index 3691d26f2..3746e7872 100644 --- a/src/addons/calendar/calendar-common.scss +++ b/src/addons/calendar/calendar-common.scss @@ -9,6 +9,12 @@ color: white; border-radius: 50%; padding: 0.7rem; + --margin-vertical: 12px; + --margin-end: 12px; + margin-top: var(--margin-vertical); + margin-bottom: var(--margin-vertical); + @include margin-horizontal(null, var(--margin-end)); + } @each $category, $value in $calendar-event-category-colors { diff --git a/src/addons/calendar/components/calendar/calendar.ts b/src/addons/calendar/components/calendar/calendar.ts index 64cd0807d..4f984d83c 100644 --- a/src/addons/calendar/components/calendar/calendar.ts +++ b/src/addons/calendar/components/calendar/calendar.ts @@ -496,7 +496,6 @@ class AddonCalendarMonthSlidesItemsManagerSource extends CoreSwipeSlidesDynamicI const weeks = result.weeks as AddonCalendarWeek[]; const currentDay = new Date().getDate(); const currentTime = CoreTimeUtils.timestamp(); - let isPast = true; const preloadedMonth: PreloadedMonth = { ...month, @@ -523,8 +522,7 @@ class AddonCalendarMonthSlidesItemsManagerSource extends CoreSwipeSlidesDynamicI if (preloadedMonth.isCurrentMonth) { day.istoday = day.mday == currentDay; - day.ispast = isPast && !day.istoday; - isPast = day.ispast; + day.ispast = preloadedMonth.isPastMonth || day.mday < currentDay; if (day.istoday) { day.eventsFormated?.forEach((event) => { diff --git a/src/addons/calendar/components/reminder-time-modal/reminder-time-modal.html b/src/addons/calendar/components/reminder-time-modal/reminder-time-modal.html index 052241aa9..1071b92d9 100644 --- a/src/addons/calendar/components/reminder-time-modal/reminder-time-modal.html +++ b/src/addons/calendar/components/reminder-time-modal/reminder-time-modal.html @@ -34,7 +34,7 @@ - +
diff --git a/src/addons/calendar/components/reminder-time-modal/reminder-time-modal.ts b/src/addons/calendar/components/reminder-time-modal/reminder-time-modal.ts index 871530664..1a10a9c27 100644 --- a/src/addons/calendar/components/reminder-time-modal/reminder-time-modal.ts +++ b/src/addons/calendar/components/reminder-time-modal/reminder-time-modal.ts @@ -15,7 +15,6 @@ import { AddonCalendar, AddonCalendarReminderUnits, AddonCalendarValueAndUnit } from '@addons/calendar/services/calendar'; import { Component, Input, OnInit } from '@angular/core'; import { CoreDomUtils } from '@services/utils/dom'; -import { CoreUtils } from '@services/utils/utils'; import { ModalController } from '@singletons'; /** @@ -166,11 +165,9 @@ export class AddonCalendarReminderTimeModalComponent implements OnInit { this.radioValue = 'custom'; - await CoreUtils.nextTick(); - - const target = ev.target; - if (target && 'focus' in target) { - target.focus(); + const target = ev.target; + if (target) { + CoreDomUtils.focusElement(target); } } diff --git a/src/core/directives/auto-focus.ts b/src/core/directives/auto-focus.ts index 9a37a208f..d84252ad6 100644 --- a/src/core/directives/auto-focus.ts +++ b/src/core/directives/auto-focus.ts @@ -49,19 +49,7 @@ export class CoreAutoFocusDirective implements AfterViewInit { await CoreDom.waitToBeInDOM(this.element); - let focusElement = this.element; - - if ('getInputElement' in focusElement) { - // If it's an Ionic element get the right input to use. - focusElement.componentOnReady && await focusElement.componentOnReady(); - focusElement = await focusElement.getInputElement(); - } - - if (!focusElement) { - return; - } - - CoreDomUtils.focusElement(focusElement); + CoreDomUtils.focusElement(this.element); } diff --git a/src/core/directives/collapsible-footer.ts b/src/core/directives/collapsible-footer.ts index 4a44fa0b9..73e9dbd5a 100644 --- a/src/core/directives/collapsible-footer.ts +++ b/src/core/directives/collapsible-footer.ts @@ -50,11 +50,10 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy { protected contentScrollListener?: EventListener; protected endContentScrollListener?: EventListener; protected resizeListener?: CoreEventObserver; - protected domPromise?: CoreCancellablePromise; + protected slotPromise?: CoreCancellablePromise; constructor(el: ElementRef, protected ionContent: IonContent) { this.element = el.nativeElement; - this.element.setAttribute('slot', 'fixed'); // Just in case somebody forgets to add it. } /** @@ -63,9 +62,9 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy { async ngOnInit(): Promise { // Only if not present or explicitly falsy it will be false. this.appearOnBottom = !CoreUtils.isFalseOrZero(this.appearOnBottom); - this.domPromise = CoreDom.waitToBeInDOM(this.element); + this.slotPromise = CoreDom.slotOnContent(this.element); - await this.domPromise; + await this.slotPromise; await this.waitLoadingsDone(); await this.waitFormatTextsRendered(); @@ -229,7 +228,7 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy { } this.resizeListener?.off(); - this.domPromise?.cancel(); + this.slotPromise?.cancel(); } } diff --git a/src/core/directives/fab.ts b/src/core/directives/fab.ts index 90f700fc5..fe18f8274 100644 --- a/src/core/directives/fab.ts +++ b/src/core/directives/fab.ts @@ -31,19 +31,18 @@ export class CoreFabDirective implements OnInit, OnDestroy { protected element: HTMLElement; protected content?: HTMLIonContentElement | null; protected initialPaddingBottom = 0; - protected domPromise?: CoreCancellablePromise; + protected slotPromise?: CoreCancellablePromise; constructor(el: ElementRef) { this.element = el.nativeElement; - this.element.setAttribute('slot', 'fixed'); } /** * @inheritdoc */ async ngOnInit(): Promise { - this.domPromise = CoreDom.waitToBeInDOM(this.element); - await this.domPromise; + this.slotPromise = CoreDom.slotOnContent(this.element); + await this.slotPromise; this.content = this.element.closest('ion-content'); @@ -70,12 +69,6 @@ export class CoreFabDirective implements OnInit, OnDestroy { } const initialHeight = this.element.getBoundingClientRect().height || 56; - - // Move element to the nearest ion-content if it's not the parent - if (this.element.parentElement?.nodeName != 'ION-CONTENT') { - this.content.appendChild(this.element); - } - this.content.style.setProperty('--padding-bottom', this.initialPaddingBottom + initialHeight + 'px'); } @@ -86,7 +79,7 @@ export class CoreFabDirective implements OnInit, OnDestroy { if (this.content) { this.content.style.setProperty('--padding-bottom', this.initialPaddingBottom + 'px'); } - this.domPromise?.cancel(); + this.slotPromise?.cancel(); } } diff --git a/src/core/features/block/components/side-blocks-button/side-blocks-button.ts b/src/core/features/block/components/side-blocks-button/side-blocks-button.ts index e8b369c29..e748b67aa 100644 --- a/src/core/features/block/components/side-blocks-button/side-blocks-button.ts +++ b/src/core/features/block/components/side-blocks-button/side-blocks-button.ts @@ -12,9 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, ElementRef, Input, ViewChild } from '@angular/core'; +import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { CoreCancellablePromise } from '@classes/cancellable-promise'; import { CoreUserTours, CoreUserToursAlignment, CoreUserToursSide } from '@features/usertours/services/user-tours'; import { CoreDomUtils } from '@services/utils/dom'; +import { CoreDom } from '@singletons/dom'; import { CoreBlockSideBlocksTourComponent } from '../side-blocks-tour/side-blocks-tour'; import { CoreBlockSideBlocksComponent } from '../side-blocks/side-blocks'; @@ -26,11 +28,25 @@ import { CoreBlockSideBlocksComponent } from '../side-blocks/side-blocks'; templateUrl: 'side-blocks-button.html', styleUrls: ['side-blocks-button.scss'], }) -export class CoreBlockSideBlocksButtonComponent { +export class CoreBlockSideBlocksButtonComponent implements OnInit, OnDestroy { @Input() courseId!: number; @ViewChild('button', { read: ElementRef }) button?: ElementRef; + protected element: HTMLElement; + protected slotPromise?: CoreCancellablePromise; + + constructor(el: ElementRef) { + this.element = el.nativeElement; + } + + /** + * @inheritdoc + */ + async ngOnInit(): Promise { + this.slotPromise = CoreDom.slotOnContent(this.element); + } + /** * Open side blocks. */ @@ -62,4 +78,11 @@ export class CoreBlockSideBlocksButtonComponent { }); } + /** + * @inheritdoc + */ + ngOnDestroy(): void { + this.slotPromise?.cancel(); + } + } diff --git a/src/core/features/course/format/singleactivity/components/core-course-format-single-activity.html b/src/core/features/course/format/singleactivity/components/core-course-format-single-activity.html index 68eedcebf..aa42eeadb 100644 --- a/src/core/features/course/format/singleactivity/components/core-course-format-single-activity.html +++ b/src/core/features/course/format/singleactivity/components/core-course-format-single-activity.html @@ -1,4 +1,4 @@ - + diff --git a/src/core/features/courses/pages/dashboard/dashboard.html b/src/core/features/courses/pages/dashboard/dashboard.html index 1e9771413..38dc1f17e 100644 --- a/src/core/features/courses/pages/dashboard/dashboard.html +++ b/src/core/features/courses/pages/dashboard/dashboard.html @@ -15,7 +15,7 @@ - + diff --git a/src/core/features/login/pages/credentials/credentials.html b/src/core/features/login/pages/credentials/credentials.html index bac39ab1b..e8703bdfa 100644 --- a/src/core/features/login/pages/credentials/credentials.html +++ b/src/core/features/login/pages/credentials/credentials.html @@ -46,7 +46,7 @@ diff --git a/src/core/features/login/pages/reconnect/reconnect.html b/src/core/features/login/pages/reconnect/reconnect.html index 7854dfa37..8c6b71f6e 100644 --- a/src/core/features/login/pages/reconnect/reconnect.html +++ b/src/core/features/login/pages/reconnect/reconnect.html @@ -51,20 +51,15 @@ - - - - - {{ 'core.login.cancel' | translate }} - - - - - {{ 'core.login.loginbutton' | translate }} - - - - +
+ + {{ 'core.login.cancel' | translate }} + + +
{{ 'core.login.or' | translate }}
diff --git a/src/core/features/sitehome/pages/index/index.html b/src/core/features/sitehome/pages/index/index.html index 97f7ba85a..f7c3d0856 100644 --- a/src/core/features/sitehome/pages/index/index.html +++ b/src/core/features/sitehome/pages/index/index.html @@ -45,7 +45,7 @@
- + diff --git a/src/core/services/utils/dom.ts b/src/core/services/utils/dom.ts index b42da0973..9d2bc991a 100644 --- a/src/core/services/utils/dom.ts +++ b/src/core/services/utils/dom.ts @@ -336,12 +336,22 @@ export class CoreDomUtilsProvider { /** * Focus an element and open keyboard. * - * @param focusElement HTML element to focus. + * @param element HTML element to focus. */ - async focusElement(focusElement: HTMLElement): Promise { + async focusElement( + element: HTMLIonInputElement | HTMLIonTextareaElement | HTMLIonSearchbarElement | HTMLElement, + ): Promise { let retries = 10; - if (!focusElement.focus) { + let focusElement = element; + + if ('getInputElement' in focusElement) { + // If it's an Ionic element get the right input to use. + focusElement.componentOnReady && await focusElement.componentOnReady(); + focusElement = await focusElement.getInputElement(); + } + + if (!focusElement || !focusElement.focus) { throw new CoreError('Element to focus cannot be focused'); } diff --git a/src/core/singletons/dom.ts b/src/core/singletons/dom.ts index 7bb8be177..fdd0dd9d0 100644 --- a/src/core/singletons/dom.ts +++ b/src/core/singletons/dom.ts @@ -205,6 +205,38 @@ export class CoreDom { return CoreDom.scrollToElement(container, '.core-input-error'); } + /** + * Move element to content so it can be slotted. + * + * @param element HTML Element. + * @param slot Slot name. + * @return Promise resolved when done. + */ + static slotOnContent(element: HTMLElement, slot = 'fixed'): CoreCancellablePromise { + element.setAttribute('slot', slot); + if (element.parentElement?.nodeName === 'ION-CONTENT') { + return CoreCancellablePromise.resolve(); + } + + const domPromise = CoreDom.waitToBeInDOM(element); + + return new CoreCancellablePromise( + async (resolve) => { + await domPromise; + + // Move element to the nearest ion-content if it's not the parent + if (element.parentElement?.nodeName !== 'ION-CONTENT') { + element.closest('ion-content')?.appendChild(element); + } + + resolve(); + }, + () => { + domPromise.cancel(); + }, + ); + } + /** * Wait an element to be added to the root DOM. *