MOBILE-1486 user: Show status indicator on user avatar

main
Pau Ferrer Ocaña 2018-11-15 16:09:55 +01:00
parent bb3a525a5b
commit 5e4e4fc75f
34 changed files with 179 additions and 126 deletions

View File

@ -28,12 +28,7 @@
<h3 margin-horizontal *ngIf="competencies && competencies.statistics.competencycount > 0">{{ 'addon.competency.competencies' | translate }}</h3> <h3 margin-horizontal *ngIf="competencies && competencies.statistics.competencycount > 0">{{ 'addon.competency.competencies' | translate }}</h3>
<ion-card *ngIf="user"> <ion-card *ngIf="user">
<ion-item text-wrap> <ion-item text-wrap>
<ion-avatar *ngIf="user.profileimageurl && user.profileimageurl !== true" item-start> <ion-avatar class="user-avatar" [user]="user" item-start></ion-avatar>
<img [src]="user.profileimageurl" [alt]="'core.pictureof' | translate:{$a: user.fullname}" core-external-content>
</ion-avatar>
<span *ngIf="user.profileimageurl === true" item-start>
<ion-icon name="person"></ion-icon>
</span>
<h2><core-format-text [text]="user.fullname"></core-format-text></h2> <h2><core-format-text [text]="user.fullname"></core-format-text></h2>
</ion-item> </ion-item>
</ion-card> </ion-card>

View File

@ -10,12 +10,7 @@
<core-loading [hideUntil]="competencyLoaded"> <core-loading [hideUntil]="competencyLoaded">
<ion-card *ngIf="user"> <ion-card *ngIf="user">
<ion-item text-wrap> <ion-item text-wrap>
<ion-avatar *ngIf="user.profileimageurl && user.profileimageurl !== true" item-start> <ion-avatar class="user-avatar" [user]="user" item-start></ion-avatar>
<img [src]="user.profileimageurl" [alt]="'core.pictureof' | translate:{$a: user.fullname}" core-external-content>
</ion-avatar>
<span *ngIf="user.profileimageurl === true" item-start>
<ion-icon name="person"></ion-icon>
</span>
<h2><core-format-text [text]="user.fullname"></core-format-text></h2> <h2><core-format-text [text]="user.fullname"></core-format-text></h2>
</ion-item> </ion-item>
</ion-card> </ion-card>
@ -78,9 +73,7 @@
</p> </p>
<ion-card *ngFor="let evidence of competency.evidence"> <ion-card *ngFor="let evidence of competency.evidence">
<a ion-item text-wrap *ngIf="evidence.actionuser" (click)="openUserProfile(evidence.actionuser.id)"> <a ion-item text-wrap *ngIf="evidence.actionuser" (click)="openUserProfile(evidence.actionuser.id)">
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="evidence.actionuser" item-start></ion-avatar>
<img core-external-content [src]="evidence.actionuser.profileimageurlsmall" [alt]="'core.pictureof' | translate:{$a: evidence.actionuser.fullname}" role="presentation">
</ion-avatar>
<h2>{{ evidence.actionuser.fullname }}</h2> <h2>{{ evidence.actionuser.fullname }}</h2>
<p>{{ evidence.timemodified | coreToLocaleString }}</p> <p>{{ evidence.timemodified | coreToLocaleString }}</p>
</a> </a>

View File

@ -10,12 +10,7 @@
<core-loading [hideUntil]="planLoaded"> <core-loading [hideUntil]="planLoaded">
<ion-card *ngIf="user"> <ion-card *ngIf="user">
<ion-item text-wrap> <ion-item text-wrap>
<ion-avatar *ngIf="user.profileimageurl && user.profileimageurl !== true" item-start> <ion-avatar class="user-avatar" [user]="user" item-start></ion-avatar>
<img [src]="user.profileimageurl" [alt]="'core.pictureof' | translate:{$a: user.fullname}" core-external-content>
</ion-avatar>
<span *ngIf="user.profileimageurl === true" item-start>
<ion-icon name="person"></ion-icon>
</span>
<h2><core-format-text [text]="user.fullname"></core-format-text></h2> <h2><core-format-text [text]="user.fullname"></core-format-text></h2>
</ion-item> </ion-item>
</ion-card> </ion-card>

View File

@ -19,9 +19,7 @@
<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 -->
<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> <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 class="user-avatar" [user]="contact" item-start></ion-avatar>
<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>
<h2><core-format-text [text]="contact.fullname"></core-format-text></h2> <h2><core-format-text [text]="contact.fullname"></core-format-text></h2>
</a> </a>
</ng-container> </ng-container>

View File

@ -17,9 +17,7 @@
<ion-note item-end>{{ search.results.length }}</ion-note> <ion-note item-end>{{ search.results.length }}</ion-note>
</ion-item-divider> </ion-item-divider>
<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> <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 class="user-avatar" [user]="result" item-start></ion-avatar>
<img src="{{result.profileimageurl}}" [alt]="'core.pictureof' | translate:{$a: result.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
</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>
</a> </a>
@ -27,9 +25,7 @@
<ion-list *ngIf="!search.showResults" no-margin> <ion-list *ngIf="!search.showResults" no-margin>
<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> <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 class="user-avatar" [user]="discussion" item-start></ion-avatar>
<img src="{{discussion.profileimageurl}}" [alt]="'core.pictureof' | translate:{$a: discussion.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<h2> <h2>
<core-format-text [text]="discussion.fullname"></core-format-text> <core-format-text [text]="discussion.fullname"></core-format-text>
<ion-note *ngIf="discussion.message.timecreated > 0 || discussion.unread"> <ion-note *ngIf="discussion.message.timecreated > 0 || discussion.unread">

View File

@ -2,9 +2,7 @@
<!-- User and status of the submission. --> <!-- User and status of the submission. -->
<a ion-item text-wrap *ngIf="!blindMarking && user" (click)="openUserProfile(submitId)" [title]="user.fullname"> <a ion-item text-wrap *ngIf="!blindMarking && user" (click)="openUserProfile(submitId)" [title]="user.fullname">
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="user" item-start></ion-avatar>
<img [src]="user.profileimageurl" core-external-content [alt]="'core.pictureof' | translate:{$a: user.fullname}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<h2>{{ user.fullname }}</h2> <h2>{{ user.fullname }}</h2>
<ng-container *ngTemplateOutlet="submissionStatus"></ng-container> <ng-container *ngTemplateOutlet="submissionStatus"></ng-container>
</a> </a>
@ -113,9 +111,7 @@
<h2>{{ 'addon.mod_assign.userswhoneedtosubmit' | translate: {$a: ''} }}</h2> <h2>{{ 'addon.mod_assign.userswhoneedtosubmit' | translate: {$a: ''} }}</h2>
<div *ngFor="let user of membersToSubmit"> <div *ngFor="let user of membersToSubmit">
<a ion-item text-wrap *ngIf="user.fullname" (click)="openUserProfile(user.id)" [title]="user.fullname"> <a ion-item text-wrap *ngIf="user.fullname" (click)="openUserProfile(user.id)" [title]="user.fullname">
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="user" item-start></ion-avatar>
<img [src]="user.profileimageurl" core-external-content [alt]="'core.pictureof' | translate:{$a: user.fullname}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<h2>{{ user.fullname }}</h2> <h2>{{ user.fullname }}</h2>
</a> </a>
<ion-item text-wrap *ngIf="!user.fullname"> <ion-item text-wrap *ngIf="!user.fullname">
@ -213,9 +209,7 @@
<!-- Data about the grader (teacher who graded). --> <!-- Data about the grader (teacher who graded). -->
<a 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 class="user-avatar" [user]="grader" item-start></ion-avatar>
<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>
<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>

View File

@ -18,9 +18,7 @@
<!-- List of submissions. --> <!-- List of submissions. -->
<ng-container *ngFor="let submission of submissions"> <ng-container *ngFor="let submission of submissions">
<a ion-item text-wrap (click)="loadSubmission(submission)" [class.core-split-item-selected]="submission.id == selectedSubmissionId"> <a ion-item text-wrap (click)="loadSubmission(submission)" [class.core-split-item-selected]="submission.id == selectedSubmissionId">
<ion-avatar item-start *ngIf="submission.userprofileimageurl"> <ion-avatar class="user-avatar" [user]="submission" item-start></ion-avatar>
<img [src]="submission.userprofileimageurl" [alt]="'core.pictureof' | translate:{$a: submission.userfullname}" core-external-content role="presentation" onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<h2 *ngIf="submission.userfullname">{{submission.userfullname}}</h2> <h2 *ngIf="submission.userfullname">{{submission.userfullname}}</h2>
<h2 *ngIf="!submission.userfullname">{{ 'addon.mod_assign.hiddenuser' | translate }}{{submission.blindid}}</h2> <h2 *ngIf="!submission.userfullname">{{ 'addon.mod_assign.hiddenuser' | translate }}{{submission.blindid}}</h2>
<p *ngIf="assign.teamsubmission"> <p *ngIf="assign.teamsubmission">

View File

@ -38,9 +38,7 @@
</div> </div>
<ion-item text-wrap *ngIf="!message.system && message.message.substr(0, 4) != 'beep'" class="addon-mod-chat-message"> <ion-item text-wrap *ngIf="!message.system && message.message.substr(0, 4) != 'beep'" class="addon-mod-chat-message">
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="message" item-start></ion-avatar>
<img [src]="message.userprofileimageurl" onError="this.src='assets/img/user-avatar.png'" core-external-content [alt]="'core.pictureof' | translate:{$a: message.userfullname}" role="presentation">
</ion-avatar>
<h2> <h2>
<p float-end>{{ message.timestamp * 1000 | coreFormatDate:"dftimedate" }}</p> <p float-end>{{ message.timestamp * 1000 | coreFormatDate:"dftimedate" }}</p>
<core-format-text [text]="message.userfullname"></core-format-text> <core-format-text [text]="message.userfullname"></core-format-text>

View File

@ -11,9 +11,7 @@
<ion-content> <ion-content>
<core-loading [hideUntil]="usersLoaded"> <core-loading [hideUntil]="usersLoaded">
<ion-item text-wrap *ngFor="let user of users" [class.addon-mod-chat-user]="currentUserId != user.id && isOnline"> <ion-item text-wrap *ngFor="let user of users" [class.addon-mod-chat-user]="currentUserId != user.id && isOnline">
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="user" item-start></ion-avatar>
<img [src]="user.profileimageurl" onError="this.src='assets/img/user-avatar.png'" core-external-content [alt]="'core.pictureof' | translate:{$a: user.fullname}" role="presentation">
</ion-avatar>
<h2><core-format-text [text]="user.fullname"></core-format-text></h2> <h2><core-format-text [text]="user.fullname"></core-format-text></h2>
<ng-container *ngIf="currentUserId != user.id && isOnline"> <ng-container *ngIf="currentUserId != user.id && isOnline">
<button ion-button clear icon-left (click)="talkTo(user)"> <button ion-button clear icon-left (click)="talkTo(user)">

View File

@ -82,9 +82,7 @@
<p>{{ 'addon.mod_choice.numberofuser' | translate }}: {{ result.numberofuser }} ({{ 'core.percentagenumber' | translate: {$a: result.percentageamount} }})</p> <p>{{ 'addon.mod_choice.numberofuser' | translate }}: {{ result.numberofuser }} ({{ 'core.percentagenumber' | translate: {$a: result.percentageamount} }})</p>
</ion-item-divider> </ion-item-divider>
<a ion-item *ngFor="let user of result.userresponses" core-user-link [courseId]="courseid" [userId]="user.userid" [title]="user.fullname" text-wrap> <a ion-item *ngFor="let user of result.userresponses" core-user-link [courseId]="courseid" [userId]="user.userid" [title]="user.fullname" text-wrap>
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="user" item-start [courseId]="courseid"></ion-avatar>
<img [src]="user.profileimageurl" [alt]="'core.pictureof' | translate:{$a: user.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<p>{{user.fullname}}</p> <p>{{user.fullname}}</p>
</a> </a>
</ion-item-group> </ion-item-group>

View File

@ -6,10 +6,8 @@
<ion-content> <ion-content>
<core-loading [hideUntil]="feedbackLoaded"> <core-loading [hideUntil]="feedbackLoaded">
<ion-list no-margin> <ion-list no-margin>
<a *ngIf="attempt.fullname" ion-item text-wrap core-user-link [userId]="attempt.userid" [attr.aria-label]=" 'core.user.viewprofile' | translate" core-user-link [courseId]="attempt.courseid" [title]="attempt.fullname"> <a *ngIf="attempt.fullname" ion-item text-wrap core-user-link [userId]="attempt.userid" [attr.aria-label]=" 'core.user.viewprofile' | translate" [courseId]="attempt.courseid" [title]="attempt.fullname">
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="attempt" item-start></ion-avatar>
<img [src]="attempt.profileimageurl" [alt]="'core.pictureof' | translate:{$a: attempt.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<h2>{{attempt.fullname}}</h2> <h2>{{attempt.fullname}}</h2>
<p *ngIf="attempt.timemodified">{{attempt.timemodified * 1000 | coreFormatDate:"LLL"}}</p> <p *ngIf="attempt.timemodified">{{attempt.timemodified * 1000 | coreFormatDate:"LLL"}}</p>
</a> </a>

View File

@ -21,9 +21,7 @@
</ion-item-divider> </ion-item-divider>
<ng-container *ngIf="total > 0"> <ng-container *ngIf="total > 0">
<ion-item *ngFor="let user of users" text-wrap> <ion-item *ngFor="let user of users" text-wrap>
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="user" item-start></ion-avatar>
<img [src]="user.profileimageurl" [alt]="'core.pictureof' | translate:{$a: user.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<h2><core-format-text [text]="user.fullname"></core-format-text></h2> <h2><core-format-text [text]="user.fullname"></core-format-text></h2>
<p> <p>
<ion-badge color="success" *ngIf="user.started"> <ion-badge color="success" *ngIf="user.started">

View File

@ -22,9 +22,7 @@
{{ 'addon.mod_feedback.non_anonymous_entries' | translate : {$a: responses.total } }} {{ 'addon.mod_feedback.non_anonymous_entries' | translate : {$a: responses.total } }}
</ion-item-divider> </ion-item-divider>
<a *ngFor="let attempt of responses.attempts" ion-item text-wrap (click)="gotoAttempt(attempt)" [class.core-split-item-selected]="attempt.id == attemptId"> <a *ngFor="let attempt of responses.attempts" ion-item text-wrap (click)="gotoAttempt(attempt)" [class.core-split-item-selected]="attempt.id == attemptId">
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="attempt" item-start></ion-avatar>
<img [src]="attempt.profileimageurl" [alt]="'core.pictureof' | translate:{$a: attempt.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<h2><core-format-text [text]="attempt.fullname"></core-format-text></h2> <h2><core-format-text [text]="attempt.fullname"></core-format-text></h2>
<p *ngIf="attempt.timemodified">{{attempt.timemodified * 1000 | coreFormatDate: "LLL"}}</p> <p *ngIf="attempt.timemodified">{{attempt.timemodified * 1000 | coreFormatDate: "LLL"}}</p>
</a> </a>

View File

@ -27,9 +27,7 @@
<ng-container *ngIf="forum && discussions.length > 0"> <ng-container *ngIf="forum && discussions.length > 0">
<ion-card *ngFor="let discussion of offlineDiscussions" (click)="openNewDiscussion(discussion.timecreated)" [class.addon-forum-discussion-selected]="discussion.timecreated == -selectedDiscussion"> <ion-card *ngFor="let discussion of offlineDiscussions" (click)="openNewDiscussion(discussion.timecreated)" [class.addon-forum-discussion-selected]="discussion.timecreated == -selectedDiscussion">
<ion-item text-wrap> <ion-item text-wrap>
<ion-avatar item-start core-user-link [userId]="discussion.userid" [courseId]="courseId"> <ion-avatar class="user-avatar" [user]="discussion" item-start [courseId]="courseId"></ion-avatar>
<img [src]="discussion.userpictureurl" onError="this.src='assets/img/user-avatar.png'" core-external-content [alt]="'core.pictureof' | translate:{$a: discussion.userfullname}" role="presentation">
</ion-avatar>
<h2><core-format-text [text]="discussion.subject"></core-format-text></h2> <h2><core-format-text [text]="discussion.subject"></core-format-text></h2>
<p *ngIf="discussion.userfullname"> <p *ngIf="discussion.userfullname">
<ion-note float-end padding-left><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</ion-note> <ion-note float-end padding-left><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</ion-note>
@ -45,9 +43,7 @@
</ion-card> </ion-card>
<ion-card *ngFor="let discussion of discussions" (click)="openDiscussion(discussion)" [class.addon-forum-discussion-selected]="discussion.discussion == selectedDiscussion"> <ion-card *ngFor="let discussion of discussions" (click)="openDiscussion(discussion)" [class.addon-forum-discussion-selected]="discussion.discussion == selectedDiscussion">
<ion-item text-wrap> <ion-item text-wrap>
<ion-avatar item-start core-user-link [userId]="discussion.userid" [courseId]="courseId"> <ion-avatar class="user-avatar" [user]="discussion" item-start [courseId]="courseId"></ion-avatar>
<img [src]="discussion.userpictureurl" onError="this.src='assets/img/user-avatar.png'" core-external-content [alt]="'core.pictureof' | translate:{$a: discussion.userfullname}" role="presentation">
</ion-avatar>
<h2><core-icon name="fa-map-pin" *ngIf="discussion.pinned"></core-icon> <core-format-text [text]="discussion.subject"></core-format-text></h2> <h2><core-icon name="fa-map-pin" *ngIf="discussion.pinned"></core-icon> <core-format-text [text]="discussion.subject"></core-format-text></h2>
<p> <p>
<ion-note float-end padding-left text-end> <ion-note float-end padding-left text-end>

View File

@ -1,8 +1,6 @@
<ion-card-header text-wrap no-padding > <ion-card-header text-wrap no-padding >
<ion-item text-wrap> <ion-item text-wrap>
<ion-avatar item-start (click)="openUserProfile(post.userid)"> <ion-avatar class="user-avatar" [user]="post" item-start (click)="openUserProfile(post.userid)"></ion-avatar>
<img [src]="post.userpictureurl" onError="this.src='assets/img/user-avatar.png'" core-external-content [alt]="'core.pictureof' | translate:{$a: post.userfullname}" role="presentation">
</ion-avatar>
<h2><span [class.core-bold]="post.parent == 0"><core-format-text [text]="post.subject"></core-format-text></span></h2> <h2><span [class.core-bold]="post.parent == 0"><core-format-text [text]="post.subject"></core-format-text></span></h2>
<p> <p>
<ion-note float-end padding-left *ngIf="!post.modified"><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</ion-note> <ion-note float-end padding-left *ngIf="!post.modified"><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</ion-note>

View File

@ -11,9 +11,7 @@
<core-loading [hideUntil]="loaded"> <core-loading [hideUntil]="loaded">
<ng-container *ngIf="entry"> <ng-container *ngIf="entry">
<ion-item text-wrap *ngIf="showAuthor"> <ion-item text-wrap *ngIf="showAuthor">
<ion-avatar item-start (click)="openUserProfile(post.userid)"> <ion-avatar class="user-avatar" [user]="entry" (click)="openUserProfile(post.userid)" item-start></ion-avatar>
<img [src]="entry.userpictureurl" onError="this.src='assets/img/user-avatar.png'" core-external-content [alt]="'core.pictureof' | translate:{$a: entry.userfullname}" role="presentation">
</ion-avatar>
<h2><core-format-text [text]="entry.concept"></core-format-text></h2> <h2><core-format-text [text]="entry.concept"></core-format-text></h2>
<ion-note item-end *ngIf="showDate">{{ entry.timemodified | coreDateDayOrTime }}</ion-note> <ion-note item-end *ngIf="showDate">{{ entry.timemodified | coreDateDayOrTime }}</ion-note>
<p><core-format-text [text]="entry.userfullname"></core-format-text></p> <p><core-format-text [text]="entry.userfullname"></core-format-text></p>

View File

@ -233,9 +233,7 @@
</ion-card-header> </ion-card-header>
<a ion-item text-wrap *ngFor="let student of overview.students" [navPush]="'AddonModLessonUserRetakePage'" [navParams]="{courseId: courseId, lessonId: lesson.id, userId: student.id}"> <a ion-item text-wrap *ngFor="let student of overview.students" [navPush]="'AddonModLessonUserRetakePage'" [navParams]="{courseId: courseId, lessonId: lesson.id, userId: student.id}">
<ion-avatar item-start *ngIf="student.profileimageurl" core-user-link [userId]="student.id" [courseId]="courseId"> <ion-avatar class="user-avatar" [user]="student" item-start [userId]="student.id" [courseId]="courseId"></ion-avatar>
<img [src]="student.profileimageurl" [alt]="'core.pictureof' | translate:{$a: student.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'" role="presentation">
</ion-avatar>
<h2>{{ student.fullname }}</h2> <h2>{{ student.fullname }}</h2>
<core-progress-bar [progress]="student.bestgrade"></core-progress-bar> <core-progress-bar [progress]="student.bestgrade"></core-progress-bar>
</a> </a>

View File

@ -12,9 +12,7 @@
<ion-list *ngIf="student"> <ion-list *ngIf="student">
<!-- Student data. --> <!-- Student data. -->
<a ion-item text-wrap core-user-link [userId]="student.id" [courseId]="courseId" [title]="student.fullname"> <a ion-item text-wrap core-user-link [userId]="student.id" [courseId]="courseId" [title]="student.fullname">
<ion-avatar *ngIf="student.profileimageurl" item-start> <ion-avatar class="user-avatar" [user]="student" item-start [userId]="student.id" [courseId]="courseId"></ion-avatar>
<img [src]="student.profileimageurl" [alt]="'core.pictureof' | translate:{$a: student.fullname}" core-external-content role="presentation">
</ion-avatar>
<h2>{{student.fullname}}</h2> <h2>{{student.fullname}}</h2>
<core-progress-bar [progress]="student.bestgrade"></core-progress-bar> <core-progress-bar [progress]="student.bestgrade"></core-progress-bar>
</a> </a>

View File

@ -1,8 +1,6 @@
<core-loading [hideUntil]="loaded"> <core-loading [hideUntil]="loaded">
<a ion-item *ngIf="summary" text-wrap [attr.detail-none]="canViewAssessment && !canSelfAssess? null : true" (click)="gotoAssessment()"> <a ion-item *ngIf="summary" text-wrap [attr.detail-none]="canViewAssessment && !canSelfAssess? null : true" (click)="gotoAssessment()">
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="profile" item-start [courseId]="courseId" [userId]="profile && profile.id"></ion-avatar>
<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>
<h2 *ngIf="profile && profile.fullname">{{profile.fullname}}</h2> <h2 *ngIf="profile && profile.fullname">{{profile.fullname}}</h2>
<p *ngIf="showGrade(assessment.grade)"> <p *ngIf="showGrade(assessment.grade)">

View File

@ -1,9 +1,7 @@
<core-loading [hideUntil]="loaded"> <core-loading [hideUntil]="loaded">
<div *ngIf="!summary"> <div *ngIf="!summary">
<ion-list-header text-wrap> <ion-list-header text-wrap>
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="profile" item-start></ion-avatar>
<img [src]="profile && profile.profileimageurl" core-external-content [alt]="'core.pictureof' | translate:{$a: profile && profile.fullname}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<h2>{{submission.title}}</h2> <h2>{{submission.title}}</h2>
<p *ngIf="profile && profile.fullname">{{profile.fullname}}</p> <p *ngIf="profile && profile.fullname">{{profile.fullname}}</p>
<p *ngIf="showGrade(submission.submissiongrade)" [class.addon-has-overriden-grade]="showGrade(submission.submissiongradeover)"> <p *ngIf="showGrade(submission.submissiongrade)" [class.addon-has-overriden-grade]="showGrade(submission.submissiongradeover)">
@ -34,9 +32,7 @@
<core-local-file *ngIf="attachment.name" [file]="attachment"></core-local-file> <core-local-file *ngIf="attachment.name" [file]="attachment"></core-local-file>
</ion-item> </ion-item>
<ion-item text-wrap *ngIf="viewDetails && submission.feedbackauthor"> <ion-item text-wrap *ngIf="viewDetails && submission.feedbackauthor">
<ion-avatar item-start *ngIf="evaluateByProfile"> <ion-avatar class="user-avatar" [user]="evaluateByProfile" item-start [courseId]="courseId" [userId]="evaluateByProfile.id"></ion-avatar>
<img [src]="evaluateByProfile.profileimageurl" core-external-content core-user-link [courseId]="courseId" [userId]="evaluateByProfile.id" [alt]="'core.pictureof' | translate:{$a: evaluateByProfile.fullname}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<h2 *ngIf="evaluateByProfile && evaluateByProfile.fullname">{{ 'addon.mod_workshop.feedbackby' | translate : {$a: evaluateByProfile.fullname} }}</h2> <h2 *ngIf="evaluateByProfile && evaluateByProfile.fullname">{{ 'addon.mod_workshop.feedbackby' | translate : {$a: evaluateByProfile.fullname} }}</h2>
<core-format-text [text]="submission.feedbackauthor"></core-format-text> <core-format-text [text]="submission.feedbackauthor"></core-format-text>
@ -50,9 +46,7 @@
</div> </div>
<a ion-item text-wrap *ngIf="summary" [attr.detail-none]="submission.timemodified ? null : true" (click)="gotoSubmission()"> <a ion-item text-wrap *ngIf="summary" [attr.detail-none]="submission.timemodified ? null : true" (click)="gotoSubmission()">
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="profile" item-start [courseId]="courseId" [userId]="profile && profile.id"></ion-avatar>
<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>
<h2>{{submission.title}}</h2> <h2>{{submission.title}}</h2>
<p *ngIf="profile && profile.fullname">{{profile.fullname}}</p> <p *ngIf="profile && profile.fullname">{{profile.fullname}}</p>

View File

@ -15,9 +15,8 @@
<core-loading [hideUntil]="loaded"> <core-loading [hideUntil]="loaded">
<ion-item text-wrap> <ion-item text-wrap>
<ion-avatar item-start *ngIf="profile"> <ion-avatar class="user-avatar" [user]="profile" item-start [courseId]="courseId" [userId]="profile.id"></ion-avatar>
<img [src]="profile.profileimageurl" core-external-content core-user-link [courseId]="courseId" [userId]="profile.id" [alt]="'core.pictureof' | translate:{$a: profile.fullname}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<h2 *ngIf="profile && profile.fullname">{{profile.fullname}}</h2> <h2 *ngIf="profile && profile.fullname">{{profile.fullname}}</h2>
<p *ngIf="workshop && assessment && showGrade(assessment.grade)"> <p *ngIf="workshop && assessment && showGrade(assessment.grade)">
@ -66,9 +65,7 @@
</form> </form>
<ion-list *ngIf="!evaluating && evaluate && evaluate.text"> <ion-list *ngIf="!evaluating && evaluate && evaluate.text">
<ion-item text-wrap> <ion-item text-wrap>
<ion-avatar item-start *ngIf="evaluateGradingByProfile"> <ion-avatar class="user-avatar" [user]="evaluateGradingByProfile" item-start [courseId]="courseId" [userId]="evaluateGradingByProfile.id"></ion-avatar>
<img [src]="evaluateGradingByProfile.profileimageurl" core-external-content core-user-link [courseId]="courseId" [userId]="evaluateGradingByProfile.id" [alt]="'core.pictureof' | translate:{$a: evaluateGradingByProfile.fullname}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<h2 *ngIf="evaluateGradingByProfile && evaluateGradingByProfile.fullname">{{ 'addon.mod_workshop.feedbackby' | translate : {$a: evaluateGradingByProfile.fullname} }}</h2> <h2 *ngIf="evaluateGradingByProfile && evaluateGradingByProfile.fullname">{{ 'addon.mod_workshop.feedbackby' | translate : {$a: evaluateGradingByProfile.fullname} }}</h2>
<core-format-text [text]="evaluate.text"></core-format-text> <core-format-text [text]="evaluate.text"></core-format-text>
</ion-item> </ion-item>

View File

@ -36,9 +36,7 @@
<ion-list *ngIf="!canAddFeedback && evaluate && evaluate.text"> <ion-list *ngIf="!canAddFeedback && evaluate && evaluate.text">
<ion-item text-wrap> <ion-item text-wrap>
<ion-avatar item-start *ngIf="evaluateByProfile"> <ion-avatar class="user-avatar" [user]="evaluateByProfile" item-start [courseId]="courseId" [userId]="evaluateByProfile.id"></ion-avatar>
<img [src]="evaluateByProfile.profileimageurl" core-external-content core-user-link [courseId]="courseId" [userId]="evaluateByProfile.id" [alt]="'core.pictureof' | translate:{$a: evaluateByProfile.fullname}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<h2 *ngIf="evaluateByProfile && evaluateByProfile.fullname">{{ 'addon.mod_workshop.feedbackby' | translate : {$a: evaluateByProfile.fullname} }}</h2> <h2 *ngIf="evaluateByProfile && evaluateByProfile.fullname">{{ 'addon.mod_workshop.feedbackby' | translate : {$a: evaluateByProfile.fullname} }}</h2>
<core-format-text [text]="evaluate.text"></core-format-text> <core-format-text [text]="evaluate.text"></core-format-text>
</ion-item> </ion-item>
@ -97,9 +95,7 @@
<ion-list *ngIf="assessmentId && !access.assessingallowed && assessment.feedbackreviewer"> <ion-list *ngIf="assessmentId && !access.assessingallowed && assessment.feedbackreviewer">
<ion-item text-wrap> <ion-item text-wrap>
<ion-avatar item-start *ngIf="evaluateGradingByProfile"> <ion-avatar class="user-avatar" [user]="evaluateGradingByProfile" item-start [courseId]="courseId" [userId]="evaluateGradingByProfile.id"></ion-avatar>
<img [src]="evaluateGradingByProfile.profileimageurl" core-external-content core-user-link [courseId]="courseId" [userId]="evaluateGradingByProfile.id" [alt]="'core.pictureof' | translate:{$a: evaluateGradingByProfile.fullname}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<h2 *ngIf="evaluateGradingByProfile && evaluateGradingByProfile.fullname">{{ 'addon.mod_workshop.feedbackby' | translate : {$a: evaluateGradingByProfile.fullname} }}</h2> <h2 *ngIf="evaluateGradingByProfile && evaluateGradingByProfile.fullname">{{ 'addon.mod_workshop.feedbackby' | translate : {$a: evaluateGradingByProfile.fullname} }}</h2>
<core-format-text [text]="assessment.feedbackreviewer"></core-format-text> <core-format-text [text]="assessment.feedbackreviewer"></core-format-text>
</ion-item> </ion-item>

View File

@ -27,9 +27,7 @@
<ion-list *ngIf="notes && notes.length > 0"> <ion-list *ngIf="notes && notes.length > 0">
<ion-card *ngFor="let note of notes"> <ion-card *ngFor="let note of notes">
<ion-item text-wrap> <ion-item text-wrap>
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="note" item-start></ion-avatar>
<img [src]="note.userprofileimageurl || 'assets/img/user-avatar.png'" core-external-content core-user-link [userId]="note.userid" [courseId]="note.courseid" [alt]="'core.pictureof' | translate:{$a: note.userfullname}" role="presentation">
</ion-avatar>
<h2>{{note.userfullname}}</h2> <h2>{{note.userfullname}}</h2>
<p *ngIf="!note.offline" item-end>{{note.lastmodified | coreDateDayOrTime}}</p> <p *ngIf="!note.offline" item-end>{{note.lastmodified | coreDateDayOrTime}}</p>
<p *ngIf="note.offline" item-end><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</p> <p *ngIf="note.offline" item-end><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</p>

View File

@ -19,9 +19,7 @@
</div> </div>
<ion-card *ngFor="let notification of notifications"> <ion-card *ngFor="let notification of notifications">
<ion-item> <ion-item>
<ion-avatar item-start core-user-link [userId]="notification.useridfrom" [courseId]="notification.courseid"> <ion-avatar class="user-avatar" [user]="notification" item-start [profileUrl]="notification.profileimageurlfrom" [fullname]="notification.userfromfullname" [userId]="notification.useridfrom" [courseId]="notification.courseid"></ion-avatar>
<img [src]="notification.profileimageurlfrom || 'assets/img/user-avatar.png'" core-external-content [alt]="'core.pictureof' | translate:{$a: notification.userfromfullname}" role="presentation">
</ion-avatar>
<h2>{{notification.userfromfullname}}</h2> <h2>{{notification.userfromfullname}}</h2>
<div item-end *ngIf="!notification.timeread"><core-icon name="fa-circle" color="primary"></core-icon></div> <div item-end *ngIf="!notification.timeread"><core-icon name="fa-circle" color="primary"></core-icon></div>
<p>{{notification.timecreated | coreDateDayOrTime}}</p> <p>{{notification.timecreated | coreDateDayOrTime}}</p>

View File

@ -52,7 +52,7 @@ export class CoreChronoComponent implements OnChanges, OnDestroy {
} }
/** /**
* Component being initialized. * Component being changed.
*/ */
ngOnChanges(changes: { [name: string]: SimpleChange }): void { ngOnChanges(changes: { [name: string]: SimpleChange }): void {
if (changes && changes.running) { if (changes && changes.running) {

View File

@ -50,6 +50,7 @@ import { CoreAttachmentsComponent } from './attachments/attachments';
import { CoreIonTabsComponent } from './ion-tabs/ion-tabs'; import { CoreIonTabsComponent } from './ion-tabs/ion-tabs';
import { CoreIonTabComponent } from './ion-tabs/ion-tab'; import { CoreIonTabComponent } from './ion-tabs/ion-tab';
import { CoreInfiniteLoadingComponent } from './infinite-loading/infinite-loading'; import { CoreInfiniteLoadingComponent } from './infinite-loading/infinite-loading';
import { CoreUserAvatarComponent } from './user-avatar/user-avatar';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -85,7 +86,8 @@ import { CoreInfiniteLoadingComponent } from './infinite-loading/infinite-loadin
CoreAttachmentsComponent, CoreAttachmentsComponent,
CoreIonTabsComponent, CoreIonTabsComponent,
CoreIonTabComponent, CoreIonTabComponent,
CoreInfiniteLoadingComponent CoreInfiniteLoadingComponent,
CoreUserAvatarComponent
], ],
entryComponents: [ entryComponents: [
CoreContextMenuPopoverComponent, CoreContextMenuPopoverComponent,
@ -128,7 +130,8 @@ import { CoreInfiniteLoadingComponent } from './infinite-loading/infinite-loadin
CoreAttachmentsComponent, CoreAttachmentsComponent,
CoreIonTabsComponent, CoreIonTabsComponent,
CoreIonTabComponent, CoreIonTabComponent,
CoreInfiniteLoadingComponent CoreInfiniteLoadingComponent,
CoreUserAvatarComponent
] ]
}) })
export class CoreComponentsModule {} export class CoreComponentsModule {}

View File

@ -0,0 +1,2 @@
<img src="{{profileUrl}}" [alt]="'core.pictureof' | translate:{$a: fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'" role="presentation" [siteId]="siteId || null" (click)="gotoProfile($event)">
<span *ngIf="isOnline()" class="contact-status online"></span>

View File

@ -0,0 +1,15 @@
ion-avatar.user-avatar {
position: relative;
.contact-status {
position: absolute;
@include position(null, 0, 0, null);
width: 14px;
height: 14px;
border-radius: 50%;
&.online {
border: 1px solid white;
background-color: $core-online-color;
}
}
}

View File

@ -0,0 +1,113 @@
// (C) Copyright 2015 Martin Dougiamas
//
// 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 { Component, Input, OnInit, OnChanges, SimpleChange } from '@angular/core';
import { NavController } from 'ionic-angular';
import { CoreSitesProvider } from '@providers/sites';
/**
* Component to display a "user avatar".
*
* Example: <core-user-avatar [user]="participant"></core-user-avatar>
*/
@Component({
selector: 'ion-avatar.user-avatar',
templateUrl: 'core-user-avatar.html'
})
export class CoreUserAvatarComponent implements OnInit, OnChanges {
@Input() user: any;
// The following params will override the ones in user object.
@Input() profileUrl?: string;
@Input() fullname?: string;
@Input() protected userId?: number; // If provided or found it will be used to link the image to the profile.
@Input() protected courseId?: number;
// Variable to check if we consider this user online or not.
protected timetoshowusers = 300000; // Miliseconds default.
protected myUser = false;
protected currentUserId: number;
constructor(private navCtrl: NavController, private sitesProvider: CoreSitesProvider) {
this.currentUserId = this.sitesProvider.getCurrentSiteUserId();
}
/**
* Component being initialized.
*/
ngOnInit(): void {
console.error(this.user);
this.setFields();
// @TODO: This setting is not currently available so we are always using the default setting.
/*if (!this.myUser) {
let minutes = 5;
this.sitesProvider.getCurrentSite().getConfig('block_online_users_timetosee').then((timetosee) => {
minutes = timetosee || minutes;
}).catch(() => {
// Ignore errors.
}).finally(() => {
this.timetoshowusers = minutes * 60000;
});
}*/
}
/**
* Listen to changes.
*/
ngOnChanges(changes: { [name: string]: SimpleChange }): void {
// If something change, update the fields.
if (changes) {
this.setFields();
}
}
/**
* Set fields from user.
*/
protected setFields(): void {
this.profileUrl = this.profileUrl || this.user.profileimageurl || this.user.userprofileimageurl ||
this.user.userpictureurl || this.user.profileimageurlsmall;
this.fullname = this.fullname || this.user.fullname || this.user.userfullname;
this.userId = this.userId || this.user.userid;
this.courseId = this.courseId || this.user.courseid;
// If not available we cannot ensure the avatar is from the current user.
this.myUser = this.userId && this.userId == this.currentUserId;
}
/**
* Helper function for checking the time meets the 'online' condition.
*
* @return boolean
*/
isOnline(): boolean {
const time = new Date().getTime() - this.timetoshowusers;
return !this.myUser && ((this.user.lastaccess && this.user.lastaccess * 1000 >= time) || this.user.isonline);
}
/**
* Function executed image clicked.
*/
gotoProfile(event: any): void {
// If the event prevented default action, do nothing.
if (!event.defaultPrevented && this.userId) {
event.preventDefault();
event.stopPropagation();
this.navCtrl.push('CoreUserProfilePage', { userId: this.userId, courseId: this.courseId });
}
}
}

View File

@ -12,9 +12,7 @@
<ion-card *ngFor="let comment of comments"> <ion-card *ngFor="let comment of comments">
<ion-item text-wrap> <ion-item text-wrap>
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="comment" item-start></ion-avatar>
<img [src]="comment.profileimageurl" onError="this.src='assets/img/user-avatar.png'" core-external-content core-user-link [userId]="comment.userid" [alt]="'core.pictureof' | translate:{$a: comment.fullname}" role="presentation">
</ion-avatar>
<h2>{{ comment.fullname }}</h2> <h2>{{ comment.fullname }}</h2>
<p>{{ comment.time }}</p> <p>{{ comment.time }}</p>
</ion-item> </ion-item>

View File

@ -26,10 +26,8 @@
<ng-container text-wrap *ngIf="course.contacts && course.contacts.length"> <ng-container text-wrap *ngIf="course.contacts && course.contacts.length">
<ion-item-divider color="light">{{ 'core.teachers' | translate }}</ion-item-divider> <ion-item-divider color="light">{{ 'core.teachers' | translate }}</ion-item-divider>
<a ion-item text-wrap *ngFor="let contact of course.contacts" core-user-link userId="{{contact.id}}" courseId="{{isEnrolled ? course.id : null}}" [attr.aria-label]="'core.viewprofile' | translate"> <a ion-item text-wrap *ngFor="let contact of course.contacts" core-user-link [userId]="contact.id" [courseId]="isEnrolled ? course.id : null" [attr.aria-label]="'core.viewprofile' | translate">
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="contact" item-start [userId]="contact.id" [courseId]="isEnrolled ? course.id : null"></ion-avatar>
<img [src]="contact.userpictureurl" onError="this.src='assets/img/user-avatar.png'" core-external-content [alt]="'core.pictureof' | translate:{$a: contact.userfullname}" role="presentation">
</ion-avatar>
<h2>{{contact.fullname}}</h2> <h2>{{contact.fullname}}</h2>
</a> </a>
<ion-item-divider color="light"></ion-item-divider> <ion-item-divider color="light"></ion-item-divider>

View File

@ -5,10 +5,8 @@
</ion-header> </ion-header>
<ion-content> <ion-content>
<ion-list> <ion-list>
<a ion-item core-user-link userId="{{siteInfo.userid}}"> <a ion-item core-user-link [userId]="siteInfo.userid">
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="siteInfo" item-start></ion-avatar>
<img [src]="siteInfo.userpictureurl" core-external-content alt="{{ 'core.pictureof' | translate:{$a: siteInfo.fullname} }}" role="presentation">
</ion-avatar>
<p>{{siteInfo.fullname}}</p> <p>{{siteInfo.fullname}}</p>
</a> </a>
<ion-item-divider color="light"></ion-item-divider> <ion-item-divider color="light"></ion-item-divider>

View File

@ -9,9 +9,7 @@
<ion-list *ngIf="participants && participants.length > 0" no-margin> <ion-list *ngIf="participants && participants.length > 0" no-margin>
<a ion-item text-wrap *ngFor="let participant of participants" [title]="participant.fullname" (click)="gotoParticipant(participant.id)" [class.core-split-item-selected]="participant.id == participantId"> <a ion-item text-wrap *ngFor="let participant of participants" [title]="participant.fullname" (click)="gotoParticipant(participant.id)" [class.core-split-item-selected]="participant.id == participantId">
<ion-avatar item-start> <ion-avatar class="user-avatar" [user]="participant" item-start [userId]="participant.id"></ion-avatar>
<img src="{{participant.profileimageurl}}" [alt]="'core.pictureof' | translate:{$a: participant.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
</ion-avatar>
<h2><core-format-text [text]="participant.fullname"></core-format-text></h2> <h2><core-format-text [text]="participant.fullname"></core-format-text></h2>
<p *ngIf="participant.lastaccess"><strong>{{ 'core.lastaccess' | translate }}: </strong>{{ participant.lastaccess * 1000 | coreFormatDate:"dfmediumdate"}}</p> <p *ngIf="participant.lastaccess"><strong>{{ 'core.lastaccess' | translate }}: </strong>{{ participant.lastaccess * 1000 | coreFormatDate:"dfmediumdate"}}</p>
</a> </a>

View File

@ -111,6 +111,8 @@ $button-md-box-shadow: 0 2px 2px 1px rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0,
$refresher-icon-color: $core-color !default; $refresher-icon-color: $core-color !default;
$core-online-color: #5cb85c;
// Moodle Mobile variables // Moodle Mobile variables
// -------------------------------------------------- // --------------------------------------------------