commit
29388cdc47
|
@ -18,12 +18,12 @@
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<ng-container *ngFor="let contact of contacts[contactType]">
|
<ng-container *ngFor="let contact of contacts[contactType]">
|
||||||
<!-- Don't show deleted users -->
|
<!-- Don't show deleted users -->
|
||||||
<ion-item text-wrap *ngIf="contact.profileimageurl || contact.profileimageurlsmall" [title]="contact.fullname" (click)="gotoDiscussion(contact.id)" [class.core-split-item-selected]="contact.id == discussionUserId" detail-none>
|
<a ion-item text-wrap *ngIf="contact.profileimageurl || contact.profileimageurlsmall" [title]="contact.fullname" (click)="gotoDiscussion(contact.id)" [class.core-split-item-selected]="contact.id == discussionUserId" detail-none>
|
||||||
<ion-avatar item-start>
|
<ion-avatar item-start>
|
||||||
<img src="{{contact.profileimageurl || contact.profileimageurlsmall}}" [alt]="'core.pictureof' | translate:{$a: contact.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
|
<img src="{{contact.profileimageurl || contact.profileimageurlsmall}}" [alt]="'core.pictureof' | translate:{$a: contact.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
|
||||||
</ion-avatar>
|
</ion-avatar>
|
||||||
<h2><core-format-text [text]="contact.fullname"></core-format-text></h2>
|
<h2><core-format-text [text]="contact.fullname"></core-format-text></h2>
|
||||||
</ion-item>
|
</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
|
|
@ -16,17 +16,17 @@
|
||||||
<h2>{{ 'core.searchresults' | translate }}</h2>
|
<h2>{{ 'core.searchresults' | translate }}</h2>
|
||||||
<ion-note item-end>{{ search.results.length }}</ion-note>
|
<ion-note item-end>{{ search.results.length }}</ion-note>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<ion-item text-wrap *ngFor="let result of search.results" [title]="result.fullname" (click)="gotoDiscussion(result.userid, result.messageid)" [class.core-split-item-selected]="result.userid == discussionUserId" detail-none>
|
<a ion-item text-wrap *ngFor="let result of search.results" [title]="result.fullname" (click)="gotoDiscussion(result.userid, result.messageid)" [class.core-split-item-selected]="result.userid == discussionUserId" detail-none>
|
||||||
<ion-avatar item-start>
|
<ion-avatar item-start>
|
||||||
<img src="{{result.profileimageurl}}" [alt]="'core.pictureof' | translate:{$a: result.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
|
<img src="{{result.profileimageurl}}" [alt]="'core.pictureof' | translate:{$a: result.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
|
||||||
</ion-avatar>
|
</ion-avatar>
|
||||||
<h2><core-format-text [text]="result.fullname"></core-format-text></h2>
|
<h2><core-format-text [text]="result.fullname"></core-format-text></h2>
|
||||||
<p><core-format-text clean="true" singleLine="true" [text]="result.lastmessage"></core-format-text></p>
|
<p><core-format-text clean="true" singleLine="true" [text]="result.lastmessage"></core-format-text></p>
|
||||||
</ion-item>
|
</a>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
|
||||||
<ion-list *ngIf="!search.showResults" no-margin>
|
<ion-list *ngIf="!search.showResults" no-margin>
|
||||||
<ion-item text-wrap *ngFor="let discussion of discussions" [title]="discussion.fullname" (click)="gotoDiscussion(discussion.message.user)" [class.core-split-item-selected]="discussion.message.user == discussionUserId" detail-none>
|
<a ion-item text-wrap *ngFor="let discussion of discussions" [title]="discussion.fullname" (click)="gotoDiscussion(discussion.message.user)" [class.core-split-item-selected]="discussion.message.user == discussionUserId" detail-none>
|
||||||
<ion-avatar item-start>
|
<ion-avatar item-start>
|
||||||
<img src="{{discussion.profileimageurl}}" [alt]="'core.pictureof' | translate:{$a: discussion.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
|
<img src="{{discussion.profileimageurl}}" [alt]="'core.pictureof' | translate:{$a: discussion.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
|
||||||
</ion-avatar>
|
</ion-avatar>
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
</ion-note>
|
</ion-note>
|
||||||
</h2>
|
</h2>
|
||||||
<p><core-format-text clean="true" singleLine="true" [text]="discussion.message.message"></core-format-text></p>
|
<p><core-format-text clean="true" singleLine="true" [text]="discussion.message.message"></core-format-text></p>
|
||||||
</ion-item>
|
</a>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
|
@ -201,14 +201,14 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Data about the grader (teacher who graded). -->
|
<!-- Data about the grader (teacher who graded). -->
|
||||||
<ion-item text-wrap *ngIf="grader" (click)="openUserProfile(grader.id)" [title]="grader.fullname" detail-push>
|
<a ion-item text-wrap *ngIf="grader" (click)="openUserProfile(grader.id)" [title]="grader.fullname" detail-push>
|
||||||
<ion-avatar item-start>
|
<ion-avatar item-start>
|
||||||
<img [src]="grader.profileimageurl" core-external-content [alt]="'core.pictureof' | translate:{$a: grader.fullname}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
|
<img [src]="grader.profileimageurl" core-external-content [alt]="'core.pictureof' | translate:{$a: grader.fullname}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
|
||||||
</ion-avatar>
|
</ion-avatar>
|
||||||
<h2>{{ 'addon.mod_assign.gradedby' | translate }}</h2>
|
<h2>{{ 'addon.mod_assign.gradedby' | translate }}</h2>
|
||||||
<h2>{{ grader.fullname }}</h2>
|
<h2>{{ grader.fullname }}</h2>
|
||||||
<p *ngIf="feedback.gradeddate">{{ feedback.gradeddate * 1000 | coreFormatDate:"dfmediumdate" }}</p>
|
<p *ngIf="feedback.gradeddate">{{ feedback.gradeddate * 1000 | coreFormatDate:"dfmediumdate" }}</p>
|
||||||
</ion-item>
|
</a>
|
||||||
|
|
||||||
<!-- Warning message if cannot save grades. -->
|
<!-- Warning message if cannot save grades. -->
|
||||||
<div *ngIf="isGrading && !canSaveGrades" class="core-warning-card" icon-start>
|
<div *ngIf="isGrading && !canSaveGrades" class="core-warning-card" icon-start>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<ion-item text-wrap (click)="showComments()">
|
<a ion-item text-wrap (click)="showComments()" detail-none>
|
||||||
<h2>{{plugin.name}}</h2>
|
<h2>{{plugin.name}}</h2>
|
||||||
<core-comments contextLevel="module" [instanceId]="assign.cmid" component="assignsubmission_comments" [itemId]="submission.id" area="submission_comments" [title]="plugin.name"></core-comments>
|
<core-comments contextLevel="module" [instanceId]="assign.cmid" component="assignsubmission_comments" [itemId]="submission.id" area="submission_comments" [title]="plugin.name"></core-comments>
|
||||||
</ion-item>
|
</a>
|
||||||
|
|
|
@ -51,13 +51,13 @@
|
||||||
<ion-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">{{groupOpt.name}}</ion-option>
|
<ion-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">{{groupOpt.name}}</ion-option>
|
||||||
</ion-select>
|
</ion-select>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item text-wrap *ngIf="access.canviewreports || access.canedititems" (click)="access.canviewreports && openFeature('Respondents')" [attr.detail-push]="access.canviewreports ? true : null">
|
<a ion-item text-wrap *ngIf="access.canviewreports || access.canedititems" (click)="access.canviewreports && openFeature('Respondents')" [attr.detail-none]="access.canviewreports ? null : true">
|
||||||
<h2>{{ 'addon.mod_feedback.completed_feedbacks' | translate }}</h2>
|
<h2>{{ 'addon.mod_feedback.completed_feedbacks' | translate }}</h2>
|
||||||
<ion-badge item-end>{{feedback.completedCount}}</ion-badge>
|
<ion-badge item-end>{{feedback.completedCount}}</ion-badge>
|
||||||
</ion-item>
|
</a>
|
||||||
<ion-item text-wrap *ngIf="!access.isanonymous && access.canviewreports" (click)="openFeature('NonRespondents')" detail-push>
|
<a ion-item text-wrap *ngIf="!access.isanonymous && access.canviewreports" (click)="openFeature('NonRespondents')" detail-push>
|
||||||
<h2>{{ 'addon.mod_feedback.show_nonrespondents' | translate }}</h2>
|
<h2>{{ 'addon.mod_feedback.show_nonrespondents' | translate }}</h2>
|
||||||
</ion-item>
|
</a>
|
||||||
<ion-item text-wrap *ngIf="access.canedititems">
|
<ion-item text-wrap *ngIf="access.canedititems">
|
||||||
<h2>{{ 'addon.mod_feedback.questions' | translate }}</h2>
|
<h2>{{ 'addon.mod_feedback.questions' | translate }}</h2>
|
||||||
<ion-badge item-end>{{feedback.itemsCount}}</ion-badge>
|
<ion-badge item-end>{{feedback.itemsCount}}</ion-badge>
|
||||||
|
|
|
@ -36,9 +36,9 @@
|
||||||
<ion-item-divider color="light">
|
<ion-item-divider color="light">
|
||||||
{{ 'addon.mod_glossary.entriestobesynced' | translate }}
|
{{ 'addon.mod_glossary.entriestobesynced' | translate }}
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<ion-item *ngFor="let entry of offlineEntries" (click)="openNewEntry(entry)">
|
<a ion-item *ngFor="let entry of offlineEntries" (click)="openNewEntry(entry)" detail-none>
|
||||||
<p>{{entry.concept}}</p>
|
<p>{{entry.concept}}</p>
|
||||||
</ion-item>
|
</a>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
|
||||||
<ion-list *ngIf="entries.length > 0">
|
<ion-list *ngIf="entries.length > 0">
|
||||||
|
@ -48,9 +48,9 @@
|
||||||
{{getDivider(entry)}}
|
{{getDivider(entry)}}
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
|
|
||||||
<ion-item (click)="openEntry(entry.id)" [class.core-split-item-selected]="entry.id == selectedEntry">
|
<a ion-item (click)="openEntry(entry.id)" [class.core-split-item-selected]="entry.id == selectedEntry" detail-none>
|
||||||
<p>{{entry.concept}}</p>
|
<p>{{entry.concept}}</p>
|
||||||
</ion-item>
|
</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<core-loading [hideUntil]="loaded">
|
<core-loading [hideUntil]="loaded">
|
||||||
<ion-item *ngIf="summary" text-wrap [attr.detail-push]="canViewAssessment && !canSelfAssess? true : null" (click)="gotoAssessment()">
|
<a ion-item *ngIf="summary" text-wrap [attr.detail-none]="canViewAssessment && !canSelfAssess? null : true" (click)="gotoAssessment()">
|
||||||
<ion-avatar item-start>
|
<ion-avatar item-start>
|
||||||
<img [src]="profile && profile.profileimageurl" core-external-content [alt]="'core.pictureof' | translate:{$a: profile && profile.fullname}" core-user-link [courseId]="courseId" [userId]="profile && profile.id" role="presentation" onError="this.src='assets/img/user-avatar.png'">
|
<img [src]="profile && profile.profileimageurl" core-external-content [alt]="'core.pictureof' | translate:{$a: profile && profile.fullname}" core-user-link [courseId]="courseId" [userId]="profile && profile.id" role="presentation" onError="this.src='assets/img/user-avatar.png'">
|
||||||
</ion-avatar>
|
</ion-avatar>
|
||||||
|
@ -23,5 +23,5 @@
|
||||||
<ion-note item-end *ngIf="offline">
|
<ion-note item-end *ngIf="offline">
|
||||||
<ion-icon name="time"></ion-icon>{{ 'core.notsent' | translate }}
|
<ion-icon name="time"></ion-icon>{{ 'core.notsent' | translate }}
|
||||||
</ion-note>
|
</ion-note>
|
||||||
</ion-item>
|
</a>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
<core-course-module-description *ngIf="description && selectedPhase == workshopPhases.PHASE_SETUP" [description]="description" [component]="component" [componentId]="componentId"></core-course-module-description>
|
<core-course-module-description *ngIf="description && selectedPhase == workshopPhases.PHASE_SETUP" [description]="description" [component]="component" [componentId]="componentId"></core-course-module-description>
|
||||||
|
|
||||||
<ion-card class="with-borders" *ngIf="phases">
|
<ion-card class="with-borders" *ngIf="phases">
|
||||||
<ion-item (click)="selectPhase()">
|
<a ion-item (click)="selectPhase()" detail-none>
|
||||||
<h2 stacked text-wrap>{{ phases[selectedPhase].title }}</h2>
|
<h2 stacked text-wrap>{{ phases[selectedPhase].title }}</h2>
|
||||||
<p text-wrap *ngIf="phases[selectedPhase].code == workshop.phase">{{ 'addon.mod_workshop.userplancurrentphase' | translate }}</p>
|
<p text-wrap *ngIf="phases[selectedPhase].code == workshop.phase">{{ 'addon.mod_workshop.userplancurrentphase' | translate }}</p>
|
||||||
<ion-icon item-end name="arrow-dropdown"></ion-icon>
|
<ion-icon item-end name="arrow-dropdown"></ion-icon>
|
||||||
</ion-item>
|
</a>
|
||||||
<a ion-item text-wrap *ngIf="phases[selectedPhase].switchUrl" [href]="phases[selectedPhase].switchUrl" detail-none>
|
<a ion-item text-wrap *ngIf="phases[selectedPhase].switchUrl" [href]="phases[selectedPhase].switchUrl" detail-none>
|
||||||
<ion-icon item-start name="swap"></ion-icon>
|
<ion-icon item-start name="swap"></ion-icon>
|
||||||
{{ 'addon.mod_workshop.switchphase' + selectedPhase | translate }}
|
{{ 'addon.mod_workshop.switchphase' + selectedPhase | translate }}
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
</ion-card>
|
</ion-card>
|
||||||
|
|
||||||
<ion-card class="with-borders" *ngIf="phases && phases[selectedPhase] && phases[selectedPhase].tasks && phases[selectedPhase].tasks.length">
|
<ion-card class="with-borders" *ngIf="phases && phases[selectedPhase] && phases[selectedPhase].tasks && phases[selectedPhase].tasks.length">
|
||||||
<ion-item text-wrap *ngFor="let task of phases[selectedPhase].tasks" [class.item-dimmed]="selectedPhase != workshop.phase" (click)="runTask(task)" detail-none>
|
<a ion-item text-wrap *ngFor="let task of phases[selectedPhase].tasks" [class.item-dimmed]="selectedPhase != workshop.phase" (click)="runTask(task)" detail-none>
|
||||||
<ion-icon item-start name="radio-button-off" *ngIf="task.completed == null"></ion-icon>
|
<ion-icon item-start name="radio-button-off" *ngIf="task.completed == null"></ion-icon>
|
||||||
<ion-icon item-start name="close-circle" color="danger" *ngIf="task.completed == ''"></ion-icon>
|
<ion-icon item-start name="close-circle" color="danger" *ngIf="task.completed == ''"></ion-icon>
|
||||||
<ion-icon item-start name="information-circle" color="info" *ngIf="task.completed == 'info'"></ion-icon>
|
<ion-icon item-start name="information-circle" color="info" *ngIf="task.completed == 'info'"></ion-icon>
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
<h2>{{task.title}}</h2>
|
<h2>{{task.title}}</h2>
|
||||||
<p *ngIf="task.details"><core-format-text [text]="task.details"></core-format-text></p>
|
<p *ngIf="task.details"><core-format-text [text]="task.details"></core-format-text></p>
|
||||||
<ion-icon item-end *ngIf="task.link && !task.support" name="open"></ion-icon>
|
<ion-icon item-end *ngIf="task.link && !task.support" name="open"></ion-icon>
|
||||||
</ion-item>
|
</a>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
|
|
||||||
<!-- Has something offline. -->
|
<!-- Has something offline. -->
|
||||||
|
@ -102,12 +102,12 @@
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ion-card class="with-borders" *ngIf="!access.canviewallsubmissions && selectedPhase == workshop.phase && (canSubmit || canAssess) && selectedPhase == workshopPhases.PHASE_EVALUATION">
|
<ion-card class="with-borders" *ngIf="!access.canviewallsubmissions && selectedPhase == workshop.phase && (canSubmit || canAssess) && selectedPhase == workshopPhases.PHASE_EVALUATION">
|
||||||
<ion-item text-wrap *ngIf="submission" (click)="switchPhase(workshopPhases.PHASE_SUBMISSION)" detail-push>
|
<a ion-item text-wrap *ngIf="submission" (click)="switchPhase(workshopPhases.PHASE_SUBMISSION)" detail-push>
|
||||||
<h2>{{ 'addon.mod_workshop.yoursubmission' | translate }}</h2>
|
<h2>{{ 'addon.mod_workshop.yoursubmission' | translate }}</h2>
|
||||||
</ion-item>
|
</a>
|
||||||
<ion-item text-wrap *ngIf="canAssess" (click)="switchPhase(workshopPhases.PHASE_ASSESSMENT)" detail-push>
|
<a ion-item text-wrap *ngIf="canAssess" (click)="switchPhase(workshopPhases.PHASE_ASSESSMENT)" detail-push>
|
||||||
<h2>{{ 'addon.mod_workshop.assignedassessments' | translate }}</h2>
|
<h2>{{ 'addon.mod_workshop.assignedassessments' | translate }}</h2>
|
||||||
</ion-item>
|
</a>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
|
|
||||||
<!-- CLOSED PHASE -->
|
<!-- CLOSED PHASE -->
|
||||||
|
@ -123,14 +123,14 @@
|
||||||
<ion-item-divider color="light" text-wrap>
|
<ion-item-divider color="light" text-wrap>
|
||||||
<h2>{{ 'addon.mod_workshop.yourgrades' | translate }}</h2>
|
<h2>{{ 'addon.mod_workshop.yourgrades' | translate }}</h2>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<ion-item text-wrap *ngIf="userGrades.submissionlongstrgrade" (click)="switchPhase(workshopPhases.PHASE_SUBMISSION)" detail-push>
|
<a ion-item text-wrap *ngIf="userGrades.submissionlongstrgrade" (click)="switchPhase(workshopPhases.PHASE_SUBMISSION)" detail-push>
|
||||||
<h2>{{ 'addon.mod_workshop.submissiongrade' | translate }}</h2>
|
<h2>{{ 'addon.mod_workshop.submissiongrade' | translate }}</h2>
|
||||||
<core-format-text [text]="userGrades.submissionlongstrgrade"></core-format-text>
|
<core-format-text [text]="userGrades.submissionlongstrgrade"></core-format-text>
|
||||||
</ion-item>
|
</a>
|
||||||
<ion-item text-wrap *ngIf="userGrades.assessmentlongstrgrade" (click)="switchPhase(workshopPhases.PHASE_ASSESSMENT)" detail-push>
|
<a ion-item text-wrap *ngIf="userGrades.assessmentlongstrgrade" (click)="switchPhase(workshopPhases.PHASE_ASSESSMENT)" detail-push>
|
||||||
<h2>{{ 'addon.mod_workshop.gradinggrade' | translate }}</h2>
|
<h2>{{ 'addon.mod_workshop.gradinggrade' | translate }}</h2>
|
||||||
<core-format-text [text]="userGrades.assessmentlongstrgrade"></core-format-text>
|
<core-format-text [text]="userGrades.assessmentlongstrgrade"></core-format-text>
|
||||||
</ion-item>
|
</a>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
|
|
||||||
<ion-card class="with-borders" *ngIf="publishedSubmissions && publishedSubmissions.length">
|
<ion-card class="with-borders" *ngIf="publishedSubmissions && publishedSubmissions.length">
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ion-item text-wrap *ngIf="summary" [attr.detail-push]="submission.timemodified? true : null" (click)="gotoSubmission()">
|
<a ion-item text-wrap *ngIf="summary" [attr.detail-none]="submission.timemodified ? null : true" (click)="gotoSubmission()">
|
||||||
<ion-avatar item-start>
|
<ion-avatar item-start>
|
||||||
<img [src]="profile && profile.profileimageurl" core-external-content [alt]="'core.pictureof' | translate:{$a: profile && profile.fullname}" core-user-link [courseId]="courseId" [userId]="profile && profile.id" role="presentation" onError="this.src='assets/img/user-avatar.png'">
|
<img [src]="profile && profile.profileimageurl" core-external-content [alt]="'core.pictureof' | translate:{$a: profile && profile.fullname}" core-user-link [courseId]="courseId" [userId]="profile && profile.id" role="presentation" onError="this.src='assets/img/user-avatar.png'">
|
||||||
</ion-avatar>
|
</ion-avatar>
|
||||||
|
@ -78,5 +78,5 @@
|
||||||
<div *ngIf="offline"><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</div>
|
<div *ngIf="offline"><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</div>
|
||||||
<div *ngIf="submission.deleted"><ion-icon name="trash"></ion-icon> {{ 'core.deletedoffline' | translate }}</div>
|
<div *ngIf="submission.deleted"><ion-icon name="trash"></ion-icon> {{ 'core.deletedoffline' | translate }}</div>
|
||||||
</ion-note>
|
</ion-note>
|
||||||
</ion-item>
|
</a>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
|
|
|
@ -376,7 +376,10 @@ export class CoreSite {
|
||||||
* @param {any} Config.
|
* @param {any} Config.
|
||||||
*/
|
*/
|
||||||
setConfig(config: any): void {
|
setConfig(config: any): void {
|
||||||
|
if (config) {
|
||||||
config.tool_mobile_disabledfeatures = this.textUtils.treatDisabledFeatures(config.tool_mobile_disabledfeatures);
|
config.tool_mobile_disabledfeatures = this.textUtils.treatDisabledFeatures(config.tool_mobile_disabledfeatures);
|
||||||
|
}
|
||||||
|
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.calculateOfflineDisabled();
|
this.calculateOfflineDisabled();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
<!-- Buttons to add to the header. *ngIf is needed, otherwise the component is executed too soon and doesn't find the header. -->
|
||||||
|
<core-navbar-buttons end *ngIf="loaded">
|
||||||
|
<core-context-menu>
|
||||||
|
<core-context-menu-item [hidden]="!displaySectionSelector || !sections || !sections.length" [priority]="500" [content]="'core.course.sections' | translate" (action)="showSectionSelector($event)" iconAction="menu"></core-context-menu-item>
|
||||||
|
</core-context-menu>
|
||||||
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Default course format. -->
|
<!-- Default course format. -->
|
||||||
<core-dynamic-component [component]="courseFormatComponent" [data]="data">
|
<core-dynamic-component [component]="courseFormatComponent" [data]="data">
|
||||||
<!-- Course summary. By default we only display the course progress. -->
|
<!-- Course summary. By default we only display the course progress. -->
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ng-container *ngFor="let section of sections">
|
<ng-container *ngFor="let section of sections">
|
||||||
<ion-item *ngIf="sectionHasContent(section)" text-wrap (click)="selectSection(section)" [class.core-primary-item]="selected.id == section.id" [class.item-dimmed]="section.visible === 0 || section.uservisible === false">
|
<a ion-item *ngIf="sectionHasContent(section)" text-wrap (click)="selectSection(section)" [class.core-primary-item]="selected.id == section.id" [class.item-dimmed]="section.visible === 0 || section.uservisible === false" detail-none>
|
||||||
<h2><core-format-text [text]="section.formattedName || section.name"></core-format-text></h2>
|
<h2><core-format-text [text]="section.formattedName || section.name"></core-format-text></h2>
|
||||||
<ion-badge color="secondary" *ngIf="section.visible === 0">{{ 'core.course.nocontentavailable' | translate }}</ion-badge>
|
<ion-badge color="secondary" *ngIf="section.visible === 0">{{ 'core.course.nocontentavailable' | translate }}</ion-badge>
|
||||||
<ion-badge color="secondary" *ngIf="section.availabilityinfo"><core-format-text [text]=" section.availabilityinfo"></core-format-text></ion-badge>
|
<ion-badge color="secondary" *ngIf="section.availabilityinfo"><core-format-text [text]=" section.availabilityinfo"></core-format-text></ion-badge>
|
||||||
</ion-item>
|
</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
|
@ -209,7 +209,7 @@ export class CoreCourseSectionPage implements OnDestroy {
|
||||||
// Get the overview files.
|
// Get the overview files.
|
||||||
if (this.course.overviewfiles) {
|
if (this.course.overviewfiles) {
|
||||||
this.course.imageThumb = this.course.overviewfiles[0] && this.course.overviewfiles[0].fileurl;
|
this.course.imageThumb = this.course.overviewfiles[0] && this.course.overviewfiles[0].fileurl;
|
||||||
} else {
|
} else if (this.coursesProvider.isGetCoursesByFieldAvailable()) {
|
||||||
promises.push(this.coursesProvider.getCoursesByField('id', this.course.id).then((coursesInfo) => {
|
promises.push(this.coursesProvider.getCoursesByField('id', this.course.id).then((coursesInfo) => {
|
||||||
if (coursesInfo[0] && coursesInfo[0].overviewfiles && coursesInfo[0].overviewfiles[0]) {
|
if (coursesInfo[0] && coursesInfo[0].overviewfiles && coursesInfo[0].overviewfiles[0]) {
|
||||||
this.course.imageThumb = coursesInfo[0].overviewfiles[0].fileurl;
|
this.course.imageThumb = coursesInfo[0].overviewfiles[0].fileurl;
|
||||||
|
|
|
@ -97,6 +97,15 @@ export class CoreCourseFormatDefaultHandler implements CoreCourseFormatHandler {
|
||||||
* @return {any|Promise<any>} Current section (or promise resolved with current section).
|
* @return {any|Promise<any>} Current section (or promise resolved with current section).
|
||||||
*/
|
*/
|
||||||
getCurrentSection(course: any, sections: any[]): any | Promise<any> {
|
getCurrentSection(course: any, sections: any[]): any | Promise<any> {
|
||||||
|
if (!this.coursesProvider.isGetCoursesByFieldAvailable()) {
|
||||||
|
// Cannot get the current section, return the first one.
|
||||||
|
if (sections[0].id != CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||||
|
return sections[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return sections[1];
|
||||||
|
}
|
||||||
|
|
||||||
// We need the "marker" to determine the current section.
|
// We need the "marker" to determine the current section.
|
||||||
return this.coursesProvider.getCoursesByField('id', course.id).catch(() => {
|
return this.coursesProvider.getCoursesByField('id', course.id).catch(() => {
|
||||||
// Ignore errors.
|
// Ignore errors.
|
||||||
|
|
|
@ -1007,7 +1007,9 @@ export class CoreCourseHelperProvider {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Prefetch other data needed to render the course.
|
// Prefetch other data needed to render the course.
|
||||||
|
if (this.coursesProvider.isGetCoursesByFieldAvailable()) {
|
||||||
promises.push(this.coursesProvider.getCoursesByField('id', course.id));
|
promises.push(this.coursesProvider.getCoursesByField('id', course.id));
|
||||||
|
}
|
||||||
promises.push(this.courseProvider.getActivitiesCompletionStatus(course.id));
|
promises.push(this.courseProvider.getActivitiesCompletionStatus(course.id));
|
||||||
|
|
||||||
return this.utils.allPromises(promises);
|
return this.utils.allPromises(promises);
|
||||||
|
|
|
@ -395,7 +395,9 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
|
||||||
* @return {Promise<void>} Promise resolved when done.
|
* @return {Promise<void>} Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
protected loadCourseOptions(course: any, refresh?: boolean): Promise<void> {
|
protected loadCourseOptions(course: any, refresh?: boolean): Promise<void> {
|
||||||
if (typeof course.navOptions == 'undefined' || typeof course.admOptions == 'undefined' || refresh) {
|
if (this.coursesProvider.canGetAdminAndNavOptions() &&
|
||||||
|
(typeof course.navOptions == 'undefined' || typeof course.admOptions == 'undefined' || refresh)) {
|
||||||
|
|
||||||
return this.coursesProvider.getCoursesAdminAndNavOptions([course.id]).then((options) => {
|
return this.coursesProvider.getCoursesAdminAndNavOptions([course.id]).then((options) => {
|
||||||
course.navOptions = options.navOptions[course.id];
|
course.navOptions = options.navOptions[course.id];
|
||||||
course.admOptions = options.admOptions[course.id];
|
course.admOptions = options.admOptions[course.id];
|
||||||
|
|
|
@ -96,7 +96,7 @@ export class CoreCoursesMyCoursesPage implements OnDestroy {
|
||||||
|
|
||||||
this.courseIds = courseIds.join(',');
|
this.courseIds = courseIds.join(',');
|
||||||
|
|
||||||
if (this.courseIds) {
|
if (this.courseIds && this.coursesProvider.isGetCoursesByFieldAvailable()) {
|
||||||
// Load course image of all the courses.
|
// Load course image of all the courses.
|
||||||
promises.push(this.coursesProvider.getCoursesByField('ids', this.courseIds).then((coursesInfo) => {
|
promises.push(this.coursesProvider.getCoursesByField('ids', this.courseIds).then((coursesInfo) => {
|
||||||
coursesInfo = this.utils.arrayToObject(coursesInfo, 'id');
|
coursesInfo = this.utils.arrayToObject(coursesInfo, 'id');
|
||||||
|
@ -111,12 +111,14 @@ export class CoreCoursesMyCoursesPage implements OnDestroy {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.coursesProvider.canGetAdminAndNavOptions()) {
|
||||||
promises.push(this.coursesProvider.getCoursesAdminAndNavOptions(courseIds).then((options) => {
|
promises.push(this.coursesProvider.getCoursesAdminAndNavOptions(courseIds).then((options) => {
|
||||||
courses.forEach((course) => {
|
courses.forEach((course) => {
|
||||||
course.navOptions = options.navOptions[course.id];
|
course.navOptions = options.navOptions[course.id];
|
||||||
course.admOptions = options.admOptions[course.id];
|
course.admOptions = options.admOptions[course.id];
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
return Promise.all(promises).then(() => {
|
return Promise.all(promises).then(() => {
|
||||||
this.courses = courses;
|
this.courses = courses;
|
||||||
|
|
|
@ -223,6 +223,7 @@ export class CoreCoursesMyOverviewPage implements OnDestroy {
|
||||||
return course.id;
|
return course.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (this.coursesProvider.canGetAdminAndNavOptions()) {
|
||||||
// Load course options of the course.
|
// Load course options of the course.
|
||||||
promises.push(this.coursesProvider.getCoursesAdminAndNavOptions(courseIds).then((options) => {
|
promises.push(this.coursesProvider.getCoursesAdminAndNavOptions(courseIds).then((options) => {
|
||||||
courses.forEach((course) => {
|
courses.forEach((course) => {
|
||||||
|
@ -230,10 +231,11 @@ export class CoreCoursesMyOverviewPage implements OnDestroy {
|
||||||
course.admOptions = options.admOptions[course.id];
|
course.admOptions = options.admOptions[course.id];
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
this.courseIds = courseIds.join(',');
|
this.courseIds = courseIds.join(',');
|
||||||
|
|
||||||
if (this.courseIds) {
|
if (this.courseIds && this.coursesProvider.isGetCoursesByFieldAvailable()) {
|
||||||
// Load course image of all the courses.
|
// Load course image of all the courses.
|
||||||
promises.push(this.coursesProvider.getCoursesByField('ids', this.courseIds).then((coursesInfo) => {
|
promises.push(this.coursesProvider.getCoursesByField('ids', this.courseIds).then((coursesInfo) => {
|
||||||
coursesInfo = this.utils.arrayToObject(coursesInfo, 'id');
|
coursesInfo = this.utils.arrayToObject(coursesInfo, 'id');
|
||||||
|
|
|
@ -33,6 +33,16 @@ export class CoreCoursesProvider {
|
||||||
this.logger = logger.getInstance('CoreCoursesProvider');
|
this.logger = logger.getInstance('CoreCoursesProvider');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether current site supports getting course options.
|
||||||
|
*
|
||||||
|
* @return {boolean} Whether current site supports getting course options.
|
||||||
|
*/
|
||||||
|
canGetAdminAndNavOptions(): boolean {
|
||||||
|
return this.sitesProvider.wsAvailableInCurrentSite('core_course_get_user_navigation_options') &&
|
||||||
|
this.sitesProvider.wsAvailableInCurrentSite('core_course_get_user_administration_options');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get categories. They can be filtered by id.
|
* Get categories. They can be filtered by id.
|
||||||
*
|
*
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content class="has-fab">
|
<ion-content class="has-fab">
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ion-item (click)="login(site.id)" *ngFor="let site of sites; let idx = index">
|
<a ion-item (click)="login(site.id)" *ngFor="let site of sites; let idx = index" detail-none>
|
||||||
<ion-avatar item-start>
|
<ion-avatar item-start>
|
||||||
<img [src]="site.avatar" core-external-content [siteId]="site.id" alt="{{ 'core.pictureof' | translate:{$a: site.fullname} }}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
|
<img [src]="site.avatar" core-external-content [siteId]="site.id" alt="{{ 'core.pictureof' | translate:{$a: site.fullname} }}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
|
||||||
</ion-avatar>
|
</ion-avatar>
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
<button *ngIf="showDelete" item-end ion-button icon-only clear color="danger" (click)="deleteSite($event, idx)" [attr.aria-label]="'core.delete' | translate">
|
<button *ngIf="showDelete" item-end ion-button icon-only clear color="danger" (click)="deleteSite($event, idx)" [attr.aria-label]="'core.delete' | translate">
|
||||||
<ion-icon name="trash"></ion-icon>
|
<ion-icon name="trash"></ion-icon>
|
||||||
</button>
|
</button>
|
||||||
</ion-item>
|
</a>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
<ion-fab bottom right>
|
<ion-fab bottom right>
|
||||||
<button ion-fab (click)="add()" [attr.aria-label]="'core.add' | translate">
|
<button ion-fab (click)="add()" [attr.aria-label]="'core.add' | translate">
|
||||||
|
|
|
@ -15,12 +15,12 @@
|
||||||
<ion-item text-center *ngIf="(!handlers || !handlers.length) && !handlersLoaded">
|
<ion-item text-center *ngIf="(!handlers || !handlers.length) && !handlersLoaded">
|
||||||
<ion-spinner></ion-spinner>
|
<ion-spinner></ion-spinner>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item *ngFor="let handler of handlers" [ngClass]="['core-moremenu-handler', handler.class]" (click)="openHandler(handler)" title="{{ handler.title | translate }}" detail-push>
|
<a ion-item *ngFor="let handler of handlers" [ngClass]="['core-moremenu-handler', handler.class]" (click)="openHandler(handler)" title="{{ handler.title | translate }}" detail-push>
|
||||||
<core-icon [name]="handler.icon" item-start></core-icon>
|
<core-icon [name]="handler.icon" item-start></core-icon>
|
||||||
<p>{{ handler.title | translate}}</p>
|
<p>{{ handler.title | translate}}</p>
|
||||||
<ion-badge item-end *ngIf="handler.showBadge" [hidden]="handler.loading || !handler.badge">{{handler.badge}}</ion-badge>
|
<ion-badge item-end *ngIf="handler.showBadge" [hidden]="handler.loading || !handler.badge">{{handler.badge}}</ion-badge>
|
||||||
<ion-spinner item-end *ngIf="handler.showBadge && handler.loading"></ion-spinner>
|
<ion-spinner item-end *ngIf="handler.showBadge && handler.loading"></ion-spinner>
|
||||||
</ion-item>
|
</a>
|
||||||
<div *ngFor="let item of customItems" class="core-moremenu-customitem">
|
<div *ngFor="let item of customItems" class="core-moremenu-customitem">
|
||||||
<a ion-item *ngIf="item.type != 'embedded'" [href]="item.url" core-link [capture]="item.type == 'app'" [inApp]="item.type == 'inappbrowser'" title="{{item.label}}">
|
<a ion-item *ngIf="item.type != 'embedded'" [href]="item.url" core-link [capture]="item.type == 'app'" [inApp]="item.type == 'inappbrowser'" title="{{item.label}}">
|
||||||
<core-icon [name]="item.icon" item-start></core-icon>
|
<core-icon [name]="item.icon" item-start></core-icon>
|
||||||
|
|
|
@ -8,32 +8,32 @@
|
||||||
<core-split-view>
|
<core-split-view>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ion-item (click)="openHandler('CoreSettingsGeneralPage')" [title]="'core.settings.general' | translate" [class.core-split-item-selected]="'CoreSettingsGeneralPage' == selectedPage" detail-push>
|
<a ion-item (click)="openHandler('CoreSettingsGeneralPage')" [title]="'core.settings.general' | translate" [class.core-split-item-selected]="'CoreSettingsGeneralPage' == selectedPage" detail-push>
|
||||||
<ion-icon name="construct" item-start></ion-icon>
|
<ion-icon name="construct" item-start></ion-icon>
|
||||||
<p>{{ 'core.settings.general' | translate }}</p>
|
<p>{{ 'core.settings.general' | translate }}</p>
|
||||||
</ion-item>
|
</a>
|
||||||
<ion-item (click)="openHandler('CoreSettingsSpaceUsagePage')" [title]="'core.settings.spaceusage' | translate" [class.core-split-item-selected]="'CoreSettingsSpaceUsagePage' == selectedPage" detail-push>
|
<a ion-item (click)="openHandler('CoreSettingsSpaceUsagePage')" [title]="'core.settings.spaceusage' | translate" [class.core-split-item-selected]="'CoreSettingsSpaceUsagePage' == selectedPage" detail-push>
|
||||||
<ion-icon name="stats" item-start></ion-icon>
|
<ion-icon name="stats" item-start></ion-icon>
|
||||||
<p>{{ 'core.settings.spaceusage' | translate }}</p>
|
<p>{{ 'core.settings.spaceusage' | translate }}</p>
|
||||||
</ion-item>
|
</a>
|
||||||
<ion-item (click)="openHandler('CoreSettingsSynchronizationPage')" [title]="'core.settings.synchronization' | translate" [class.core-split-item-selected]="'CoreSettingsSynchronizationPage' == selectedPage" detail-push>
|
<a ion-item (click)="openHandler('CoreSettingsSynchronizationPage')" [title]="'core.settings.synchronization' | translate" [class.core-split-item-selected]="'CoreSettingsSynchronizationPage' == selectedPage" detail-push>
|
||||||
<ion-icon name="sync" item-start></ion-icon>
|
<ion-icon name="sync" item-start></ion-icon>
|
||||||
<p>{{ 'core.settings.synchronization' | translate }}</p>
|
<p>{{ 'core.settings.synchronization' | translate }}</p>
|
||||||
</ion-item>
|
</a>
|
||||||
<ion-item *ngIf="isIOS" (click)="openHandler('CoreSharedFilesListPage', {manage: true})" [title]="'core.sharedfiles.sharedfiles' | translate" [class.core-split-item-selected]="'CoreSharedFilesListPage' == selectedPage" detail-push>
|
<a ion-item *ngIf="isIOS" (click)="openHandler('CoreSharedFilesListPage', {manage: true})" [title]="'core.sharedfiles.sharedfiles' | translate" [class.core-split-item-selected]="'CoreSharedFilesListPage' == selectedPage" detail-push>
|
||||||
<ion-icon name="folder" item-start></ion-icon>
|
<ion-icon name="folder" item-start></ion-icon>
|
||||||
<p>{{ 'core.sharedfiles.sharedfiles' | translate }}</p>
|
<p>{{ 'core.sharedfiles.sharedfiles' | translate }}</p>
|
||||||
</ion-item>
|
</a>
|
||||||
|
|
||||||
<ion-item *ngFor="let handler of handlers" [ngClass]="['core-settings-handler', handler.class]" (click)="openHandler(handler.page, handler.params)" [title]="handler.title | translate" detail-push [class.core-split-item-selected]="handler.page == selectedPage">
|
<a ion-item *ngFor="let handler of handlers" [ngClass]="['core-settings-handler', handler.class]" (click)="openHandler(handler.page, handler.params)" [title]="handler.title | translate" detail-push [class.core-split-item-selected]="handler.page == selectedPage">
|
||||||
<core-icon [name]="handler.icon" item-start *ngIf="handler.icon"></core-icon>
|
<core-icon [name]="handler.icon" item-start *ngIf="handler.icon"></core-icon>
|
||||||
<p>{{ handler.title | translate}}</p>
|
<p>{{ handler.title | translate}}</p>
|
||||||
</ion-item>
|
</a>
|
||||||
|
|
||||||
<ion-item (click)="openHandler('CoreSettingsAboutPage')" [title]="'core.settings.about' | translate" [class.core-split-item-selected]="'CoreSettingsAboutPage' == selectedPage" detail-push>
|
<a ion-item (click)="openHandler('CoreSettingsAboutPage')" [title]="'core.settings.about' | translate" [class.core-split-item-selected]="'CoreSettingsAboutPage' == selectedPage" detail-push>
|
||||||
<ion-icon name="contacts" item-start></ion-icon>
|
<ion-icon name="contacts" item-start></ion-icon>
|
||||||
<p>{{ 'core.settings.about' | translate }}</p>
|
<p>{{ 'core.settings.about' | translate }}</p>
|
||||||
</ion-item>
|
</a>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
</core-split-view>
|
</core-split-view>
|
||||||
|
|
|
@ -213,21 +213,33 @@ export class CoreUserDelegate extends CoreDelegate {
|
||||||
* @return {Subject<CoreUserProfileHandlerToDisplay[]>} Resolved with the handlers.
|
* @return {Subject<CoreUserProfileHandlerToDisplay[]>} Resolved with the handlers.
|
||||||
*/
|
*/
|
||||||
getProfileHandlersFor(user: any, courseId: number): Subject<CoreUserProfileHandlerToDisplay[]> {
|
getProfileHandlersFor(user: any, courseId: number): Subject<CoreUserProfileHandlerToDisplay[]> {
|
||||||
const promises = [];
|
let promise,
|
||||||
|
navOptions,
|
||||||
|
admOptions;
|
||||||
|
|
||||||
this.userHandlers = [];
|
if (this.coursesProvider.canGetAdminAndNavOptions()) {
|
||||||
|
// Get course options.
|
||||||
// Retrieve course options forcing cache.
|
promise = this.coursesProvider.getUserCourses(true).then((courses) => {
|
||||||
this.coursesProvider.getUserCourses(true).then((courses) => {
|
|
||||||
const courseIds = courses.map((course) => {
|
const courseIds = courses.map((course) => {
|
||||||
return course.id;
|
return course.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.coursesProvider.getCoursesAdminAndNavOptions(courseIds).then((options) => {
|
return this.coursesProvider.getCoursesAdminAndNavOptions(courseIds).then((options) => {
|
||||||
// For backwards compatibility we don't modify the courseId.
|
// For backwards compatibility we don't modify the courseId.
|
||||||
const courseIdForOptions = courseId || this.sitesProvider.getCurrentSiteHomeId(),
|
const courseIdForOptions = courseId || this.sitesProvider.getCurrentSiteHomeId();
|
||||||
navOptions = options.navOptions[courseIdForOptions],
|
|
||||||
|
navOptions = options.navOptions[courseIdForOptions];
|
||||||
admOptions = options.admOptions[courseIdForOptions];
|
admOptions = options.admOptions[courseIdForOptions];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
promise = Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.userHandlers = [];
|
||||||
|
|
||||||
|
promise.then(() => {
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
for (const name in this.enabledHandlers) {
|
for (const name in this.enabledHandlers) {
|
||||||
// Checks if the handler is enabled for the user.
|
// Checks if the handler is enabled for the user.
|
||||||
|
@ -258,7 +270,6 @@ export class CoreUserDelegate extends CoreDelegate {
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
this.observableHandlers.next(this.userHandlers);
|
this.observableHandlers.next(this.userHandlers);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
// Never fails.
|
// Never fails.
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
|
|
Loading…
Reference in New Issue