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({
|
||||
selector: 'addon-block-activitymodules',
|
||||
templateUrl: 'addon-block-activitymodules.html',
|
||||
styleUrls: ['activitymodules.scss'],
|
||||
})
|
||||
export class AddonBlockActivityModulesComponent extends CoreBlockBaseComponent implements OnInit {
|
||||
|
||||
|
@ -96,16 +97,13 @@ export class AddonBlockActivityModulesComponent extends CoreBlockBaseComponent i
|
|||
// Sort the modnames alphabetically.
|
||||
modFullNames = CoreUtils.sortValues(modFullNames);
|
||||
for (const modName in modFullNames) {
|
||||
let icon: string;
|
||||
const iconModName = modName === 'resources' ? 'page' : modName;
|
||||
|
||||
if (modName === 'resources') {
|
||||
icon = await CoreCourse.getModuleIconSrc('page', modIcons['page']);
|
||||
} else {
|
||||
icon = await CoreCourseModuleDelegate.getModuleIconSrc(modName, modIcons[modName]);
|
||||
}
|
||||
const icon = await CoreCourseModuleDelegate.getModuleIconSrc(iconModName, modIcons[iconModName]);
|
||||
|
||||
this.entries.push({
|
||||
icon: icon,
|
||||
icon,
|
||||
iconModName,
|
||||
name: modFullNames[modName],
|
||||
modName,
|
||||
});
|
||||
|
@ -145,4 +143,5 @@ type AddonBlockActivityModuleEntry = {
|
|||
icon: string;
|
||||
name: string;
|
||||
modName: string;
|
||||
iconModName: string;
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</ion-item-divider>
|
||||
<core-loading [hideUntil]="loaded" [fullscreen]="false">
|
||||
<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>
|
||||
<ion-label>{{ entry.name }}</ion-label>
|
||||
</ion-item>
|
||||
|
|
|
@ -23,6 +23,7 @@ import { CoreConstants, ModPurpose } from '@/core/constants';
|
|||
import { AddonModForumIndexComponent } from '../../components/index';
|
||||
import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler';
|
||||
import { CoreCourseModuleData } from '@features/course/services/course-helper';
|
||||
import { CoreIonicColorNames } from '@singletons/colors';
|
||||
|
||||
/**
|
||||
* Handler to support forum modules.
|
||||
|
@ -58,7 +59,7 @@ export class AddonModForumModuleHandlerService extends CoreModuleHandlerBase imp
|
|||
const data = await super.getData(module, courseId);
|
||||
|
||||
if ('afterlink' in module && !!module.afterlink) {
|
||||
data.extraBadgeColor = '';
|
||||
data.extraBadgeColor = undefined;
|
||||
const match = />(\d+)[^<]+/.exec(module.afterlink);
|
||||
data.extraBadge = match ? Translate.instant('addon.mod_forum.unreadpostsnumber', { $a : match[1] }) : '';
|
||||
} else {
|
||||
|
@ -112,7 +113,7 @@ export class AddonModForumModuleHandlerService extends CoreModuleHandlerBase imp
|
|||
}
|
||||
|
||||
data.extraBadge = Translate.instant('core.loading');
|
||||
data.extraBadgeColor = 'light';
|
||||
data.extraBadgeColor = CoreIonicColorNames.DARK;
|
||||
|
||||
await CoreUtils.ignoreErrors(AddonModForum.invalidateForumData(courseId));
|
||||
|
||||
|
@ -120,7 +121,7 @@ export class AddonModForumModuleHandlerService extends CoreModuleHandlerBase imp
|
|||
// Handle unread posts.
|
||||
const forum = await AddonModForum.getForum(courseId, moduleId, { siteId });
|
||||
|
||||
data.extraBadgeColor = '';
|
||||
data.extraBadgeColor = undefined;
|
||||
data.extraBadge = forum.unreadpostscount
|
||||
? Translate.instant(
|
||||
'addon.mod_forum.unreadpostsnumber',
|
||||
|
@ -129,7 +130,7 @@ export class AddonModForumModuleHandlerService extends CoreModuleHandlerBase imp
|
|||
: '';
|
||||
} catch {
|
||||
// Ignore errors.
|
||||
data.extraBadgeColor = '';
|
||||
data.extraBadgeColor = undefined;
|
||||
data.extraBadge = '';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@
|
|||
<ion-item class="ion-text-wrap addon-mod_h5pactivity-result-table-header">
|
||||
<ion-label>
|
||||
<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.answerlabel }}</ion-col>
|
||||
</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-label>
|
||||
<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"
|
||||
contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId">
|
||||
</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 { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||
import { CoreFileHelper } from '@services/file-helper';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
||||
import { CoreTextUtils } from '@services/utils/text';
|
||||
import { CoreTimeUtils } from '@services/utils/time';
|
||||
|
@ -95,7 +96,14 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase
|
|||
|
||||
this.getResourceData(module, courseId, handlerData).then((extra) => {
|
||||
handlerData.extraBadge = extra;
|
||||
handlerData.extraBadgeColor = '';
|
||||
|
||||
return;
|
||||
}).catch(() => {
|
||||
// Ignore errors.
|
||||
});
|
||||
|
||||
this.getIconSrc(module).then((icon) => {
|
||||
handlerData.icon = icon;
|
||||
|
||||
return;
|
||||
}).catch(() => {
|
||||
|
@ -214,6 +222,36 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase
|
|||
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
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
@import "~theme/globals";
|
||||
|
||||
:host {
|
||||
--core-format-text-background-gradient-rgb: var(--background-rgb, #{$ion-item-background-rgb});
|
||||
--course-storage-max-activity-height: 120px;
|
||||
|
||||
ion-card.section ion-card-header {
|
||||
|
@ -23,8 +22,8 @@
|
|||
min-height: var(--course-storage-max-activity-height);
|
||||
position: absolute;
|
||||
@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: 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: -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(--background-gradient-rgb), 0) calc(100% - 30px), rgba(var(--background-gradient-rgb), 1) calc(100% - 20px));
|
||||
z-index: 6;
|
||||
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 { Routes } from '@angular/router';
|
||||
import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate';
|
||||
import { CoreMainMenuRoutingModule } from '@features/mainmenu/mainmenu-routing.module';
|
||||
import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module';
|
||||
import { CoreSitePreferencesRoutingModule } from '@features/settings/pages/site/site-routing';
|
||||
import { CoreSettingsDelegate } from '@features/settings/services/settings-delegate';
|
||||
import { AddonStorageManagerCourseMenuHandler } from './services/handlers/course-menu';
|
||||
import { AddonStorageManagerSettingsHandler } from './services/handlers/settings';
|
||||
|
||||
const routes: Routes = [
|
||||
|
@ -41,7 +39,6 @@ const routes: Routes = [
|
|||
provide: APP_INITIALIZER,
|
||||
multi: true,
|
||||
useValue: () => {
|
||||
CoreCourseOptionsDelegate.registerHandler(AddonStorageManagerCourseMenuHandler.instance);
|
||||
CoreSettingsDelegate.registerHandler(AddonStorageManagerSettingsHandler.instance);
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<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()"
|
||||
[attr.aria-label]="(fullscreen ? 'core.disablefullscreen' : 'core.fullscreen') | translate">
|
||||
<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;
|
||||
|
||||
if (!this.maxHeight || (window.innerWidth > 576 && window.innerHeight > 576)) {
|
||||
// Do not collapse on big screens.
|
||||
if (!this.maxHeight) {
|
||||
// Do not collapse.
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -91,9 +91,6 @@ export class CoreCollapsibleItemDirective implements OnInit {
|
|||
*/
|
||||
protected calculateHeight(): void {
|
||||
// @todo: Work on calculate this height better.
|
||||
if (!this.maxHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove max-height (if any) to calculate the real height.
|
||||
const initialMaxHeight = this.element.style.maxHeight;
|
||||
|
@ -117,7 +114,11 @@ export class CoreCollapsibleItemDirective implements OnInit {
|
|||
this.toggleExpandEnabled = 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;
|
||||
}
|
||||
|
||||
|
@ -128,6 +129,7 @@ export class CoreCollapsibleItemDirective implements OnInit {
|
|||
|
||||
const toggleText = document.createElement('span');
|
||||
toggleText.classList.add('collapsible-toggle-text');
|
||||
toggleText.classList.add('sr-only');
|
||||
toggleButton.appendChild(toggleText);
|
||||
|
||||
const expandArrow = document.createElement('span');
|
||||
|
|
|
@ -279,23 +279,28 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
*/
|
||||
protected setExpandButtonEnabled(enable: boolean): void {
|
||||
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;
|
||||
}
|
||||
|
||||
// Add expand/collapse buttons
|
||||
const toggleButton = document.createElement('ion-button');
|
||||
toggleButton.classList.add('core-format-text-toggle');
|
||||
toggleButton.classList.add('collapsible-toggle');
|
||||
toggleButton.setAttribute('fill', 'clear');
|
||||
|
||||
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);
|
||||
|
||||
const expandArrow = document.createElement('span');
|
||||
expandArrow.classList.add('core-format-text-arrow');
|
||||
expandArrow.classList.add('collapsible-toggle-arrow');
|
||||
toggleButton.appendChild(expandArrow);
|
||||
|
||||
this.element.appendChild(toggleButton);
|
||||
|
@ -313,12 +318,12 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
expand = !this.expanded;
|
||||
}
|
||||
this.expanded = expand;
|
||||
this.element.classList.toggle('core-text-format-expanded', expand);
|
||||
this.element.classList.toggle('core-text-format-collapsed', !expand);
|
||||
this.element.classList.toggle('collapsible-expanded', expand);
|
||||
this.element.classList.toggle('collapsible-collapsed', !expand);
|
||||
this.element.style.maxHeight = expand ? '' : this.maxHeight + 'px';
|
||||
|
||||
const toggleButton = this.element.querySelector('ion-button.core-format-text-toggle');
|
||||
const toggleText = toggleButton?.querySelector('.core-format-text-toggle-text');
|
||||
const toggleButton = this.element.querySelector('ion-button.collapsible-toggle');
|
||||
const toggleText = toggleButton?.querySelector('.collapsible-toggle-text');
|
||||
if (!toggleButton || !toggleText) {
|
||||
return;
|
||||
}
|
||||
|
@ -396,8 +401,7 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
this.element.classList.add('core-disable-media-adapt');
|
||||
|
||||
this.contentSpan.innerHTML = ''; // Remove current contents.
|
||||
if (this.maxHeight && result.div.innerHTML != '' &&
|
||||
(window.innerWidth < 576 || window.innerHeight < 576)) { // Don't collapse in big screens.
|
||||
if (this.maxHeight && result.div.innerHTML != '') {
|
||||
|
||||
// Move the children to the current element to be able to calculate the height.
|
||||
CoreDomUtils.moveChildren(result.div, this.contentSpan);
|
||||
|
|
|
@ -33,16 +33,35 @@ ion-item.item.item-current {
|
|||
--background: var(--primary);
|
||||
--color: var(--primary-contrast);
|
||||
border: 0;
|
||||
|
||||
ion-badge {
|
||||
border: 1px solid var(--primary-contrast);
|
||||
}
|
||||
|
||||
::ng-deep ion-icon {
|
||||
color: var(--primary-contrast);
|
||||
}
|
||||
}
|
||||
|
||||
ion-icon.restricted {
|
||||
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 *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-label>
|
||||
{{ rule.rulevalue.description }}
|
||||
</ion-label>
|
||||
</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-label>
|
||||
{{ rule.rulevalue.description }}
|
||||
</ion-label>
|
||||
</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-label>
|
||||
{{ rule.rulevalue.description }}
|
||||
|
@ -29,7 +32,7 @@
|
|||
</ng-container>
|
||||
|
||||
<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-label>
|
||||
{{ 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({
|
||||
selector: 'core-course-module-completion',
|
||||
templateUrl: 'core-course-module-completion.html',
|
||||
styleUrls: ['module-completion.scss'],
|
||||
})
|
||||
export class CoreCourseModuleCompletionComponent extends CoreCourseModuleCompletionBaseComponent {
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
{{ 'core.course' | translate}}
|
||||
</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>
|
||||
</p>
|
||||
</ion-label>
|
||||
|
@ -58,7 +58,7 @@
|
|||
<ion-item lines="full" class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<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 }}
|
||||
</h2>
|
||||
</ion-label>
|
||||
|
@ -81,7 +81,7 @@
|
|||
</ion-item>
|
||||
<ion-button fill="outline" expand="block" *ngIf="canPrefetch && displayOptions.displayPrefetch" class="ion-text-wrap"
|
||||
(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-label>
|
||||
{{ 'core.download' | translate }}
|
||||
|
|
|
@ -249,7 +249,13 @@ export class CoreCourseModuleSummaryComponent implements OnInit, OnDestroy {
|
|||
* Fetch course.
|
||||
*/
|
||||
protected async fetchCourse(): Promise<void> {
|
||||
this.course = await CoreCourses.getUserCourse(this.courseId, true);
|
||||
// Fix that.
|
||||
try {
|
||||
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>
|
||||
|
||||
<!-- 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">
|
||||
</core-course-module-completion>
|
||||
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
|
||||
:host {
|
||||
--horizontal-margin: 10px;
|
||||
--vertical-margin: 10px;
|
||||
|
||||
ion-card {
|
||||
margin-left: var(--horizontal-margin);
|
||||
margin-right: var(--horizontal-margin);
|
||||
margin: var(--vertical-margin) var(--horizontal-margin);
|
||||
}
|
||||
|
||||
ion-item {
|
||||
--padding-start: 12px;
|
||||
}
|
||||
|
||||
ion-item.core-module-main-item {
|
||||
|
@ -84,4 +88,7 @@
|
|||
@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,
|
||||
CoreCourseSection,
|
||||
} 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 {
|
||||
CoreCourseModulePrefetchDelegate,
|
||||
|
@ -55,6 +55,8 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
|||
showManualCompletion = false; // Whether to show manual completion when completion conditions are disabled.
|
||||
prefetchStatusIcon = ''; // Module prefetch status icon.
|
||||
prefetchStatusText = ''; // Module prefetch status text.
|
||||
autoCompletionTodo = false;
|
||||
|
||||
protected prefetchHandler?: CoreCourseModulePrefetchHandler;
|
||||
|
||||
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;
|
||||
|
||||
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.module.description ||
|
||||
(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.module.isStealth) ||
|
||||
(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>
|
||||
<ion-content>
|
||||
<ion-refresher slot="fixed" [disabled]="!dataLoaded || !displayRefresher" (ionRefresh)="doRefresh($event.target)">
|
||||
|
|
|
@ -29,7 +29,6 @@ import {
|
|||
} from '@features/course/services/course-helper';
|
||||
import { CoreCourseFormatDelegate } from '@features/course/services/format-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 { CoreCourseFormatComponent } from '../../components/course-format/course-format';
|
||||
import {
|
||||
|
@ -54,7 +53,6 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
|||
sections?: CoreCourseSection[];
|
||||
sectionId?: number;
|
||||
sectionNumber?: number;
|
||||
courseMenuHandlers: CoreCourseOptionsMenuHandlerToDisplay[] = [];
|
||||
dataLoaded = false;
|
||||
downloadCourseEnabled = false;
|
||||
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 {
|
||||
this.isDestroyed = true;
|
||||
|
|
|
@ -26,14 +26,23 @@
|
|||
<ng-container *ngIf="course">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<p *ngIf="course.categoryname">
|
||||
<core-format-text [text]="course.categoryname" contextLevel="coursecat" [contextInstanceId]="course.categoryid">
|
||||
<p *ngIf="course.displayname && course.shortname && course.fullname != course.displayname"
|
||||
class="core-course-shortname">
|
||||
<core-format-text [text]="course.shortname" contextLevel="course" [contextInstanceId]="course.id">
|
||||
</core-format-text>
|
||||
</p>
|
||||
<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>
|
||||
</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">
|
||||
<core-progress-bar [progress]="progress" a11yText="core.course.aria:sectionprogress">
|
||||
|
|
|
@ -21,10 +21,6 @@
|
|||
<img [src]="imageThumb" core-external-content alt="" />
|
||||
</ion-avatar>
|
||||
<ion-label>
|
||||
<p *ngIf="category">
|
||||
<core-format-text [text]="category" contextLevel="coursecat" [contextInstanceId]="course!.categoryid">
|
||||
</core-format-text>
|
||||
</p>
|
||||
<h1>{{ title }}</h1>
|
||||
<div class="core-course-progress" *ngIf="progress !== undefined">
|
||||
<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.
|
||||
this.title = CoreCourseFormatDelegate.getCourseTitle(this.course);
|
||||
this.category = 'categoryname' in this.course ? this.course.categoryname : '';
|
||||
|
||||
if ('overviewfiles' in this.course) {
|
||||
this.imageThumb = this.course.overviewfiles?.[0]?.fileurl;
|
||||
|
|
|
@ -25,6 +25,7 @@ import { CoreSites } from '@services/sites';
|
|||
import { makeSingleton } from '@singletons';
|
||||
import { CoreCourseModuleData } from './course-helper';
|
||||
import { CoreNavigationOptions } from '@services/navigator';
|
||||
import { CoreIonicColorNames } from '@singletons/colors';
|
||||
|
||||
/**
|
||||
* Interface that all course module handlers must implement.
|
||||
|
@ -146,7 +147,7 @@ export interface CoreCourseModuleHandlerData {
|
|||
/**
|
||||
* 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.
|
||||
|
|
|
@ -70,7 +70,8 @@
|
|||
class="core-course-category core-course-additional-info ion-text-nowrap">
|
||||
<span class="sr-only">{{ 'core.courses.aria:coursecategory' | translate }}</span>
|
||||
<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-chip>
|
||||
</div>
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
form .core-username.ios {
|
||||
--inner-border-width: 0 0 1px 0;
|
||||
}
|
||||
|
||||
form .item,
|
||||
form .item ion-label {
|
||||
--background: var(--core-login-input-background);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<core-loading [hideUntil]="userLoaded">
|
||||
<ion-list *ngIf="user">
|
||||
<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()"
|
||||
[attr.aria-label]="'core.user.newpicture' | translate" fill="clear" color="dark">
|
||||
<ion-icon slot="icon-only" name="fas-pen" aria-hidden="true"></ion-icon>
|
||||
|
|
|
@ -4,13 +4,11 @@
|
|||
|
||||
core-format-text {
|
||||
--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-loader-shine: 251,251,251;
|
||||
}
|
||||
|
||||
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-loader-shine: 90,90,90;
|
||||
}
|
||||
|
@ -51,12 +49,12 @@ core-format-text {
|
|||
display: inline;
|
||||
}
|
||||
|
||||
.core-format-text-toggle {
|
||||
.collapsible-toggle {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.core-format-text-toggle {
|
||||
.collapsible-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -84,81 +82,21 @@ core-format-text {
|
|||
}
|
||||
|
||||
// This is to allow clicks in radio/checkbox content.
|
||||
&.core-text-formatted {
|
||||
&.collapsible-enabled {
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
|
||||
.core-format-text-toggle {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@include collapsible-item();
|
||||
}
|
||||
}
|
||||
|
||||
@if ($core-format-text-never-shorten) {
|
||||
&[maxHeight],
|
||||
&[ng-reflect-max-height] {
|
||||
&.core-text-formatted.core-text-format-expanded {
|
||||
&.collapsible-enabled.collapsible-expanded {
|
||||
max-height: none !important;
|
||||
|
||||
.core-format-text-toggle {
|
||||
.collapsible-toggle {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
|
|
@ -219,9 +219,84 @@
|
|||
--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.
|
||||
@function get_brightness($color) {
|
||||
|
|
|
@ -164,6 +164,9 @@ ion-header {
|
|||
--ion-toolbar-color: var(--core-header-toolbar-color);
|
||||
--border-radius: var(--huge-radius);
|
||||
}
|
||||
ion-back-button::part(text) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.button.button-clear,
|
||||
.button.button-solid {
|
||||
|
@ -813,6 +816,7 @@ ion-card {
|
|||
border-color: var(--border-color);
|
||||
box-shadow: var(--box-shadow);
|
||||
border-radius: var(--border-radius);
|
||||
margin: var(--ion-card-vertical-margin) var(--ion-card-horizontal-margin);
|
||||
|
||||
ion-item:only-child {
|
||||
--inner-border-width: 0px;
|
||||
|
@ -983,6 +987,12 @@ ion-chip {
|
|||
min-height: 24px;
|
||||
height: auto;
|
||||
|
||||
// Chips are not currently clickable.
|
||||
&.ion-activatable {
|
||||
cursor: auto;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.ion-color {
|
||||
background: var(--ion-color-tint);
|
||||
&.chip-outline {
|
||||
|
@ -1145,6 +1155,10 @@ ion-item.item-lines-inset {
|
|||
--border-width: 0px;
|
||||
}
|
||||
|
||||
ion-item.item-input.ios {
|
||||
--inner-border-width: 0 0 1px 0;
|
||||
}
|
||||
|
||||
// Fake item.
|
||||
div.fake-ion-item {
|
||||
position: relative;
|
||||
|
@ -1425,77 +1439,7 @@ ion-grid.core-no-grid > ion-row {
|
|||
}
|
||||
|
||||
[collapsible-item] {
|
||||
--collapsible-display-toggle: none;
|
||||
--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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@include collapsible-item();
|
||||
}
|
||||
|
||||
ion-header.no-title {
|
||||
|
|
|
@ -97,6 +97,10 @@
|
|||
--core-combobox-color: var(--text-color);
|
||||
--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-text-color: var(--white);
|
||||
--core-login-input-background: var(--core-login-background);
|
||||
|
|
|
@ -88,6 +88,8 @@
|
|||
--subdued-text-color: var(--gray-700);
|
||||
|
||||
--ion-card-color: var(--text-color);
|
||||
--ion-card-vertical-margin: 10px;
|
||||
--ion-card-horizontal-margin: 10px;
|
||||
ion-card {
|
||||
--border-width: 1px;
|
||||
--border-style: solid;
|
||||
|
@ -286,6 +288,12 @@
|
|||
--selected-item-color: var(--primary);
|
||||
--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-text-color: var(--gray-900);
|
||||
--core-login-input-background: var(--white);
|
||||
|
|
Loading…
Reference in New Issue