From 650aafc96e02943f4daf92c374b015e3dc72c6b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= <crazyserver@gmail.com> Date: Mon, 26 Apr 2021 14:14:15 +0200 Subject: [PATCH] MOBILE-3734 core: Style ion fab not direct children of ion content --- .../index/addon-mod-data-index.html | 197 +++++++++--------- .../index/addon-mod-wiki-index.html | 88 ++++---- src/core/directives/fab.ts | 14 +- src/theme/theme.base.scss | 8 + 4 files changed, 155 insertions(+), 152 deletions(-) diff --git a/src/addons/mod/data/components/index/addon-mod-data-index.html b/src/addons/mod/data/components/index/addon-mod-data-index.html index 26c2e3ec2..bf89fd47c 100644 --- a/src/addons/mod/data/components/index/addon-mod-data-index.html +++ b/src/addons/mod/data/components/index/addon-mod-data-index.html @@ -37,118 +37,115 @@ </core-navbar-buttons> <!-- Content. --> +<core-loading [hideUntil]="loaded" class="core-loading-center"> -<ion-content> - <core-loading [hideUntil]="loaded" class="core-loading-center"> + <core-course-module-description [description]="description" [component]="component" [componentId]="componentId" + contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"> + </core-course-module-description> - <core-course-module-description [description]="description" [component]="component" [componentId]="componentId" - contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"> - </core-course-module-description> + <!-- Data done in offline but not synchronized --> + <ion-card class="core-warning-card" *ngIf="hasOffline || hasOfflineRatings"> + <ion-item> + <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> + <ion-label>{{ 'core.hasdatatosync' | translate: {$a: moduleName} }}</ion-label> + </ion-item> + </ion-card> - <!-- Data done in offline but not synchronized --> - <ion-card class="core-warning-card" *ngIf="hasOffline || hasOfflineRatings"> - <ion-item> - <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> - <ion-label>{{ 'core.hasdatatosync' | translate: {$a: moduleName} }}</ion-label> - </ion-item> - </ion-card> + <ion-item class="ion-text-wrap" *ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)"> + <ion-label id="addon-data-groupslabel"> + <ng-container *ngIf="groupInfo.separateGroups">{{'core.groupsseparate' | translate }}</ng-container> + <ng-container *ngIf="groupInfo.visibleGroups">{{'core.groupsvisible' | translate }}</ng-container> + </ion-label> + <ion-select [(ngModel)]="selectedGroup" (ionChange)="setGroup(selectedGroup)" aria-labelledby="addon-data-groupslabel" + interface="action-sheet"> + <ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id"> + {{groupOpt.name}} + </ion-select-option> + </ion-select> + </ion-item> - <ion-item class="ion-text-wrap" *ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)"> - <ion-label id="addon-data-groupslabel"> - <ng-container *ngIf="groupInfo.separateGroups">{{'core.groupsseparate' | translate }}</ng-container> - <ng-container *ngIf="groupInfo.visibleGroups">{{'core.groupsvisible' | translate }}</ng-container> + <ion-card class="core-info-card" *ngIf="!access?.timeavailable && timeAvailableFrom"> + <ion-item> + <ion-icon name="fas-info-circle" slot="start"></ion-icon> + <ion-label>{{ 'addon.mod_data.notopenyet' | translate:{$a: timeAvailableFromReadable} }}</ion-label> + </ion-item> + </ion-card> + + <ion-card class="core-info-card" *ngIf="!access?.timeavailable && timeAvailableTo"> + <ion-item> + <ion-icon name="fas-info-circle" slot="start"></ion-icon> + <ion-label>{{ 'addon.mod_data.expired' | translate:{$a: timeAvailableToReadable} }}</ion-label> + </ion-item> + </ion-card> + + <ion-card class="core-info-card" *ngIf="access && access.entrieslefttoview">> + <ion-item> + <ion-icon name="fas-info-circle" slot="start"></ion-icon> + <ion-label> + {{ 'addon.mod_data.entrieslefttoaddtoview' | translate:{$a: {entrieslefttoview: access.entrieslefttoview} } }} + </ion-label> + </ion-item> + </ion-card> + + <ion-card class="core-info-card" *ngIf="access && access.entrieslefttoadd">> + <ion-item> + <ion-icon name="fas-info-circle" slot="start"></ion-icon> + <ion-label> + {{ 'addon.mod_data.entrieslefttoadd' | translate:{$a: {entriesleft: access.entrieslefttoadd} } }} + </ion-label> + </ion-item> + </ion-card> + + <!-- Reset search. --> + <ng-container *ngIf="search.searching && !isEmpty"> + <ion-item *ngIf="!foundRecordsTranslationData"> + <ion-label> + <a (click)="searchReset()">{{ 'addon.mod_data.resetsettings' | translate}}</a> </ion-label> - <ion-select [(ngModel)]="selectedGroup" (ionChange)="setGroup(selectedGroup)" aria-labelledby="addon-data-groupslabel" - interface="action-sheet"> - <ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id"> - {{groupOpt.name}} - </ion-select-option> - </ion-select> </ion-item> - <ion-card class="core-info-card" *ngIf="!access?.timeavailable && timeAvailableFrom"> - <ion-item> - <ion-icon name="fas-info-circle" slot="start"></ion-icon> - <ion-label>{{ 'addon.mod_data.notopenyet' | translate:{$a: timeAvailableFromReadable} }}</ion-label> - </ion-item> + <ion-card class="core-success-card" *ngIf="foundRecordsTranslationData" (click)="searchReset()"> + <ion-item><ion-label> + <p [innerHTML]="'addon.mod_data.foundrecords' | translate:{$a: foundRecordsTranslationData}"></p> + </ion-label></ion-item> </ion-card> + </ng-container> - <ion-card class="core-info-card" *ngIf="!access?.timeavailable && timeAvailableTo"> - <ion-item> - <ion-icon name="fas-info-circle" slot="start"></ion-icon> - <ion-label>{{ 'addon.mod_data.expired' | translate:{$a: timeAvailableToReadable} }}</ion-label> - </ion-item> - </ion-card> + <div class="addon-data-contents addon-data-entries-{{database.id}} ion-padding-horizontal" *ngIf="!isEmpty && database"> + <core-style [css]="database.csstemplate" prefix=".addon-data-entries-{{database.id}}"></core-style> - <ion-card class="core-info-card" *ngIf="access && access.entrieslefttoview">> - <ion-item> - <ion-icon name="fas-info-circle" slot="start"></ion-icon> - <ion-label> - {{ 'addon.mod_data.entrieslefttoaddtoview' | translate:{$a: {entrieslefttoview: access.entrieslefttoview} } }} - </ion-label> - </ion-item> - </ion-card> + <core-compile-html [text]="entriesRendered" [jsData]="jsData" [extraImports]="extraImports"></core-compile-html> + </div> - <ion-card class="core-info-card" *ngIf="access && access.entrieslefttoadd">> - <ion-item> - <ion-icon name="fas-info-circle" slot="start"></ion-icon> - <ion-label> - {{ 'addon.mod_data.entrieslefttoadd' | translate:{$a: {entriesleft: access.entrieslefttoadd} } }} - </ion-label> - </ion-item> - </ion-card> + <ion-grid *ngIf="search.page > 0 || hasNextPage"> + <ion-row class="ion-align-items-center"> + <ion-col *ngIf="search.page > 0"> + <ion-button expand="block" fill="outline" (click)="searchEntries(search.page - 1)"> + <ion-icon name="fas-chevron-left" slot="start"></ion-icon> + {{ 'core.previous' | translate }} + </ion-button> + </ion-col> + <ion-col *ngIf="hasNextPage"> + <ion-button expand="block" (click)="searchEntries(search.page + 1)"> + {{ 'core.next' | translate }} + <ion-icon name="fas-chevron-right" slot="end"></ion-icon> + </ion-button> + </ion-col> + </ion-row> + </ion-grid> - <!-- Reset search. --> - <ng-container *ngIf="search.searching && !isEmpty"> - <ion-item *ngIf="!foundRecordsTranslationData"> - <ion-label> - <a (click)="searchReset()">{{ 'addon.mod_data.resetsettings' | translate}}</a> - </ion-label> - </ion-item> + <core-empty-box *ngIf="isEmpty && !search.searching" icon="fas-database" [message]="'addon.mod_data.norecords' | translate"> + </core-empty-box> - <ion-card class="core-success-card" *ngIf="foundRecordsTranslationData" (click)="searchReset()"> - <ion-item><ion-label> - <p [innerHTML]="'addon.mod_data.foundrecords' | translate:{$a: foundRecordsTranslationData}"></p> - </ion-label></ion-item> - </ion-card> - </ng-container> + <core-empty-box *ngIf="isEmpty && search.searching" icon="fas-database" [message]="'addon.mod_data.nomatch' | translate" + class="core-empty-box-clickable"> + <a (click)="searchReset()">{{ 'addon.mod_data.resetsettings' | translate}}</a> + </core-empty-box> - <div class="addon-data-contents addon-data-entries-{{database.id}} ion-padding-horizontal" *ngIf="!isEmpty && database"> - <core-style [css]="database.csstemplate" prefix=".addon-data-entries-{{database.id}}"></core-style> +</core-loading> - <core-compile-html [text]="entriesRendered" [jsData]="jsData" [extraImports]="extraImports"></core-compile-html> - </div> - - <ion-grid *ngIf="search.page > 0 || hasNextPage"> - <ion-row class="ion-align-items-center"> - <ion-col *ngIf="search.page > 0"> - <ion-button expand="block" fill="outline" (click)="searchEntries(search.page - 1)"> - <ion-icon name="fas-chevron-left" slot="start"></ion-icon> - {{ 'core.previous' | translate }} - </ion-button> - </ion-col> - <ion-col *ngIf="hasNextPage"> - <ion-button expand="block" (click)="searchEntries(search.page + 1)"> - {{ 'core.next' | translate }} - <ion-icon name="fas-chevron-right" slot="end"></ion-icon> - </ion-button> - </ion-col> - </ion-row> - </ion-grid> - - <core-empty-box *ngIf="isEmpty && !search.searching" icon="fas-database" [message]="'addon.mod_data.norecords' | translate"> - </core-empty-box> - - <core-empty-box *ngIf="isEmpty && search.searching" icon="fas-database" [message]="'addon.mod_data.nomatch' | translate" - class="core-empty-box-clickable"> - <a (click)="searchReset()">{{ 'addon.mod_data.resetsettings' | translate}}</a> - </core-empty-box> - - </core-loading> - - <ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="canAdd"> - <ion-fab-button (click)="gotoAddEntries()" [attr.aria-label]="'addon.mod_data.addentries' | translate"> - <ion-icon name="fas-plus"></ion-icon> - </ion-fab-button> - </ion-fab> -</ion-content> +<ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="canAdd"> + <ion-fab-button (click)="gotoAddEntries()" [attr.aria-label]="'addon.mod_data.addentries' | translate"> + <ion-icon name="fas-plus"></ion-icon> + </ion-fab-button> +</ion-fab> diff --git a/src/addons/mod/wiki/components/index/addon-mod-wiki-index.html b/src/addons/mod/wiki/components/index/addon-mod-wiki-index.html index 4885fe49c..3466dfb92 100644 --- a/src/addons/mod/wiki/components/index/addon-mod-wiki-index.html +++ b/src/addons/mod/wiki/components/index/addon-mod-wiki-index.html @@ -46,52 +46,50 @@ </core-navbar-buttons> <!-- Content. --> -<ion-content> - <core-loading [hideUntil]="loaded" class="core-loading-center"> - <div *ngIf="description || pageIsOffline || hasOffline || pageWarning"> - <core-course-module-description [description]="description" [component]="component" [componentId]="componentId" +<core-loading [hideUntil]="loaded" class="core-loading-center"> + <div *ngIf="description || pageIsOffline || hasOffline || pageWarning"> + <core-course-module-description [description]="description" [component]="component" [componentId]="componentId" + contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"> + </core-course-module-description> + + <!-- Wiki has something offline. --> + <ion-card class="core-warning-card" *ngIf="pageIsOffline || hasOffline"> + <ion-item> + <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> + <ion-label> + <span *ngIf="pageIsOffline">{{ 'core.hasdatatosync' | translate:{$a: pageStr} }}</span> + <span *ngIf="!pageIsOffline">{{ 'core.hasdatatosync' | translate:{$a: moduleName} }}</span> + </ion-label> + </ion-item> + </ion-card> + + <!-- Page warning. --> + <ion-card class="core-warning-card" *ngIf="pageWarning"> + <ion-item> + <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> + <ion-label>{{ pageWarning }}</ion-label> + </ion-item> + </ion-card> + </div> + <div class="ion-padding addon-mod_wiki-page-content"> + <article [ngClass]="{'addon-mod_wiki-noedit': !canEdit}"> + <core-format-text *ngIf="pageContent" [component]="component" [componentId]="componentId" [text]="pageContent" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"> - </core-course-module-description> + </core-format-text> + <core-empty-box *ngIf="!pageContent" icon="fas-file-alt" [message]="'addon.mod_wiki.nocontent' | translate" + [inline]="true"> + </core-empty-box> + </article> - <!-- Wiki has something offline. --> - <ion-card class="core-warning-card" *ngIf="pageIsOffline || hasOffline"> - <ion-item> - <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> - <ion-label> - <span *ngIf="pageIsOffline">{{ 'core.hasdatatosync' | translate:{$a: pageStr} }}</span> - <span *ngIf="!pageIsOffline">{{ 'core.hasdatatosync' | translate:{$a: moduleName} }}</span> - </ion-label> - </ion-item> - </ion-card> - - <!-- Page warning. --> - <ion-card class="core-warning-card" *ngIf="pageWarning"> - <ion-item> - <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> - <ion-label>{{ pageWarning }}</ion-label> - </ion-item> - </ion-card> + <div class="ion-margin-top" *ngIf="tagsEnabled && tags.length > 0"> + <b>{{ 'core.tag.tags' | translate }}:</b> + <core-tag-list [tags]="tags"></core-tag-list> </div> - <div class="ion-padding addon-mod_wiki-page-content"> - <article [ngClass]="{'addon-mod_wiki-noedit': !canEdit}"> - <core-format-text *ngIf="pageContent" [component]="component" [componentId]="componentId" [text]="pageContent" - contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"> - </core-format-text> - <core-empty-box *ngIf="!pageContent" icon="fas-file-alt" [message]="'addon.mod_wiki.nocontent' | translate" - [inline]="true"> - </core-empty-box> - </article> + </div> +</core-loading> - <div class="ion-margin-top" *ngIf="tagsEnabled && tags.length > 0"> - <b>{{ 'core.tag.tags' | translate }}:</b> - <core-tag-list [tags]="tags"></core-tag-list> - </div> - </div> - </core-loading> - - <ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="canEdit"> - <ion-fab-button (click)="goToNewPage()" [attr.aria-label]="'addon.mod_wiki.createpage' | translate"> - <ion-icon name="fas-plus"></ion-icon> - </ion-fab-button> - </ion-fab> -</ion-content> +<ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="canEdit"> + <ion-fab-button (click)="goToNewPage()" [attr.aria-label]="'addon.mod_wiki.createpage' | translate"> + <ion-icon name="fas-plus"></ion-icon> + </ion-fab-button> +</ion-fab> diff --git a/src/core/directives/fab.ts b/src/core/directives/fab.ts index 433d16bf5..838c0b9c2 100644 --- a/src/core/directives/fab.ts +++ b/src/core/directives/fab.ts @@ -29,7 +29,7 @@ export class CoreFabDirective implements OnDestroy { protected static readonly PADDINGBOTTOM = 56; - protected element?: HTMLElement; + protected scrollElement?: HTMLElement; protected done = false; constructor(protected content: IonContent) { @@ -41,10 +41,10 @@ export class CoreFabDirective implements OnDestroy { */ async asyncInit(): Promise<void> { if (this.content) { - this.element = await this.content.getScrollElement(); + this.scrollElement = await this.content.getScrollElement(); if (!this.done) { - const bottom = parseInt(this.element.style.paddingBottom, 10) || 0; - this.element.style.paddingBottom = (bottom + CoreFabDirective.PADDINGBOTTOM) + 'px'; + const bottom = parseInt(this.scrollElement.style.paddingBottom, 10) || 0; + this.scrollElement.style.paddingBottom = (bottom + CoreFabDirective.PADDINGBOTTOM) + 'px'; this.done = true; } } @@ -54,9 +54,9 @@ export class CoreFabDirective implements OnDestroy { * Destroy component. */ ngOnDestroy(): void { - if (this.done && this.element) { - const bottom = parseInt(this.element.style.paddingBottom, 10) || 0; - this.element.style.paddingBottom = (bottom + CoreFabDirective.PADDINGBOTTOM) + 'px'; + if (this.done && this.scrollElement) { + const bottom = parseInt(this.scrollElement.style.paddingBottom, 10) || 0; + this.scrollElement.style.paddingBottom = (bottom - CoreFabDirective.PADDINGBOTTOM) + 'px'; } } diff --git a/src/theme/theme.base.scss b/src/theme/theme.base.scss index 17809b66b..e83caa979 100644 --- a/src/theme/theme.base.scss +++ b/src/theme/theme.base.scss @@ -496,3 +496,11 @@ ion-button.core-button-select { textarea:not([core-auto-rows]) { height: 200px; } + +ion-fab[core-fab] { + position: fixed; +} + +ion-content > ion-fab[core-fab] { + position: absolute; +}