-
-
![{{ 'core.pictureof' | translate:{$a: user.fullname} }}]()
+
-
+
diff --git a/src/core/user/pages/profile/profile.scss b/src/core/user/pages/profile/profile.scss
index 496e1ae0c..647c39a36 100644
--- a/src/core/user/pages/profile/profile.scss
+++ b/src/core/user/pages/profile/profile.scss
@@ -1,9 +1,27 @@
ion-app.app-root page-core-user-profile {
.core-icon-foreground {
- position: relative;
- @include position(null, null, 30px, 60px);
+ position: absolute;
+ @include position(null, 0, 0, null);
font-size: 24px;
+ line-height: 30px;
+ text-align: center;
+
+ width: 30px;
+ height: 30px;
+ border-radius: 50%;
+ background-color: white;
}
+ .user-avatar.item-avatar-center {
+ display: inline-block;
+ img {
+ margin: 0;
+ }
+ .contact-status {
+ width: 24px;
+ height: 24px;
+ }
+ }
+
.core-user-communication-handlers {
background: $list-background-color;
border-bottom: 1px solid $list-border-color;
From cfb6ac4f86500b6d71b353728577ab52c0101093 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?=
Date: Fri, 16 Nov 2018 10:55:32 +0100
Subject: [PATCH 3/3] MOBILE-1486 course: Log view when course is viewed
---
src/components/user-avatar/user-avatar.ts | 24 ++++----
src/core/course/course.module.ts | 24 +++++++-
src/core/course/pages/section/section.ts | 5 ++
src/core/course/providers/log-cron-handler.ts | 59 +++++++++++++++++++
src/core/user/pages/profile/profile.html | 2 +-
src/core/user/pages/profile/profile.scss | 2 +-
src/providers/cron.ts | 32 +++++++---
7 files changed, 124 insertions(+), 24 deletions(-)
create mode 100644 src/core/course/providers/log-cron-handler.ts
diff --git a/src/components/user-avatar/user-avatar.ts b/src/components/user-avatar/user-avatar.ts
index 057d1a251..20aab67fd 100644
--- a/src/components/user-avatar/user-avatar.ts
+++ b/src/components/user-avatar/user-avatar.ts
@@ -66,18 +66,21 @@ export class CoreUserAvatarComponent implements OnInit, OnChanges {
* Set fields from user.
*/
protected setFields(): void {
- if (this.user) {
- this.profileUrl = this.profileUrl || this.user.profileimageurl || this.user.userprofileimageurl ||
- this.user.userpictureurl || this.user.profileimageurlsmall;
+ this.profileUrl = this.profileUrl || (this.user && (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;
+ if (typeof this.profileUrl != 'string') {
+ this.profileUrl = '';
}
+
+ this.fullname = this.fullname || (this.user && (this.user.fullname || this.user.userfullname));
+
+ this.userId = this.userId || (this.user && this.user.userid);
+ this.courseId = this.courseId || (this.user && this.user.courseid);
+
+ // If not available we cannot ensure the avatar is from the current user.
+ this.myUser = this.userId && this.userId == this.currentUserId;
+
}
/**
@@ -95,7 +98,6 @@ export class CoreUserAvatarComponent implements OnInit, OnChanges {
* Function executed image clicked.
*/
gotoProfile(event: any): void {
- // If the event prevented default action, do nothing.
if (this.linkProfile && this.userId) {
event.preventDefault();
event.stopPropagation();
diff --git a/src/core/course/course.module.ts b/src/core/course/course.module.ts
index 541c4333b..e6e01a772 100644
--- a/src/core/course/course.module.ts
+++ b/src/core/course/course.module.ts
@@ -13,7 +13,9 @@
// limitations under the License.
import { NgModule } from '@angular/core';
+import { Platform } from 'ionic-angular';
import { CoreCronDelegate } from '@providers/cron';
+import { CoreEventsProvider } from '@providers/events';
import { CoreCourseProvider } from './providers/course';
import { CoreCourseHelperProvider } from './providers/helper';
import { CoreCourseFormatDelegate } from './providers/format-delegate';
@@ -29,6 +31,7 @@ import { CoreCourseFormatTopicsModule } from './formats/topics/topics.module';
import { CoreCourseFormatWeeksModule } from './formats/weeks/weeks.module';
import { CoreCourseSyncProvider } from './providers/sync';
import { CoreCourseSyncCronHandler } from './providers/sync-cron-handler';
+import { CoreCourseLogCronHandler } from './providers/log-cron-handler';
// List of providers (without handlers).
export const CORE_COURSE_PROVIDERS: any[] = [
@@ -61,12 +64,29 @@ export const CORE_COURSE_PROVIDERS: any[] = [
CoreCourseSyncProvider,
CoreCourseFormatDefaultHandler,
CoreCourseModuleDefaultHandler,
- CoreCourseSyncCronHandler
+ CoreCourseSyncCronHandler,
+ CoreCourseLogCronHandler
],
exports: []
})
export class CoreCourseModule {
- constructor(cronDelegate: CoreCronDelegate, syncHandler: CoreCourseSyncCronHandler) {
+ constructor(cronDelegate: CoreCronDelegate, syncHandler: CoreCourseSyncCronHandler, logHandler: CoreCourseLogCronHandler,
+ platform: Platform, eventsProvider: CoreEventsProvider) {
cronDelegate.register(syncHandler);
+ cronDelegate.register(logHandler);
+
+ platform.resume.subscribe(() => {
+ // Log the app is open to keep user in online status.
+ setTimeout(() => {
+ cronDelegate.forceCronHandlerExecution(logHandler.name);
+ }, 1000);
+ });
+
+ eventsProvider.on(CoreEventsProvider.LOGIN, () => {
+ // Log the app is open to keep user in online status.
+ setTimeout(() => {
+ cronDelegate.forceCronHandlerExecution(logHandler.name);
+ }, 1000);
+ });
}
}
diff --git a/src/core/course/pages/section/section.ts b/src/core/course/pages/section/section.ts
index c915b4b4e..1a048fc84 100644
--- a/src/core/course/pages/section/section.ts
+++ b/src/core/course/pages/section/section.ts
@@ -202,6 +202,11 @@ export class CoreCourseSectionPage implements OnDestroy {
}).then((sections) => {
let promise;
+ // Add log in Moodle.
+ this.courseProvider.logView(this.course.id, this.sectionNumber).catch(() => {
+ // Ignore errors.
+ });
+
// Get the completion status.
if (this.course.enablecompletion === false) {
// Completion not enabled.
diff --git a/src/core/course/providers/log-cron-handler.ts b/src/core/course/providers/log-cron-handler.ts
new file mode 100644
index 000000000..108c8765d
--- /dev/null
+++ b/src/core/course/providers/log-cron-handler.ts
@@ -0,0 +1,59 @@
+// (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 { Injectable } from '@angular/core';
+import { CoreCronHandler } from '@providers/cron';
+import { CoreSitesProvider } from '@providers/sites';
+import { CoreCourseProvider } from '@core/course/providers/course';
+
+/**
+ * Log cron handler. It will update last access of the user while app is open.
+ */
+@Injectable()
+export class CoreCourseLogCronHandler implements CoreCronHandler {
+ name = 'CoreCourseLogCronHandler';
+
+ constructor(private coreProvider: CoreCourseProvider, private sitesProvider: CoreSitesProvider) {}
+
+ /**
+ * Execute the process.
+ * Receives the ID of the site affected, undefined for the current site.
+ *
+ * @param {string} [siteId] ID of the site affected, undefined for the current site.
+ * @return {Promise} Promise resolved when done, rejected if failure.
+ */
+ execute(siteId?: string): Promise {
+ return this.sitesProvider.getSite(siteId).then((site) => {
+ return this.coreProvider.logView(site.getSiteHomeId(), undefined, site.getId());
+ });
+ }
+
+ /**
+ * Check whether it's a synchronization process or not.
+ *
+ * @return {boolean} Whether it's a synchronization process or not.
+ */
+ isSync(): boolean {
+ return false;
+ }
+
+ /**
+ * Get the time between consecutive executions.
+ *
+ * @return {number} Time between consecutive executions (in ms).
+ */
+ getInterval(): number {
+ return 240000; // 4 minutes. By default platform will see the user as online if lastaccess is less than 5 minutes.
+ }
+}
diff --git a/src/core/user/pages/profile/profile.html b/src/core/user/pages/profile/profile.html
index 8b1293c50..57d96674e 100644
--- a/src/core/user/pages/profile/profile.html
+++ b/src/core/user/pages/profile/profile.html
@@ -10,7 +10,7 @@
-
+
diff --git a/src/core/user/pages/profile/profile.scss b/src/core/user/pages/profile/profile.scss
index 647c39a36..edee0fc71 100644
--- a/src/core/user/pages/profile/profile.scss
+++ b/src/core/user/pages/profile/profile.scss
@@ -11,7 +11,7 @@ ion-app.app-root page-core-user-profile {
border-radius: 50%;
background-color: white;
}
- .user-avatar.item-avatar-center {
+ [core-user-avatar].item-avatar-center {
display: inline-block;
img {
margin: 0;
diff --git a/src/providers/cron.ts b/src/providers/cron.ts
index 74eae363e..b82335476 100644
--- a/src/providers/cron.ts
+++ b/src/providers/cron.ts
@@ -236,23 +236,37 @@ export class CoreCronDelegate {
const promises = [];
for (const name in this.handlers) {
- const handler = this.handlers[name];
if (this.isHandlerManualSync(name)) {
- // Mark the handler as running (it might be running already).
- handler.running = true;
-
- // Cancel pending timeout.
- clearTimeout(handler.timeout);
- delete handler.timeout;
-
// Now force the execution of the handler.
- promises.push(this.checkAndExecuteHandler(name, true, siteId));
+ promises.push(this.forceCronHandlerExecution(name, siteId));
}
}
return this.utils.allPromises(promises);
}
+ /**
+ * Force execution of a cron tasks without waiting for the scheduled time.
+ * Please notice that some tasks may not be executed depending on the network connection and sync settings.
+ *
+ * @param {string} [name] If provided, the name of the handler.
+ * @param {string} [siteId] Site ID. If not defined, all sites.
+ * @return {Promise} Promise resolved if handler has been executed successfully, rejected otherwise.
+ */
+ forceCronHandlerExecution(name?: string, siteId?: string): Promise {
+ const handler = this.handlers[name];
+
+ // Mark the handler as running (it might be running already).
+ handler.running = true;
+
+ // Cancel pending timeout.
+ clearTimeout(handler.timeout);
+ delete handler.timeout;
+
+ // Now force the execution of the handler.
+ return this.checkAndExecuteHandler(name, true, siteId);
+ }
+
/**
* Get a handler's interval.
*