|
@ -2,6 +2,10 @@ ion-app.app-root addon-mod-forum-post .addon-mod_forum-post {
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
border-bottom: 1px solid $list-md-border-color;
|
border-bottom: 1px solid $list-md-border-color;
|
||||||
|
|
||||||
|
@include darkmode() {
|
||||||
|
background-color: $core-dark-item-bg-color;
|
||||||
|
}
|
||||||
|
|
||||||
.addon-forum-star {
|
.addon-forum-star {
|
||||||
color: $core-star-color;
|
color: $core-star-color;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ ion-app.app-root page-addon-mod-forum-discussion {
|
||||||
.highlight .card-header .item {
|
.highlight .card-header .item {
|
||||||
background-color: $gray-lighter;
|
background-color: $gray-lighter;
|
||||||
@include darkmode() {
|
@include darkmode() {
|
||||||
background-color: $black;
|
background-color: $gray-dark;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import { CoreSitesProvider } from '@providers/sites';
|
||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader';
|
import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader';
|
||||||
|
import { CoreUserProvider } from '@core/user/providers/user';
|
||||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
import { CoreRatingProvider, CoreRatingInfo } from '@core/rating/providers/rating';
|
import { CoreRatingProvider, CoreRatingInfo } from '@core/rating/providers/rating';
|
||||||
import { CoreRatingOfflineProvider } from '@core/rating/providers/offline';
|
import { CoreRatingOfflineProvider } from '@core/rating/providers/offline';
|
||||||
|
@ -57,7 +58,7 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
||||||
isOnline: boolean;
|
isOnline: boolean;
|
||||||
isSplitViewOn: boolean;
|
isSplitViewOn: boolean;
|
||||||
postHasOffline: boolean;
|
postHasOffline: boolean;
|
||||||
sort: SortType = 'flat-oldest';
|
sort: SortType = 'nested';
|
||||||
trackPosts: boolean;
|
trackPosts: boolean;
|
||||||
replyData = {
|
replyData = {
|
||||||
replyingTo: 0,
|
replyingTo: 0,
|
||||||
|
@ -96,19 +97,20 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
||||||
constructor(navParams: NavParams,
|
constructor(navParams: NavParams,
|
||||||
network: Network,
|
network: Network,
|
||||||
zone: NgZone,
|
zone: NgZone,
|
||||||
private appProvider: CoreAppProvider,
|
protected appProvider: CoreAppProvider,
|
||||||
private eventsProvider: CoreEventsProvider,
|
protected eventsProvider: CoreEventsProvider,
|
||||||
private sitesProvider: CoreSitesProvider,
|
protected sitesProvider: CoreSitesProvider,
|
||||||
private domUtils: CoreDomUtilsProvider,
|
protected domUtils: CoreDomUtilsProvider,
|
||||||
private utils: CoreUtilsProvider,
|
protected utils: CoreUtilsProvider,
|
||||||
private translate: TranslateService,
|
protected translate: TranslateService,
|
||||||
private uploaderProvider: CoreFileUploaderProvider,
|
protected uploaderProvider: CoreFileUploaderProvider,
|
||||||
private forumProvider: AddonModForumProvider,
|
protected forumProvider: AddonModForumProvider,
|
||||||
private forumOffline: AddonModForumOfflineProvider,
|
protected forumOffline: AddonModForumOfflineProvider,
|
||||||
private forumHelper: AddonModForumHelperProvider,
|
protected forumHelper: AddonModForumHelperProvider,
|
||||||
private forumSync: AddonModForumSyncProvider,
|
protected forumSync: AddonModForumSyncProvider,
|
||||||
private ratingOffline: CoreRatingOfflineProvider,
|
protected ratingOffline: CoreRatingOfflineProvider,
|
||||||
@Optional() private svComponent: CoreSplitViewComponent,
|
protected userProvider: CoreUserProvider,
|
||||||
|
@Optional() protected svComponent: CoreSplitViewComponent,
|
||||||
protected navCtrl: NavController) {
|
protected navCtrl: NavController) {
|
||||||
this.courseId = navParams.get('courseId');
|
this.courseId = navParams.get('courseId');
|
||||||
this.cmId = navParams.get('cmId');
|
this.cmId = navParams.get('cmId');
|
||||||
|
@ -134,7 +136,29 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
||||||
* View loaded.
|
* View loaded.
|
||||||
*/
|
*/
|
||||||
ionViewDidLoad(): void {
|
ionViewDidLoad(): void {
|
||||||
this.sitesProvider.getCurrentSite().getLocalSiteConfig('AddonModForumDiscussionSort', this.sort).then((value) => {
|
this.sitesProvider.getCurrentSite().getLocalSiteConfig('AddonModForumDiscussionSort').catch(() => {
|
||||||
|
this.userProvider.getUserPreference('forum_displaymode').catch(() => {
|
||||||
|
// Ignore errors.
|
||||||
|
}).then((value) => {
|
||||||
|
const sortValue = value && parseInt(value, 10);
|
||||||
|
|
||||||
|
switch (sortValue) {
|
||||||
|
case 1:
|
||||||
|
this.sort = 'flat-oldest';
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
this.sort = 'flat-newest';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
this.sort = 'nested';
|
||||||
|
break;
|
||||||
|
case 2: // Threaded not implemented.
|
||||||
|
default:
|
||||||
|
// Not set, use default sort.
|
||||||
|
// @TODO add fallback to $CFG->forum_displaymode.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).then((value) => {
|
||||||
this.sort = value;
|
this.sort = value;
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.fetchPosts(true, false, true).then(() => {
|
this.fetchPosts(true, false, true).then(() => {
|
||||||
|
|
|
@ -51,8 +51,8 @@
|
||||||
<h3>{{ 'addon.mod_scorm.gradeforattempt' | translate }} {{attempt.number}}</h3>
|
<h3>{{ 'addon.mod_scorm.gradeforattempt' | translate }} {{attempt.number}}</h3>
|
||||||
<p item-content *ngIf="attempt.grade != -1">{{ attempt.grade }}</p>
|
<p item-content *ngIf="attempt.grade != -1">{{ attempt.grade }}</p>
|
||||||
<p item-content *ngIf="attempt.grade == -1">{{ 'addon.mod_scorm.cannotcalculategrade' | translate }}</p>
|
<p item-content *ngIf="attempt.grade == -1">{{ 'addon.mod_scorm.cannotcalculategrade' | translate }}</p>
|
||||||
<p item-content *ngIf="scorm.maxattempt == 0 || attempt.number <= scorm.maxattempt">{{ 'addon.mod_scorm.offlineattemptnote' | translate }}</p>
|
<p *ngIf="scorm.maxattempt == 0 || attempt.number <= scorm.maxattempt">{{ 'addon.mod_scorm.offlineattemptnote' | translate }}</p>
|
||||||
<p item-content *ngIf="scorm.maxattempt != 0 && attempt.number > scorm.maxattempt">{{ 'addon.mod_scorm.offlineattemptovermax' | translate }}</p>
|
<p *ngIf="scorm.maxattempt != 0 && attempt.number > scorm.maxattempt">{{ 'addon.mod_scorm.offlineattemptovermax' | translate }}</p>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item text-wrap *ngIf="scorm.displayattemptstatus && scorm.gradeMethodReadable">
|
<ion-item text-wrap *ngIf="scorm.displayattemptstatus && scorm.gradeMethodReadable">
|
||||||
<h3>{{ 'addon.mod_scorm.grademethod' | translate }}</h3>
|
<h3>{{ 'addon.mod_scorm.grademethod' | translate }}</h3>
|
||||||
|
@ -95,9 +95,9 @@
|
||||||
<!-- If data shown doesn't belong to last attempt, show a warning. -->
|
<!-- If data shown doesn't belong to last attempt, show a warning. -->
|
||||||
<p *ngIf="attemptToContinue">{{ 'addon.mod_scorm.dataattemptshown' | translate:{number: attemptToContinue} }}</p>
|
<p *ngIf="attemptToContinue">{{ 'addon.mod_scorm.dataattemptshown' | translate:{number: attemptToContinue} }}</p>
|
||||||
<p>{{ currentOrganization.title }}</p>
|
<p>{{ currentOrganization.title }}</p>
|
||||||
<div *ngFor="let sco of toc" class="core-padding-{{sco.level}}">
|
<div *ngFor="let sco of toc" class="core-padding-{{sco.level}} addon-mod_scorm-type-{{sco.scormtype}}">
|
||||||
<p *ngIf="sco.isvisible">
|
<p *ngIf="sco.isvisible">
|
||||||
<img [src]="sco.image.url" [alt]="sco.image.description" />
|
<core-icon [name]="sco.image.icon" [label]="sco.image.description" item-start></core-icon>
|
||||||
<a *ngIf="sco.prereq && sco.launch" (click)="open($event, sco.id)"><core-format-text [text]="sco.title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"></core-format-text></a>
|
<a *ngIf="sco.prereq && sco.launch" (click)="open($event, sco.id)"><core-format-text [text]="sco.title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"></core-format-text></a>
|
||||||
<span *ngIf="!sco.prereq || !sco.launch"><core-format-text [text]="sco.title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"></core-format-text></span>
|
<span *ngIf="!sco.prereq || !sco.launch"><core-format-text [text]="sco.title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"></core-format-text></span>
|
||||||
<span *ngIf="accessInfo && accessInfo.canviewscores && sco.score_raw">({{ 'addon.mod_scorm.score' | translate }}: {{sco.score_raw}})</span>
|
<span *ngIf="accessInfo && accessInfo.canviewscores && sco.score_raw">({{ 'addon.mod_scorm.score' | translate }}: {{sco.score_raw}})</span>
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
ion-app.app-root addon-mod-scorm-index {
|
ion-app.app-root addon-mod-scorm-index,
|
||||||
|
ion-app.app-root page-addon-mod-scorm-toc {
|
||||||
.addon-mod_scorm-toc {
|
.addon-mod_scorm-toc {
|
||||||
img {
|
// Hide all non sco icons using css to maintain padding.
|
||||||
width: auto;
|
ion-icon {
|
||||||
display: inline;
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addon-mod_scorm-type-sco ion-icon {
|
||||||
|
opacity: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<nav>
|
<nav>
|
||||||
<ion-list>
|
<ion-list class="addon-mod_scorm-toc">
|
||||||
<ion-item text-wrap *ngIf="attemptToContinue">
|
<ion-item text-wrap *ngIf="attemptToContinue">
|
||||||
<p>{{ 'addon.mod_scorm.dataattemptshown' | translate:{number: attemptToContinue} }}</p>
|
<p>{{ 'addon.mod_scorm.dataattemptshown' | translate:{number: attemptToContinue} }}</p>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
@ -23,8 +23,8 @@
|
||||||
|
|
||||||
<!-- List of SCOs. -->
|
<!-- List of SCOs. -->
|
||||||
<ng-container *ngFor="let sco of toc">
|
<ng-container *ngFor="let sco of toc">
|
||||||
<a *ngIf="sco.isvisible" ion-item text-wrap [ngClass]="'core-padding-' + sco.level" [class.core-nav-item-selected]="selected == sco.id" (click)="loadSco(sco)" [attr.disabled]="!sco.prereq || !sco.launch ? true : null" [attr.detail-none]="!sco.prereq || !sco.launch ? true : null">
|
<a *ngIf="sco.isvisible" ion-item text-wrap [ngClass]="'core-padding-' + sco.level + ' addon-mod_scorm-type-' + sco.scormtype" [class.core-nav-item-selected]="selected == sco.id" [class]="" (click)="loadSco(sco)" [attr.disabled]="!sco.prereq || !sco.launch ? true : null" [attr.detail-none]="!sco.prereq || !sco.launch ? true : null">
|
||||||
<img [src]="sco.image.url" [alt]="sco.image.description" />
|
<core-icon [name]="sco.image.icon" [label]="sco.image.description" item-start></core-icon>
|
||||||
<core-format-text [text]="sco.title" contextLevel="module" [contextInstanceId]="moduleId" [courseId]="courseId"></core-format-text>
|
<core-format-text [text]="sco.title" contextLevel="module" [contextInstanceId]="moduleId" [courseId]="courseId"></core-format-text>
|
||||||
<span *ngIf="accessInfo && accessInfo.canviewscores && sco.score_raw">({{ 'addon.mod_scorm.score' | translate }}: {{sco.score_raw}})</span>
|
<span *ngIf="accessInfo && accessInfo.canviewscores && sco.score_raw">({{ 'addon.mod_scorm.score' | translate }}: {{sco.score_raw}})</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { NgModule } from '@angular/core';
|
||||||
import { IonicPageModule } from 'ionic-angular';
|
import { IonicPageModule } from 'ionic-angular';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||||
|
import { CoreComponentsModule } from '@components/components.module';
|
||||||
import { AddonModScormTocPage } from './toc';
|
import { AddonModScormTocPage } from './toc';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -24,6 +25,7 @@ import { AddonModScormTocPage } from './toc';
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CoreDirectivesModule,
|
CoreDirectivesModule,
|
||||||
|
CoreComponentsModule,
|
||||||
IonicPageModule.forChild(AddonModScormTocPage),
|
IonicPageModule.forChild(AddonModScormTocPage),
|
||||||
TranslateModule.forChild()
|
TranslateModule.forChild()
|
||||||
],
|
],
|
||||||
|
|
|
@ -106,6 +106,22 @@ export class AddonModScormProvider {
|
||||||
'b': 'browsed',
|
'b': 'browsed',
|
||||||
'n': 'notattempted'
|
'n': 'notattempted'
|
||||||
};
|
};
|
||||||
|
protected static STATUS_TO_ICON = {
|
||||||
|
assetc: 'fa-file-archive-o',
|
||||||
|
asset: 'fa-file-archive-o',
|
||||||
|
browsed: 'fa-book',
|
||||||
|
completed: 'fa-check-square-o',
|
||||||
|
failed: 'fa-times',
|
||||||
|
incomplete: 'fa-pencil-square-o',
|
||||||
|
minus: 'fa-minus',
|
||||||
|
notattempted: 'fa-square-o',
|
||||||
|
passed: 'fa-check',
|
||||||
|
plus: 'fa-plus',
|
||||||
|
popdown: 'fa-window-close-o',
|
||||||
|
popup: 'fa-window-restore',
|
||||||
|
suspend: 'fa-pause',
|
||||||
|
wait: 'fa-clock-o',
|
||||||
|
};
|
||||||
|
|
||||||
protected ROOT_CACHE_KEY = 'mmaModScorm:';
|
protected ROOT_CACHE_KEY = 'mmaModScorm:';
|
||||||
protected logger;
|
protected logger;
|
||||||
|
@ -1048,39 +1064,56 @@ export class AddonModScormProvider {
|
||||||
* @param incomplete Whether the SCORM is incomplete.
|
* @param incomplete Whether the SCORM is incomplete.
|
||||||
* @return Image URL and description.
|
* @return Image URL and description.
|
||||||
*/
|
*/
|
||||||
getScoStatusIcon(sco: any, incomplete?: boolean): {url: string, description: string} {
|
getScoStatusIcon(sco: any, incomplete?: boolean): {icon: string, description: string} {
|
||||||
let imageName = '',
|
let imageName = '',
|
||||||
descName = '',
|
descName = '',
|
||||||
status;
|
suspendedStr = '';
|
||||||
|
|
||||||
if (sco.scormtype == 'sco') {
|
const status = sco.status;
|
||||||
// Not an asset, calculate image using status.
|
|
||||||
status = sco.status;
|
|
||||||
if (this.VALID_STATUSES.indexOf(status) < 0) {
|
|
||||||
// Status empty or not valid, use 'notattempted'.
|
|
||||||
status = 'notattempted';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!incomplete) {
|
if (sco.isvisible) {
|
||||||
// Check if SCO is completed or not. If SCORM is incomplete there's no need to check SCO.
|
if (this.VALID_STATUSES.indexOf(status) >= 0) {
|
||||||
incomplete = this.isStatusIncomplete(status);
|
if (sco.scormtype == 'sco') {
|
||||||
}
|
imageName = status;
|
||||||
|
descName = status;
|
||||||
|
} else {
|
||||||
|
imageName = 'asset';
|
||||||
|
descName = 'assetlaunched';
|
||||||
|
}
|
||||||
|
|
||||||
if (incomplete && sco.exitvalue == 'suspend') {
|
if (!incomplete) {
|
||||||
imageName = 'suspend';
|
// Check if SCO is completed or not. If SCORM is incomplete there's no need to check SCO.
|
||||||
descName = 'suspended';
|
incomplete = this.isStatusIncomplete(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (incomplete && sco.exitvalue == 'suspend') {
|
||||||
|
imageName = 'suspend';
|
||||||
|
suspendedStr = ' - ' + this.translate.instant('addon.mod_scorm.suspended');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
imageName = sco.status;
|
incomplete = true;
|
||||||
descName = sco.status;
|
|
||||||
|
if (sco.scormtype == 'sco') {
|
||||||
|
// Status empty or not valid, use 'notattempted'.
|
||||||
|
imageName = 'notattempted';
|
||||||
|
} else {
|
||||||
|
imageName = 'asset';
|
||||||
|
}
|
||||||
|
descName = imageName;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
imageName = 'asset';
|
|
||||||
descName = (!sco.status || sco.status == 'notattempted') ? 'asset' : 'assetlaunched';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (imageName == '') {
|
||||||
|
imageName = 'notattempted';
|
||||||
|
descName = 'notattempted';
|
||||||
|
suspendedStr = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
sco.incomplete = incomplete;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url: 'assets/img/scorm/' + imageName + '.gif',
|
icon: AddonModScormProvider.STATUS_TO_ICON[imageName],
|
||||||
description: this.translate.instant('addon.mod_scorm.' + descName)
|
description: this.translate.instant('addon.mod_scorm.' + descName) + suspendedStr
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,8 @@
|
||||||
<div *ngIf="question.multiArray && question.multiArray.length" [attr.padding-top]="index == 1">
|
<div *ngIf="question.multiArray && question.multiArray.length" [attr.padding-top]="index == 1">
|
||||||
<h3 padding-horizontal>{{ question.text }}</h3>
|
<h3 padding-horizontal>{{ question.text }}</h3>
|
||||||
<ion-grid no-padding>
|
<ion-grid no-padding>
|
||||||
<ion-row no-padding align-items-center class="hidden-phone">
|
<ion-row no-padding nowrap align-items-center class="hidden-phone">
|
||||||
<ion-col col-7>
|
<ion-col col-6>
|
||||||
<div padding>{{ 'addon.mod_survey.responses' | translate }}</div>
|
<div padding>{{ 'addon.mod_survey.responses' | translate }}</div>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
<ion-col text-center *ngFor="let option of question.optionsArray">
|
<ion-col text-center *ngFor="let option of question.optionsArray">
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
<!-- Subquestion -->
|
<!-- Subquestion -->
|
||||||
<ion-grid no-padding *ngIf="question.parent !== 0" text-wrap [class.even]="isEven">
|
<ion-grid no-padding *ngIf="question.parent !== 0" text-wrap [class.even]="isEven">
|
||||||
<ion-row no-padding nowrap align-items-center radio-group [(ngModel)]="answers[question.name]" [required]="question.required">
|
<ion-row no-padding nowrap align-items-center radio-group [(ngModel)]="answers[question.name]" [required]="question.required">
|
||||||
<ion-col col-7>
|
<ion-col col-6>
|
||||||
<ion-label padding-horizontal [core-mark-required]="question.required" id="addon-mod_survey-{{question.name}}"><strong>{{question.num}}.</strong> {{ question.text }}</ion-label>
|
<ion-label padding-horizontal [core-mark-required]="question.required" id="addon-mod_survey-{{question.name}}"><strong>{{question.num}}.</strong> {{ question.text }}</ion-label>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
|
|
||||||
|
@ -77,13 +77,13 @@
|
||||||
<ng-container *ngIf="(!question.multiArray || question.multiArray.length == 0) && question.parent === 0">
|
<ng-container *ngIf="(!question.multiArray || question.multiArray.length == 0) && question.parent === 0">
|
||||||
<ion-grid no-padding text-wrap *ngIf="question.type > 0" [class.even]="isEven">
|
<ion-grid no-padding text-wrap *ngIf="question.type > 0" [class.even]="isEven">
|
||||||
<ion-row no-padding align-items-center>
|
<ion-row no-padding align-items-center>
|
||||||
<ion-col col-7>
|
<ion-col col-6>
|
||||||
<ion-label [core-mark-required]="question.required" padding-horizontal id="addon-mod_survey-{{question.name}}"><strong>{{question.num}}.</strong> {{ question.text }}</ion-label>
|
<ion-label [core-mark-required]="question.required" padding-horizontal id="addon-mod_survey-{{question.name}}"><strong>{{question.num}}.</strong> {{ question.text }}</ion-label>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
<ion-col col-5>
|
<ion-col col-6>
|
||||||
<ion-select padding [(ngModel)]="answers[question.name]" [attr.aria-labelledby]="'addon-mod_survey-'+question.name" interface="action-sheet" [required]="question.required">
|
<ion-select padding [(ngModel)]="answers[question.name]" [attr.aria-labelledby]="'addon-mod_survey-'+question.name" interface="action-sheet" [required]="question.required">
|
||||||
<ion-option *ngFor="let option of question.optionsArray; let value=index;" [value]="value">{{option}}</ion-option>
|
<ion-option *ngFor="let option of question.optionsArray; let value=index;" [value]="value">{{option}}</ion-option>
|
||||||
</ion-select>
|
</ion-select>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
</ion-row>
|
</ion-row>
|
||||||
</ion-grid>
|
</ion-grid>
|
||||||
|
|
|
@ -163,13 +163,10 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo
|
||||||
* @return If answers are valid
|
* @return If answers are valid
|
||||||
*/
|
*/
|
||||||
isValidResponse(): boolean {
|
isValidResponse(): boolean {
|
||||||
for (const x in this.answers) {
|
return !this.questions.some((question) => {
|
||||||
if (this.answers[x] === -1) {
|
return question.required && question.name &&
|
||||||
return false;
|
(question.type === 0 ? this.answers[question.name] == '' : parseInt(this.answers[question.name], 10) === -1);
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,6 +4,11 @@ $addon-mod-wiki-toc-title-color: $gray-darker !default;
|
||||||
$addon-mod-wiki-toc-border-color: $gray-dark !default;
|
$addon-mod-wiki-toc-border-color: $gray-dark !default;
|
||||||
$addon-mod-wiki-toc-background-color: $gray-light !default;
|
$addon-mod-wiki-toc-background-color: $gray-light !default;
|
||||||
|
|
||||||
|
$addon-mod-wiki-dark-toc-title-color: $white !default;
|
||||||
|
$addon-mod-wiki-dark-toc-border-color: $gray-dark !default;
|
||||||
|
$addon-mod-wiki-dark-toc-background-color: $gray-darker !default;
|
||||||
|
$addon-mod-wiki-dark-newentry-link-color: $red-light !default;
|
||||||
|
|
||||||
ion-app.app-root addon-mod-wiki-index {
|
ion-app.app-root addon-mod-wiki-index {
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
@include darkmode() {
|
@include darkmode() {
|
||||||
|
@ -28,6 +33,17 @@ ion-app.app-root addon-mod-wiki-index {
|
||||||
a {
|
a {
|
||||||
color: $link-color;
|
color: $link-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@include darkmode() {
|
||||||
|
border: 1px solid $addon-mod-wiki-dark-toc-border-color;
|
||||||
|
background: $addon-mod-wiki-dark-toc-background-color;
|
||||||
|
p {
|
||||||
|
color: $core-dark-text-color !important;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: $core-dark-link-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
margin: 16px;
|
margin: 16px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
|
@ -55,6 +71,9 @@ ion-app.app-root addon-mod-wiki-index {
|
||||||
.wiki_newentry {
|
.wiki_newentry {
|
||||||
color: $addon-mod-wiki-newentry-link-color;
|
color: $addon-mod-wiki-newentry-link-color;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
|
@include darkmode() {
|
||||||
|
color: $addon-mod-wiki-dark-newentry-link-color !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hide edit section links */
|
/* Hide edit section links */
|
||||||
|
|
|
@ -500,7 +500,7 @@ ion-app.app-root {
|
||||||
@include darkmode() {
|
@include darkmode() {
|
||||||
ion-select.core-button-select,
|
ion-select.core-button-select,
|
||||||
.core-button-select {
|
.core-button-select {
|
||||||
background-color: $core-dark-item-divider-bg-color;
|
background-color: $core-dark-item-bg-color;
|
||||||
|
|
||||||
|
|
||||||
&.select-md,
|
&.select-md,
|
||||||
|
@ -509,7 +509,7 @@ ion-app.app-root {
|
||||||
&.button-ios,
|
&.button-ios,
|
||||||
&.select-wp,
|
&.select-wp,
|
||||||
&.button-wp {
|
&.button-wp {
|
||||||
background: $core-dark-item-divider-bg-color;
|
background: $core-dark-item-bg-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 178 B |
Before Width: | Height: | Size: 105 B |
Before Width: | Height: | Size: 190 B |
Before Width: | Height: | Size: 190 B |
Before Width: | Height: | Size: 597 B |
Before Width: | Height: | Size: 79 B |
Before Width: | Height: | Size: 190 B |
Before Width: | Height: | Size: 362 B |
|
@ -82,6 +82,7 @@ export class CoreIconComponent implements OnChanges, OnDestroy {
|
||||||
!this.ariaLabel && this.newElement.setAttribute('aria-hidden', 'true');
|
!this.ariaLabel && this.newElement.setAttribute('aria-hidden', 'true');
|
||||||
!this.ariaLabel && this.newElement.setAttribute('role', 'presentation');
|
!this.ariaLabel && this.newElement.setAttribute('role', 'presentation');
|
||||||
this.ariaLabel && this.newElement.setAttribute('aria-label', this.ariaLabel);
|
this.ariaLabel && this.newElement.setAttribute('aria-label', this.ariaLabel);
|
||||||
|
this.ariaLabel && this.newElement.setAttribute('title', this.ariaLabel);
|
||||||
|
|
||||||
const attrs = this.element.attributes;
|
const attrs = this.element.attributes;
|
||||||
for (let i = attrs.length - 1; i >= 0; i--) {
|
for (let i = attrs.length - 1; i >= 0; i--) {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<core-loading [hideUntil]="loaded">
|
<core-loading [hideUntil]="loaded">
|
||||||
<!-- Section selector. -->
|
<!-- Section selector. -->
|
||||||
<core-dynamic-component [component]="sectionSelectorComponent" [data]="data">
|
<core-dynamic-component [component]="sectionSelectorComponent" [data]="data">
|
||||||
<div text-wrap *ngIf="displaySectionSelector && sections && sections.length" padding class="clearfix" ion-row justify-content-between class="safe-padding-horizontal" [class.core-section-download]="downloadEnabled">
|
<div text-wrap *ngIf="displaySectionSelector && sections && sections.length" padding class="clearfix" ion-row justify-content-between class="safe-padding-horizontal core-button-selector-row" [class.core-section-download]="downloadEnabled">
|
||||||
<button float-start ion-button icon-start icon-end (click)="showSectionSelector($event)" color="light" class="core-button-select button-no-uppercase" ion-col [attr.aria-label]="('core.course.sections' | translate) + ': ' + (selectedSection && (selectedSection.formattedName || selectedSection.name))" aria-haspopup="true" [attr.aria-expanded]="sectionSelectorExpanded" aria-controls="core-course-section-selector" id="core-course-section-button">
|
<button float-start ion-button icon-start icon-end (click)="showSectionSelector($event)" color="light" class="core-button-select button-no-uppercase" ion-col [attr.aria-label]="('core.course.sections' | translate) + ': ' + (selectedSection && (selectedSection.formattedName || selectedSection.name))" aria-haspopup="true" [attr.aria-expanded]="sectionSelectorExpanded" aria-controls="core-course-section-selector" id="core-course-section-button">
|
||||||
<core-icon name="fa-folder"></core-icon>
|
<core-icon name="fa-folder"></core-icon>
|
||||||
<span class="core-button-select-text">{{selectedSection && (selectedSection.formattedName || selectedSection.name) || 'core.course.sections' | translate }}</span>
|
<span class="core-button-select-text">{{selectedSection && (selectedSection.formattedName || selectedSection.name) || 'core.course.sections' | translate }}</span>
|
||||||
|
|
|
@ -64,6 +64,10 @@ ion-app.app-root core-course-format {
|
||||||
@include padding(null, 0, null, null);
|
@include padding(null, 0, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.core-button-selector-row {
|
||||||
|
@include safe-area-padding-start($content-padding !important, $content-padding);
|
||||||
|
}
|
||||||
|
|
||||||
.core-course-section-nav-buttons {
|
.core-course-section-nav-buttons {
|
||||||
.button-inner core-format-text {
|
.button-inner core-format-text {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
|
@ -88,7 +88,7 @@ export class ZipMock extends Zip {
|
||||||
const destParent = destination.substring(0, source.lastIndexOf('/')),
|
const destParent = destination.substring(0, source.lastIndexOf('/')),
|
||||||
destFolderName = destination.substr(source.lastIndexOf('/') + 1);
|
destFolderName = destination.substr(source.lastIndexOf('/') + 1);
|
||||||
|
|
||||||
return this.file.createDir(destParent, destFolderName, false);
|
return this.file.createDir(destParent, destFolderName, true);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
|
||||||
const promises = [],
|
const promises = [],
|
||||||
|
|
|
@ -1017,7 +1017,7 @@ export class CoreFileProvider {
|
||||||
return this.zip.unzip(fileEntry.toURL(), destFolder, onProgress);
|
return this.zip.unzip(fileEntry.toURL(), destFolder, onProgress);
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
return Promise.reject(null);
|
return Promise.reject('Unzip failed.');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ $core-dark-text-secondary-color: $gray-light !default;
|
||||||
$core-dark-link-color: $blue-light !default;
|
$core-dark-link-color: $blue-light !default;
|
||||||
|
|
||||||
$core-dark-item-bg-color: $gray-darker !default;
|
$core-dark-item-bg-color: $gray-darker !default;
|
||||||
$core-dark-item-divider-bg-color: $black !default;
|
$core-dark-item-divider-bg-color: $gray-dark !default;
|
||||||
$core-dark-background-color: $gray-dark !default;
|
$core-dark-background-color: $black !default;
|
||||||
|
|
||||||
// Login.
|
// Login.
|
||||||
$core-dark-login-page-background-color: radial-gradient(white, $gray-dark) !default;
|
$core-dark-login-page-background-color: radial-gradient(white, $gray-dark) !default;
|
||||||
|
@ -31,7 +31,8 @@ ion-app.app-root .ion-page {
|
||||||
.item,
|
.item,
|
||||||
.item-select,
|
.item-select,
|
||||||
ion-card,
|
ion-card,
|
||||||
.card-header {
|
.card-header,
|
||||||
|
.card-content {
|
||||||
color: $core-dark-text-color;
|
color: $core-dark-text-color;
|
||||||
background-color: $core-dark-item-bg-color;
|
background-color: $core-dark-item-bg-color;
|
||||||
|
|
||||||
|
|