MOBILE-1486 user: Show status indicator on user avatar
parent
bb3a525a5b
commit
5e4e4fc75f
|
@ -28,12 +28,7 @@
|
|||
<h3 margin-horizontal *ngIf="competencies && competencies.statistics.competencycount > 0">{{ 'addon.competency.competencies' | translate }}</h3>
|
||||
<ion-card *ngIf="user">
|
||||
<ion-item text-wrap>
|
||||
<ion-avatar *ngIf="user.profileimageurl && user.profileimageurl !== true" item-start>
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="user" item-start></ion-avatar>
|
||||
<h2><core-format-text [text]="user.fullname"></core-format-text></h2>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
|
|
|
@ -10,12 +10,7 @@
|
|||
<core-loading [hideUntil]="competencyLoaded">
|
||||
<ion-card *ngIf="user">
|
||||
<ion-item text-wrap>
|
||||
<ion-avatar *ngIf="user.profileimageurl && user.profileimageurl !== true" item-start>
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="user" item-start></ion-avatar>
|
||||
<h2><core-format-text [text]="user.fullname"></core-format-text></h2>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
|
@ -78,9 +73,7 @@
|
|||
</p>
|
||||
<ion-card *ngFor="let evidence of competency.evidence">
|
||||
<a ion-item text-wrap *ngIf="evidence.actionuser" (click)="openUserProfile(evidence.actionuser.id)">
|
||||
<ion-avatar item-start>
|
||||
<img core-external-content [src]="evidence.actionuser.profileimageurlsmall" [alt]="'core.pictureof' | translate:{$a: evidence.actionuser.fullname}" role="presentation">
|
||||
</ion-avatar>
|
||||
<ion-avatar class="user-avatar" [user]="evidence.actionuser" item-start></ion-avatar>
|
||||
<h2>{{ evidence.actionuser.fullname }}</h2>
|
||||
<p>{{ evidence.timemodified | coreToLocaleString }}</p>
|
||||
</a>
|
||||
|
|
|
@ -10,12 +10,7 @@
|
|||
<core-loading [hideUntil]="planLoaded">
|
||||
<ion-card *ngIf="user">
|
||||
<ion-item text-wrap>
|
||||
<ion-avatar *ngIf="user.profileimageurl && user.profileimageurl !== true" item-start>
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="user" item-start></ion-avatar>
|
||||
<h2><core-format-text [text]="user.fullname"></core-format-text></h2>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
|
|
|
@ -19,9 +19,7 @@
|
|||
<ng-container *ngFor="let contact of contacts[contactType]">
|
||||
<!-- 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>
|
||||
<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'">
|
||||
</ion-avatar>
|
||||
<ion-avatar class="user-avatar" [user]="contact" item-start></ion-avatar>
|
||||
<h2><core-format-text [text]="contact.fullname"></core-format-text></h2>
|
||||
</a>
|
||||
</ng-container>
|
||||
|
|
|
@ -17,9 +17,7 @@
|
|||
<ion-note item-end>{{ search.results.length }}</ion-note>
|
||||
</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>
|
||||
<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'">
|
||||
</ion-avatar>
|
||||
<ion-avatar class="user-avatar" [user]="result" item-start></ion-avatar>
|
||||
<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>
|
||||
</a>
|
||||
|
@ -27,9 +25,7 @@
|
|||
|
||||
<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>
|
||||
<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'">
|
||||
</ion-avatar>
|
||||
<ion-avatar class="user-avatar" [user]="discussion" item-start></ion-avatar>
|
||||
<h2>
|
||||
<core-format-text [text]="discussion.fullname"></core-format-text>
|
||||
<ion-note *ngIf="discussion.message.timecreated > 0 || discussion.unread">
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
<!-- User and status of the submission. -->
|
||||
<a ion-item text-wrap *ngIf="!blindMarking && user" (click)="openUserProfile(submitId)" [title]="user.fullname">
|
||||
<ion-avatar item-start>
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="user" item-start></ion-avatar>
|
||||
<h2>{{ user.fullname }}</h2>
|
||||
<ng-container *ngTemplateOutlet="submissionStatus"></ng-container>
|
||||
</a>
|
||||
|
@ -113,9 +111,7 @@
|
|||
<h2>{{ 'addon.mod_assign.userswhoneedtosubmit' | translate: {$a: ''} }}</h2>
|
||||
<div *ngFor="let user of membersToSubmit">
|
||||
<a ion-item text-wrap *ngIf="user.fullname" (click)="openUserProfile(user.id)" [title]="user.fullname">
|
||||
<ion-avatar item-start>
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="user" item-start></ion-avatar>
|
||||
<h2>{{ user.fullname }}</h2>
|
||||
</a>
|
||||
<ion-item text-wrap *ngIf="!user.fullname">
|
||||
|
@ -213,9 +209,7 @@
|
|||
|
||||
<!-- Data about the grader (teacher who graded). -->
|
||||
<a ion-item text-wrap *ngIf="grader" (click)="openUserProfile(grader.id)" [title]="grader.fullname" detail-push>
|
||||
<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'">
|
||||
</ion-avatar>
|
||||
<ion-avatar class="user-avatar" [user]="grader" item-start></ion-avatar>
|
||||
<h2>{{ 'addon.mod_assign.gradedby' | translate }}</h2>
|
||||
<h2>{{ grader.fullname }}</h2>
|
||||
<p *ngIf="feedback.gradeddate">{{ feedback.gradeddate * 1000 | coreFormatDate:"dfmediumdate" }}</p>
|
||||
|
|
|
@ -18,9 +18,7 @@
|
|||
<!-- List 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">
|
||||
<ion-avatar item-start *ngIf="submission.userprofileimageurl">
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="submission" item-start></ion-avatar>
|
||||
<h2 *ngIf="submission.userfullname">{{submission.userfullname}}</h2>
|
||||
<h2 *ngIf="!submission.userfullname">{{ 'addon.mod_assign.hiddenuser' | translate }}{{submission.blindid}}</h2>
|
||||
<p *ngIf="assign.teamsubmission">
|
||||
|
|
|
@ -38,9 +38,7 @@
|
|||
</div>
|
||||
|
||||
<ion-item text-wrap *ngIf="!message.system && message.message.substr(0, 4) != 'beep'" class="addon-mod-chat-message">
|
||||
<ion-avatar item-start>
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="message" item-start></ion-avatar>
|
||||
<h2>
|
||||
<p float-end>{{ message.timestamp * 1000 | coreFormatDate:"dftimedate" }}</p>
|
||||
<core-format-text [text]="message.userfullname"></core-format-text>
|
||||
|
|
|
@ -11,9 +11,7 @@
|
|||
<ion-content>
|
||||
<core-loading [hideUntil]="usersLoaded">
|
||||
<ion-item text-wrap *ngFor="let user of users" [class.addon-mod-chat-user]="currentUserId != user.id && isOnline">
|
||||
<ion-avatar item-start>
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="user" item-start></ion-avatar>
|
||||
<h2><core-format-text [text]="user.fullname"></core-format-text></h2>
|
||||
<ng-container *ngIf="currentUserId != user.id && isOnline">
|
||||
<button ion-button clear icon-left (click)="talkTo(user)">
|
||||
|
|
|
@ -82,9 +82,7 @@
|
|||
<p>{{ 'addon.mod_choice.numberofuser' | translate }}: {{ result.numberofuser }} ({{ 'core.percentagenumber' | translate: {$a: result.percentageamount} }})</p>
|
||||
</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>
|
||||
<ion-avatar item-start>
|
||||
<img [src]="user.profileimageurl" [alt]="'core.pictureof' | translate:{$a: user.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
|
||||
</ion-avatar>
|
||||
<ion-avatar class="user-avatar" [user]="user" item-start [courseId]="courseid"></ion-avatar>
|
||||
<p>{{user.fullname}}</p>
|
||||
</a>
|
||||
</ion-item-group>
|
||||
|
|
|
@ -6,10 +6,8 @@
|
|||
<ion-content>
|
||||
<core-loading [hideUntil]="feedbackLoaded">
|
||||
<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">
|
||||
<ion-avatar item-start>
|
||||
<img [src]="attempt.profileimageurl" [alt]="'core.pictureof' | translate:{$a: attempt.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
|
||||
</ion-avatar>
|
||||
<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 class="user-avatar" [user]="attempt" item-start></ion-avatar>
|
||||
<h2>{{attempt.fullname}}</h2>
|
||||
<p *ngIf="attempt.timemodified">{{attempt.timemodified * 1000 | coreFormatDate:"LLL"}}</p>
|
||||
</a>
|
||||
|
|
|
@ -21,9 +21,7 @@
|
|||
</ion-item-divider>
|
||||
<ng-container *ngIf="total > 0">
|
||||
<ion-item *ngFor="let user of users" text-wrap>
|
||||
<ion-avatar item-start>
|
||||
<img [src]="user.profileimageurl" [alt]="'core.pictureof' | translate:{$a: user.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
|
||||
</ion-avatar>
|
||||
<ion-avatar class="user-avatar" [user]="user" item-start></ion-avatar>
|
||||
<h2><core-format-text [text]="user.fullname"></core-format-text></h2>
|
||||
<p>
|
||||
<ion-badge color="success" *ngIf="user.started">
|
||||
|
|
|
@ -22,9 +22,7 @@
|
|||
{{ 'addon.mod_feedback.non_anonymous_entries' | translate : {$a: responses.total } }}
|
||||
</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">
|
||||
<ion-avatar item-start>
|
||||
<img [src]="attempt.profileimageurl" [alt]="'core.pictureof' | translate:{$a: attempt.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
|
||||
</ion-avatar>
|
||||
<ion-avatar class="user-avatar" [user]="attempt" item-start></ion-avatar>
|
||||
<h2><core-format-text [text]="attempt.fullname"></core-format-text></h2>
|
||||
<p *ngIf="attempt.timemodified">{{attempt.timemodified * 1000 | coreFormatDate: "LLL"}}</p>
|
||||
</a>
|
||||
|
|
|
@ -27,9 +27,7 @@
|
|||
<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-item text-wrap>
|
||||
<ion-avatar item-start core-user-link [userId]="discussion.userid" [courseId]="courseId">
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="discussion" item-start [courseId]="courseId"></ion-avatar>
|
||||
<h2><core-format-text [text]="discussion.subject"></core-format-text></h2>
|
||||
<p *ngIf="discussion.userfullname">
|
||||
<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 *ngFor="let discussion of discussions" (click)="openDiscussion(discussion)" [class.addon-forum-discussion-selected]="discussion.discussion == selectedDiscussion">
|
||||
<ion-item text-wrap>
|
||||
<ion-avatar item-start core-user-link [userId]="discussion.userid" [courseId]="courseId">
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="discussion" item-start [courseId]="courseId"></ion-avatar>
|
||||
<h2><core-icon name="fa-map-pin" *ngIf="discussion.pinned"></core-icon> <core-format-text [text]="discussion.subject"></core-format-text></h2>
|
||||
<p>
|
||||
<ion-note float-end padding-left text-end>
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
<ion-card-header text-wrap no-padding >
|
||||
<ion-item text-wrap>
|
||||
<ion-avatar item-start (click)="openUserProfile(post.userid)">
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="post" item-start (click)="openUserProfile(post.userid)"></ion-avatar>
|
||||
<h2><span [class.core-bold]="post.parent == 0"><core-format-text [text]="post.subject"></core-format-text></span></h2>
|
||||
<p>
|
||||
<ion-note float-end padding-left *ngIf="!post.modified"><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</ion-note>
|
||||
|
|
|
@ -11,9 +11,7 @@
|
|||
<core-loading [hideUntil]="loaded">
|
||||
<ng-container *ngIf="entry">
|
||||
<ion-item text-wrap *ngIf="showAuthor">
|
||||
<ion-avatar item-start (click)="openUserProfile(post.userid)">
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="entry" (click)="openUserProfile(post.userid)" item-start></ion-avatar>
|
||||
<h2><core-format-text [text]="entry.concept"></core-format-text></h2>
|
||||
<ion-note item-end *ngIf="showDate">{{ entry.timemodified | coreDateDayOrTime }}</ion-note>
|
||||
<p><core-format-text [text]="entry.userfullname"></core-format-text></p>
|
||||
|
|
|
@ -233,9 +233,7 @@
|
|||
</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}">
|
||||
<ion-avatar item-start *ngIf="student.profileimageurl" core-user-link [userId]="student.id" [courseId]="courseId">
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="student" item-start [userId]="student.id" [courseId]="courseId"></ion-avatar>
|
||||
<h2>{{ student.fullname }}</h2>
|
||||
<core-progress-bar [progress]="student.bestgrade"></core-progress-bar>
|
||||
</a>
|
||||
|
|
|
@ -12,9 +12,7 @@
|
|||
<ion-list *ngIf="student">
|
||||
<!-- Student data. -->
|
||||
<a ion-item text-wrap core-user-link [userId]="student.id" [courseId]="courseId" [title]="student.fullname">
|
||||
<ion-avatar *ngIf="student.profileimageurl" item-start>
|
||||
<img [src]="student.profileimageurl" [alt]="'core.pictureof' | translate:{$a: student.fullname}" core-external-content role="presentation">
|
||||
</ion-avatar>
|
||||
<ion-avatar class="user-avatar" [user]="student" item-start [userId]="student.id" [courseId]="courseId"></ion-avatar>
|
||||
<h2>{{student.fullname}}</h2>
|
||||
<core-progress-bar [progress]="student.bestgrade"></core-progress-bar>
|
||||
</a>
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
<core-loading [hideUntil]="loaded">
|
||||
<a ion-item *ngIf="summary" text-wrap [attr.detail-none]="canViewAssessment && !canSelfAssess? null : true" (click)="gotoAssessment()">
|
||||
<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'">
|
||||
</ion-avatar>
|
||||
<ion-avatar class="user-avatar" [user]="profile" item-start [courseId]="courseId" [userId]="profile && profile.id"></ion-avatar>
|
||||
|
||||
<h2 *ngIf="profile && profile.fullname">{{profile.fullname}}</h2>
|
||||
<p *ngIf="showGrade(assessment.grade)">
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
<core-loading [hideUntil]="loaded">
|
||||
<div *ngIf="!summary">
|
||||
<ion-list-header text-wrap>
|
||||
<ion-avatar item-start>
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="profile" item-start></ion-avatar>
|
||||
<h2>{{submission.title}}</h2>
|
||||
<p *ngIf="profile && profile.fullname">{{profile.fullname}}</p>
|
||||
<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>
|
||||
</ion-item>
|
||||
<ion-item text-wrap *ngIf="viewDetails && submission.feedbackauthor">
|
||||
<ion-avatar item-start *ngIf="evaluateByProfile">
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="evaluateByProfile" item-start [courseId]="courseId" [userId]="evaluateByProfile.id"></ion-avatar>
|
||||
|
||||
<h2 *ngIf="evaluateByProfile && evaluateByProfile.fullname">{{ 'addon.mod_workshop.feedbackby' | translate : {$a: evaluateByProfile.fullname} }}</h2>
|
||||
<core-format-text [text]="submission.feedbackauthor"></core-format-text>
|
||||
|
@ -50,9 +46,7 @@
|
|||
</div>
|
||||
|
||||
<a ion-item text-wrap *ngIf="summary" [attr.detail-none]="submission.timemodified ? null : true" (click)="gotoSubmission()">
|
||||
<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'">
|
||||
</ion-avatar>
|
||||
<ion-avatar class="user-avatar" [user]="profile" item-start [courseId]="courseId" [userId]="profile && profile.id"></ion-avatar>
|
||||
|
||||
<h2>{{submission.title}}</h2>
|
||||
<p *ngIf="profile && profile.fullname">{{profile.fullname}}</p>
|
||||
|
|
|
@ -15,9 +15,8 @@
|
|||
<core-loading [hideUntil]="loaded">
|
||||
|
||||
<ion-item text-wrap>
|
||||
<ion-avatar item-start *ngIf="profile">
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="profile" item-start [courseId]="courseId" [userId]="profile.id"></ion-avatar>
|
||||
|
||||
<h2 *ngIf="profile && profile.fullname">{{profile.fullname}}</h2>
|
||||
|
||||
<p *ngIf="workshop && assessment && showGrade(assessment.grade)">
|
||||
|
@ -66,9 +65,7 @@
|
|||
</form>
|
||||
<ion-list *ngIf="!evaluating && evaluate && evaluate.text">
|
||||
<ion-item text-wrap>
|
||||
<ion-avatar item-start *ngIf="evaluateGradingByProfile">
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="evaluateGradingByProfile" item-start [courseId]="courseId" [userId]="evaluateGradingByProfile.id"></ion-avatar>
|
||||
<h2 *ngIf="evaluateGradingByProfile && evaluateGradingByProfile.fullname">{{ 'addon.mod_workshop.feedbackby' | translate : {$a: evaluateGradingByProfile.fullname} }}</h2>
|
||||
<core-format-text [text]="evaluate.text"></core-format-text>
|
||||
</ion-item>
|
||||
|
|
|
@ -36,9 +36,7 @@
|
|||
|
||||
<ion-list *ngIf="!canAddFeedback && evaluate && evaluate.text">
|
||||
<ion-item text-wrap>
|
||||
<ion-avatar item-start *ngIf="evaluateByProfile">
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="evaluateByProfile" item-start [courseId]="courseId" [userId]="evaluateByProfile.id"></ion-avatar>
|
||||
<h2 *ngIf="evaluateByProfile && evaluateByProfile.fullname">{{ 'addon.mod_workshop.feedbackby' | translate : {$a: evaluateByProfile.fullname} }}</h2>
|
||||
<core-format-text [text]="evaluate.text"></core-format-text>
|
||||
</ion-item>
|
||||
|
@ -97,9 +95,7 @@
|
|||
|
||||
<ion-list *ngIf="assessmentId && !access.assessingallowed && assessment.feedbackreviewer">
|
||||
<ion-item text-wrap>
|
||||
<ion-avatar item-start *ngIf="evaluateGradingByProfile">
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="evaluateGradingByProfile" item-start [courseId]="courseId" [userId]="evaluateGradingByProfile.id"></ion-avatar>
|
||||
<h2 *ngIf="evaluateGradingByProfile && evaluateGradingByProfile.fullname">{{ 'addon.mod_workshop.feedbackby' | translate : {$a: evaluateGradingByProfile.fullname} }}</h2>
|
||||
<core-format-text [text]="assessment.feedbackreviewer"></core-format-text>
|
||||
</ion-item>
|
||||
|
|
|
@ -27,9 +27,7 @@
|
|||
<ion-list *ngIf="notes && notes.length > 0">
|
||||
<ion-card *ngFor="let note of notes">
|
||||
<ion-item text-wrap>
|
||||
<ion-avatar item-start>
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="note" item-start></ion-avatar>
|
||||
<h2>{{note.userfullname}}</h2>
|
||||
<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>
|
||||
|
|
|
@ -19,9 +19,7 @@
|
|||
</div>
|
||||
<ion-card *ngFor="let notification of notifications">
|
||||
<ion-item>
|
||||
<ion-avatar item-start core-user-link [userId]="notification.useridfrom" [courseId]="notification.courseid">
|
||||
<img [src]="notification.profileimageurlfrom || 'assets/img/user-avatar.png'" core-external-content [alt]="'core.pictureof' | translate:{$a: notification.userfromfullname}" role="presentation">
|
||||
</ion-avatar>
|
||||
<ion-avatar class="user-avatar" [user]="notification" item-start [profileUrl]="notification.profileimageurlfrom" [fullname]="notification.userfromfullname" [userId]="notification.useridfrom" [courseId]="notification.courseid"></ion-avatar>
|
||||
<h2>{{notification.userfromfullname}}</h2>
|
||||
<div item-end *ngIf="!notification.timeread"><core-icon name="fa-circle" color="primary"></core-icon></div>
|
||||
<p>{{notification.timecreated | coreDateDayOrTime}}</p>
|
||||
|
|
|
@ -52,7 +52,7 @@ export class CoreChronoComponent implements OnChanges, OnDestroy {
|
|||
}
|
||||
|
||||
/**
|
||||
* Component being initialized.
|
||||
* Component being changed.
|
||||
*/
|
||||
ngOnChanges(changes: { [name: string]: SimpleChange }): void {
|
||||
if (changes && changes.running) {
|
||||
|
|
|
@ -50,6 +50,7 @@ import { CoreAttachmentsComponent } from './attachments/attachments';
|
|||
import { CoreIonTabsComponent } from './ion-tabs/ion-tabs';
|
||||
import { CoreIonTabComponent } from './ion-tabs/ion-tab';
|
||||
import { CoreInfiniteLoadingComponent } from './infinite-loading/infinite-loading';
|
||||
import { CoreUserAvatarComponent } from './user-avatar/user-avatar';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
@ -85,7 +86,8 @@ import { CoreInfiniteLoadingComponent } from './infinite-loading/infinite-loadin
|
|||
CoreAttachmentsComponent,
|
||||
CoreIonTabsComponent,
|
||||
CoreIonTabComponent,
|
||||
CoreInfiniteLoadingComponent
|
||||
CoreInfiniteLoadingComponent,
|
||||
CoreUserAvatarComponent
|
||||
],
|
||||
entryComponents: [
|
||||
CoreContextMenuPopoverComponent,
|
||||
|
@ -128,7 +130,8 @@ import { CoreInfiniteLoadingComponent } from './infinite-loading/infinite-loadin
|
|||
CoreAttachmentsComponent,
|
||||
CoreIonTabsComponent,
|
||||
CoreIonTabComponent,
|
||||
CoreInfiniteLoadingComponent
|
||||
CoreInfiniteLoadingComponent,
|
||||
CoreUserAvatarComponent
|
||||
]
|
||||
})
|
||||
export class CoreComponentsModule {}
|
||||
|
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,9 +12,7 @@
|
|||
|
||||
<ion-card *ngFor="let comment of comments">
|
||||
<ion-item text-wrap>
|
||||
<ion-avatar item-start>
|
||||
<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>
|
||||
<ion-avatar class="user-avatar" [user]="comment" item-start></ion-avatar>
|
||||
<h2>{{ comment.fullname }}</h2>
|
||||
<p>{{ comment.time }}</p>
|
||||
</ion-item>
|
||||
|
|
|
@ -26,10 +26,8 @@
|
|||
|
||||
<ng-container text-wrap *ngIf="course.contacts && course.contacts.length">
|
||||
<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">
|
||||
<ion-avatar item-start>
|
||||
<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>
|
||||
<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 class="user-avatar" [user]="contact" item-start [userId]="contact.id" [courseId]="isEnrolled ? course.id : null"></ion-avatar>
|
||||
<h2>{{contact.fullname}}</h2>
|
||||
</a>
|
||||
<ion-item-divider color="light"></ion-item-divider>
|
||||
|
|
|
@ -5,10 +5,8 @@
|
|||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<a ion-item core-user-link userId="{{siteInfo.userid}}">
|
||||
<ion-avatar item-start>
|
||||
<img [src]="siteInfo.userpictureurl" core-external-content alt="{{ 'core.pictureof' | translate:{$a: siteInfo.fullname} }}" role="presentation">
|
||||
</ion-avatar>
|
||||
<a ion-item core-user-link [userId]="siteInfo.userid">
|
||||
<ion-avatar class="user-avatar" [user]="siteInfo" item-start></ion-avatar>
|
||||
<p>{{siteInfo.fullname}}</p>
|
||||
</a>
|
||||
<ion-item-divider color="light"></ion-item-divider>
|
||||
|
|
|
@ -9,9 +9,7 @@
|
|||
|
||||
<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">
|
||||
<ion-avatar item-start>
|
||||
<img src="{{participant.profileimageurl}}" [alt]="'core.pictureof' | translate:{$a: participant.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'">
|
||||
</ion-avatar>
|
||||
<ion-avatar class="user-avatar" [user]="participant" item-start [userId]="participant.id"></ion-avatar>
|
||||
<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>
|
||||
</a>
|
||||
|
|
|
@ -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;
|
||||
|
||||
$core-online-color: #5cb85c;
|
||||
|
||||
|
||||
// Moodle Mobile variables
|
||||
// --------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue