forked from EVOgeek/Vmeda.Online
MOBILE-4362 user: Improve user pages look and feel
parent
4cee48ff8b
commit
1e7fe59dab
|
@ -1631,7 +1631,6 @@
|
||||||
"core.course.warningmanualcompletionmodified": "local_moodlemobileapp",
|
"core.course.warningmanualcompletionmodified": "local_moodlemobileapp",
|
||||||
"core.course.warningofflinemanualcompletiondeleted": "local_moodlemobileapp",
|
"core.course.warningofflinemanualcompletiondeleted": "local_moodlemobileapp",
|
||||||
"core.course.youmust": "completion",
|
"core.course.youmust": "completion",
|
||||||
"core.coursedetails": "moodle",
|
|
||||||
"core.coursenogroups": "local_moodlemobileapp",
|
"core.coursenogroups": "local_moodlemobileapp",
|
||||||
"core.courses.addtofavourites": "block_myoverview",
|
"core.courses.addtofavourites": "block_myoverview",
|
||||||
"core.courses.aria:coursecategory": "course",
|
"core.courses.aria:coursecategory": "course",
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
width: var(--core-avatar-size);
|
width: var(--core-avatar-size);
|
||||||
height: var(--core-avatar-size);
|
height: var(--core-avatar-size);
|
||||||
|
--contact-status-size: 14px;
|
||||||
|
--margin-end-on-item: 8px;
|
||||||
|
--margin-vertical-on-item: 8px;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
border-radius: var(--core-avatar-radius);
|
border-radius: var(--core-avatar-radius);
|
||||||
|
@ -53,8 +56,8 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 14px;
|
width: var(--contact-status-size);
|
||||||
height: 14px;
|
height: var(--contact-status-size);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
&.online {
|
&.online {
|
||||||
border: 1px solid white;
|
border: 1px solid white;
|
||||||
|
@ -92,7 +95,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
:host-context(ion-item) {
|
:host-context(ion-item) {
|
||||||
@include margin(6px, 8px, 6px, 0px);
|
@include margin(var(--margin-vertical-on-item), var(--margin-end-on-item), var(--margin-vertical-on-item), 0px);
|
||||||
img {
|
img {
|
||||||
min-width: var(--core-avatar-size);
|
min-width: var(--core-avatar-size);
|
||||||
min-height: var(--core-avatar-size);
|
min-height: var(--core-avatar-size);
|
||||||
|
|
|
@ -75,7 +75,8 @@ Feature: Test signup in app
|
||||||
|
|
||||||
When I press the user menu button in the app
|
When I press the user menu button in the app
|
||||||
And I press "User Test" in the app
|
And I press "User Test" in the app
|
||||||
Then I should find "Barcelona, Spain" in the app
|
Then I should find "Barcelona" in the app
|
||||||
|
Then I should find "Spain" in the app
|
||||||
And I should find "u1@u1.com" in the app
|
And I should find "u1@u1.com" in the app
|
||||||
|
|
||||||
@lms_from3.10
|
@lms_from3.10
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
<core-loading [hideUntil]="userLoaded">
|
<core-loading [hideUntil]="userLoaded">
|
||||||
<ion-list *ngIf="user">
|
<ion-list *ngIf="user">
|
||||||
<ion-item class="ion-text-center core-user-profile-maininfo ion-text-wrap" lines="full">
|
<ion-item class="ion-text-center core-user-profile-maininfo ion-text-wrap" [lines]="user.description ? null : 'full'">
|
||||||
<core-user-avatar [user]="user" [userId]="user.id" [linkProfile]="false" [checkOnline]="!canChangeProfilePicture">
|
<core-user-avatar [user]="user" [userId]="user.id" [linkProfile]="false" [checkOnline]="!canChangeProfilePicture">
|
||||||
<ion-button class="edit-avatar" *ngIf="canChangeProfilePicture" (click)="changeProfilePicture()"
|
<ion-button class="edit-avatar" *ngIf="canChangeProfilePicture" (click)="changeProfilePicture()"
|
||||||
[attr.aria-label]="'core.user.newpicture' | translate" fill="clear">
|
[attr.aria-label]="'core.user.newpicture' | translate" fill="clear">
|
||||||
|
@ -23,8 +23,14 @@
|
||||||
</core-user-avatar>
|
</core-user-avatar>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ user.fullname }}</h2>
|
<h2>{{ user.fullname }}</h2>
|
||||||
<p *ngIf="user.address">
|
</ion-label>
|
||||||
<ion-icon name="fas-location-dot" [attr.aria-hidden]="true"></ion-icon> {{ user.address }}
|
</ion-item>
|
||||||
|
|
||||||
|
<ion-item class="ion-text-wrap" *ngIf="user.description" lines="full">
|
||||||
|
<ion-label>
|
||||||
|
<p>
|
||||||
|
<core-format-text [text]="user.description" contextLevel="user" [contextInstanceId]="user.id">
|
||||||
|
</core-format-text>
|
||||||
</p>
|
</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
@ -32,7 +38,7 @@
|
||||||
<ion-item-group *ngIf="hasContact">
|
<ion-item-group *ngIf="hasContact">
|
||||||
<ion-item-divider>
|
<ion-item-divider>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'core.user.contact' | translate}}</p>
|
<h3>{{ 'core.user.contact' | translate}}</h3>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="user.email">
|
<ion-item class="ion-text-wrap" *ngIf="user.email">
|
||||||
|
@ -43,6 +49,24 @@
|
||||||
</a></p>
|
</a></p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
<ion-item class="ion-text-wrap" *ngIf="user.country">
|
||||||
|
<ion-label>
|
||||||
|
<p class="item-heading">{{ 'core.user.country' | translate}}</p>
|
||||||
|
<p>{{ user.country }}</p>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item class="ion-text-wrap" *ngIf="user.city">
|
||||||
|
<ion-label>
|
||||||
|
<p class="item-heading">{{ 'core.user.city' | translate}}</p>
|
||||||
|
<p>{{ user.city }}</p>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item class="ion-text-wrap" *ngIf="displayTimezone && user.timezone">
|
||||||
|
<ion-label>
|
||||||
|
<p class="item-heading">{{ 'core.timezone' | translate}}</p>
|
||||||
|
<p>{{ user.timezone }}</p>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="user.phone1">
|
<ion-item class="ion-text-wrap" *ngIf="user.phone1">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'core.user.phone1' | translate}}</p>
|
<p class="item-heading">{{ 'core.user.phone1' | translate}}</p>
|
||||||
|
@ -59,31 +83,9 @@
|
||||||
</a></p>
|
</a></p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="user.city">
|
|
||||||
<ion-label>
|
|
||||||
<p class="item-heading">{{ 'core.user.city' | translate}}</p>
|
|
||||||
<p>{{ user.city }}</p>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
<ion-item class="ion-text-wrap" *ngIf="user.country">
|
|
||||||
<ion-label>
|
|
||||||
<p class="item-heading">{{ 'core.user.country' | translate}}</p>
|
|
||||||
<p>{{ user.country }}</p>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
<ion-item class="ion-text-wrap" *ngIf="displayTimezone && user.timezone">
|
|
||||||
<ion-label>
|
|
||||||
<p class="item-heading">{{ 'core.timezone' | translate}}</p>
|
|
||||||
<p>{{ user.timezone }}</p>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
<ng-container *ngIf="canShowDepartment">
|
<ng-container *ngIf="canShowDepartment">
|
||||||
<ion-item class="ion-text-wrap" *ngIf="user.idnumber">
|
|
||||||
<ion-label>
|
|
||||||
<p class="item-heading">{{ 'core.user.idnumber' | translate }}</p>
|
|
||||||
<p>{{ user.idnumber }}</p>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
<ion-item class="ion-text-wrap" *ngIf="user.institution">
|
<ion-item class="ion-text-wrap" *ngIf="user.institution">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'core.user.institution' | translate }}</p>
|
<p class="item-heading">{{ 'core.user.institution' | translate }}</p>
|
||||||
|
@ -96,12 +98,18 @@
|
||||||
<p>{{ user.department }}</p>
|
<p>{{ user.department }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
<ion-item class="ion-text-wrap" *ngIf="user.idnumber">
|
||||||
|
<ion-label>
|
||||||
|
<p class="item-heading">{{ 'core.user.idnumber' | translate }}</p>
|
||||||
|
<p>{{ user.idnumber }}</p>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-item-group>
|
</ion-item-group>
|
||||||
<ion-item-group *ngIf="hasDetails">
|
<ion-item-group *ngIf="hasDetails">
|
||||||
<ion-item-divider>
|
<ion-item-divider>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'core.userdetails' | translate}}</p>
|
<h3>{{ 'core.userdetails' | translate}}</h3>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="user.url">
|
<ion-item class="ion-text-wrap" *ngIf="user.url">
|
||||||
|
@ -124,21 +132,6 @@
|
||||||
[contextInstanceId]="courseId" [courseId]="courseId">
|
[contextInstanceId]="courseId" [courseId]="courseId">
|
||||||
</core-user-profile-field>
|
</core-user-profile-field>
|
||||||
</ion-item-group>
|
</ion-item-group>
|
||||||
<ion-item-group *ngIf="user.description">
|
|
||||||
<ion-item-divider>
|
|
||||||
<ion-label>
|
|
||||||
<p class="item-heading">{{ 'core.user.description' | translate}}</p>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item-divider>
|
|
||||||
<ion-item class="ion-text-wrap">
|
|
||||||
<ion-label>
|
|
||||||
<p>
|
|
||||||
<core-format-text [text]="user.description" contextLevel="user" [contextInstanceId]="user.id">
|
|
||||||
</core-format-text>
|
|
||||||
</p>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
</ion-item-group>
|
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
|
||||||
<core-empty-box *ngIf="!user || (!hasContact && !hasDetails && !user.description)" icon="fas-user"
|
<core-empty-box *ngIf="!user || (!hasContact && !hasDetails && !user.description)" icon="fas-user"
|
||||||
|
|
|
@ -1,27 +1,20 @@
|
||||||
:host {
|
:host {
|
||||||
|
|
||||||
.core-user-profile-maininfo::part(native) {
|
.core-user-profile-maininfo::part(native) {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
::ng-deep {
|
|
||||||
core-user-avatar {
|
core-user-avatar {
|
||||||
display: block;
|
|
||||||
--core-avatar-size: var(--core-large-avatar-size);
|
--core-avatar-size: var(--core-large-avatar-size);
|
||||||
height: calc(var(--core-avatar-size) + 16px);
|
--contact-status-size: 24px;
|
||||||
|
--margin-end-on-item: 0px;
|
||||||
img {
|
--margin-vertical-on-item: 0px;
|
||||||
margin: 8px auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-status {
|
.contact-status {
|
||||||
width: 24px !important;
|
|
||||||
height: 24px !important;
|
|
||||||
right: calc(50% - 12px - var(--core-avatar-size) / 2) !important;
|
right: calc(50% - 12px - var(--core-avatar-size) / 2) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-avatar {
|
.edit-avatar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: calc(50% - 15px - var(--core-avatar-size) / 2);
|
right: calc(50% - 24px - var(--core-avatar-size) / 2);
|
||||||
bottom: -12px;
|
bottom: -12px;
|
||||||
|
|
||||||
:host-context([dir="rtl"]) & {
|
:host-context([dir="rtl"]) & {
|
||||||
|
@ -34,8 +27,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
.core-user-profile-interests {
|
.core-user-profile-interests {
|
||||||
ion-badge {
|
ion-badge {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -46,7 +44,7 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:host-context([dir="rtl"]) ::ng-deep core-user-avatar .edit-avatar {
|
:host-context([dir="rtl"]) core-user-avatar .edit-avatar {
|
||||||
left: -24px;
|
left: -24px;
|
||||||
right: unset;
|
right: unset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,6 @@ export class CoreUserAboutPage implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.user.email = data.user.email;
|
this.user.email = data.user.email;
|
||||||
this.user.address = CoreUserHelper.formatAddress('', data.user.city, data.user.country);
|
|
||||||
}, CoreSites.getCurrentSiteId());
|
}, CoreSites.getCurrentSiteId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,8 +117,6 @@ export class CoreUserAboutPage implements OnInit, OnDestroy {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.title = user.fullname;
|
this.title = user.fullname;
|
||||||
|
|
||||||
this.user.address = CoreUserHelper.formatAddress('', user.city, user.country);
|
|
||||||
|
|
||||||
this.fillTimezone();
|
this.fillTimezone();
|
||||||
|
|
||||||
await this.checkUserImageUpdated();
|
await this.checkUserImageUpdated();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<ion-header>
|
<ion-header collapsible>
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-buttons slot="start">
|
<ion-buttons slot="start">
|
||||||
<ion-back-button [text]="'core.back' | translate"></ion-back-button>
|
<ion-back-button [text]="'core.back' | translate"></ion-back-button>
|
||||||
|
@ -14,11 +14,11 @@
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
<core-loading [hideUntil]="userLoaded">
|
<core-loading [hideUntil]="userLoaded">
|
||||||
<ion-list *ngIf="user && !isDeleted && isEnrolled">
|
<ion-list *ngIf="user && !isDeleted && isEnrolled">
|
||||||
<ion-item class="ion-text-center core-user-profile-maininfo ion-text-wrap">
|
<ion-item class="core-user-profile-maininfo ion-text-wrap" collapsible>
|
||||||
<core-user-avatar [user]="user" [userId]="user.id" [linkProfile]="false" [checkOnline]="true">
|
<core-user-avatar [user]="user" [userId]="user.id" [linkProfile]="false" [checkOnline]="true" slot="start">
|
||||||
</core-user-avatar>
|
</core-user-avatar>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ user.fullname }}</h2>
|
<h1>{{ user.fullname }}</h1>
|
||||||
<p *ngIf="user.address">
|
<p *ngIf="user.address">
|
||||||
<ion-icon name="fas-location-dot" [attr.aria-hidden]="true"></ion-icon> {{ user.address }}
|
<ion-icon name="fas-location-dot" [attr.aria-hidden]="true"></ion-icon> {{ user.address }}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -1,29 +1,10 @@
|
||||||
:host {
|
:host {
|
||||||
|
|
||||||
.core-user-profile-maininfo::part(native) {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
::ng-deep {
|
|
||||||
core-user-avatar {
|
core-user-avatar {
|
||||||
display: block;
|
|
||||||
--core-avatar-size: var(--core-large-avatar-size);
|
--core-avatar-size: var(--core-large-avatar-size);
|
||||||
height: calc(var(--core-avatar-size) + 16px);
|
--contact-status-size: 24px;
|
||||||
|
--margin-end-on-item: 16px;
|
||||||
img {
|
|
||||||
margin: 8px auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-status {
|
.contact-status {
|
||||||
width: 24px !important;
|
|
||||||
height: 24px !important;
|
|
||||||
right: calc(50% - 12px - var(--core-avatar-size) / 2) !important;
|
right: calc(50% - 12px - var(--core-avatar-size) / 2) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
:host-context([dir="rtl"]) ::ng-deep core-user-avatar .edit-avatar {
|
|
||||||
left: -24px;
|
|
||||||
right: unset;
|
|
||||||
}
|
|
||||||
|
|
|
@ -74,7 +74,6 @@ export class CoreUserProfilePage implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.user.email = data.user.email;
|
this.user.email = data.user.email;
|
||||||
this.user.address = CoreUserHelper.formatAddress('', data.user.city, data.user.country);
|
|
||||||
}, CoreSites.getCurrentSiteId());
|
}, CoreSites.getCurrentSiteId());
|
||||||
|
|
||||||
this.logView = CoreTime.once(async (user) => {
|
this.logView = CoreTime.once(async (user) => {
|
||||||
|
@ -151,7 +150,6 @@ export class CoreUserProfilePage implements OnInit, OnDestroy {
|
||||||
try {
|
try {
|
||||||
const user = await CoreUser.getProfile(this.userId, this.courseId);
|
const user = await CoreUser.getProfile(this.userId, this.courseId);
|
||||||
|
|
||||||
user.address = CoreUserHelper.formatAddress('', user.city, user.country);
|
|
||||||
this.rolesFormatted = 'roles' in user ? CoreUserHelper.formatRoleList(user.roles) : '';
|
this.rolesFormatted = 'roles' in user ? CoreUserHelper.formatRoleList(user.roles) : '';
|
||||||
|
|
||||||
this.user = user;
|
this.user = user;
|
||||||
|
|
|
@ -89,6 +89,7 @@ export class CoreUserHelperProvider {
|
||||||
* @param city City.
|
* @param city City.
|
||||||
* @param country Country.
|
* @param country Country.
|
||||||
* @returns Formatted address.
|
* @returns Formatted address.
|
||||||
|
* @deprecated since 4.3 Not used anymore.
|
||||||
*/
|
*/
|
||||||
formatAddress(address?: string, city?: string, country?: string): string {
|
formatAddress(address?: string, city?: string, country?: string): string {
|
||||||
const separator = Translate.instant('core.listsep');
|
const separator = Translate.instant('core.listsep');
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 29 KiB |
|
@ -61,7 +61,6 @@
|
||||||
"copiedtoclipboard": "Text copied to clipboard",
|
"copiedtoclipboard": "Text copied to clipboard",
|
||||||
"copytoclipboard": "Copy to clipboard",
|
"copytoclipboard": "Copy to clipboard",
|
||||||
"course": "Course",
|
"course": "Course",
|
||||||
"coursedetails": "Course details",
|
|
||||||
"coursenogroups": "You are not a member of any group of this course.",
|
"coursenogroups": "You are not a member of any group of this course.",
|
||||||
"currentdevice": "Current device",
|
"currentdevice": "Current device",
|
||||||
"custom": "Custom",
|
"custom": "Custom",
|
||||||
|
|
Loading…
Reference in New Issue