Merge pull request #1817 from dpalou/MOBILE-2915

Mobile 2915
main
Juan Leyva 2019-03-22 09:33:08 +01:00 committed by GitHub
commit 9ecf908d24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 101 additions and 16 deletions

View File

@ -124,7 +124,7 @@
</plugin>
<plugin name="cordova-plugin-device" spec="2.0.2" />
<plugin name="cordova-plugin-file" spec="6.0.1" />
<plugin name="cordova-plugin-file-opener2" spec="2.2.0" />
<plugin name="cordova-plugin-file-opener2" spec="2.0.19" />
<plugin name="cordova-plugin-file-transfer" spec="1.7.1" />
<plugin name="cordova-plugin-globalization" spec="1.11.0" />
<plugin name="cordova-plugin-inappbrowser" spec="3.0.0" />

View File

@ -145,6 +145,7 @@
"addon.coursecompletion.criteriarequiredany": "completion",
"addon.coursecompletion.inprogress": "completion",
"addon.coursecompletion.manualselfcompletion": "completion",
"addon.coursecompletion.nottracked": "completion",
"addon.coursecompletion.notyetstarted": "completion",
"addon.coursecompletion.pending": "completion",
"addon.coursecompletion.required": "moodle",

View File

@ -3,7 +3,7 @@
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
</ion-refresher>
<core-loading [hideUntil]="completionLoaded">
<ion-card *ngIf="completion">
<ion-card *ngIf="completion && tracked">
<ion-item text-wrap>
<h2>{{ 'addon.coursecompletion.status' | translate }}</h2>
<p>{{ completion.statusText | translate }}</p>
@ -14,7 +14,7 @@
<p *ngIf="completion.aggregation === 2">{{ 'addon.coursecompletion.criteriarequiredany' | translate }}</p>
</ion-item>
</ion-card>
<ion-card *ngIf="completion">
<ion-card *ngIf="completion && tracked">
<ion-item-divider>{{ 'addon.coursecompletion.requiredcriteria' | translate }}</ion-item-divider>
<ion-item class="hidden-tablet" text-wrap *ngFor="let criteria of completion.completions">
<h2><core-format-text clean="true" [text]="criteria.details.criteria"></core-format-text></h2>
@ -41,11 +41,16 @@
</ion-row>
</ion-item>
</ion-card>
<ion-card *ngIf="showSelfComplete">
<ion-card *ngIf="showSelfComplete && tracked">
<ion-item-divider>{{ 'addon.coursecompletion.manualselfcompletion' | translate }}</ion-item-divider>
<ion-item>
<button ion-button block (click)="completeCourse()">{{ 'addon.coursecompletion.completecourse' | translate }}</button>
</ion-item>
</ion-card>
<div *ngIf="!tracked" class="core-warning-card" icon-start>
<ion-icon name="warning"></ion-icon>
{{ 'addon.coursecompletion.nottracked' | translate }}
</div>
</core-loading>
</ion-content>

View File

@ -31,6 +31,7 @@ export class AddonCourseCompletionReportComponent implements OnInit {
completionLoaded = false;
completion: any;
showSelfComplete: boolean;
tracked = true; // Whether completion is tracked.
constructor(
private sitesProvider: CoreSitesProvider,
@ -62,8 +63,14 @@ export class AddonCourseCompletionReportComponent implements OnInit {
this.completion = completion;
this.showSelfComplete = this.courseCompletionProvider.canMarkSelfCompleted(this.userId, completion);
}).catch((message) => {
this.domUtils.showErrorModalDefault(message, 'addon.coursecompletion.couldnotloadreport', true);
this.tracked = true;
}).catch((error) => {
if (error && error.errorcode == 'notenroled') {
// Not enrolled error, probably a teacher.
this.tracked = false;
} else {
this.domUtils.showErrorModalDefault(error, 'addon.coursecompletion.couldnotloadreport', true);
}
});
}

View File

@ -12,6 +12,7 @@
"criteriarequiredany": "Any criteria below are required",
"inprogress": "In progress",
"manualselfcompletion": "Manual self completion",
"nottracked": "You are currently not being tracked by completion in this course",
"notyetstarted": "Not yet started",
"pending": "Pending",
"required": "Required",

View File

@ -145,6 +145,7 @@
"addon.coursecompletion.criteriarequiredany": "Any criteria below are required",
"addon.coursecompletion.inprogress": "In progress",
"addon.coursecompletion.manualselfcompletion": "Manual self completion",
"addon.coursecompletion.nottracked": "You are currently not being tracked by completion in this course",
"addon.coursecompletion.notyetstarted": "Not yet started",
"addon.coursecompletion.pending": "Pending",
"addon.coursecompletion.required": "Required",

View File

@ -582,7 +582,7 @@ export class CoreSite {
});
}
const promise = this.getFromCache(method, data, preSets, false, originalData).catch(() => {
let promise = this.getFromCache(method, data, preSets, false, originalData).catch(() => {
// Do not pass those options to the core WS factory.
return this.wsProvider.call(method, data, wsPreSets).then((response) => {
if (preSets.saveToCache) {
@ -688,12 +688,13 @@ export class CoreSite {
});
this.ongoingRequests[cacheId] = promise;
// Clear ongoing request after setting the promise (just in case it's already resolved).
promise.finally(() => {
// Make sure we don't clear the promise of a newer request that ignores the cache.
if (this.ongoingRequests[cacheId] === promise) {
delete this.ongoingRequests[cacheId];
}
promise = promise.finally(() => {
// Make sure we don't clear the promise of a newer request that ignores the cache.
if (this.ongoingRequests[cacheId] === promise) {
delete this.ongoingRequests[cacheId];
}
});
return promise.then((response) => {

View File

@ -169,7 +169,9 @@ export class CoreCourseSectionPage implements OnDestroy {
*/
protected loadData(refresh?: boolean, sync?: boolean): Promise<any> {
// First of all, get the course because the data might have changed.
return this.coursesProvider.getUserCourse(this.course.id).catch(() => {
return this.courseHelper.getCourse(this.course.id).then((result) => {
return result.course;
}).catch(() => {
// Error getting the course, probably guest access.
}).then((course) => {
if (course) {

View File

@ -767,6 +767,33 @@ export class CoreCourseHelperProvider {
});
}
/**
* Get a course. It will first check the user courses, and fallback to another WS if not enrolled.
*
* @param {number} courseId Course ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<{enrolled: boolean, course: any}>} Promise resolved with the course.
*/
getCourse(courseId: number, siteId?: string): Promise<{enrolled: boolean, course: any}> {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
// Try with enrolled courses first.
return this.coursesProvider.getUserCourse(courseId, false, siteId).then((course) => {
return { enrolled: true, course: course };
}).catch(() => {
// Not enrolled or an error happened. Try to use another WebService.
return this.coursesProvider.isGetCoursesByFieldAvailableInSite(siteId).then((available) => {
if (available) {
return this.coursesProvider.getCourseByField('id', courseId, siteId);
} else {
return this.coursesProvider.getCourse(courseId, siteId);
}
}).then((course) => {
return { enrolled: false, course: course };
});
});
}
/**
* Check if the course has a block with that name.
*

View File

@ -389,6 +389,30 @@ export class CoreCoursesProvider {
}
}
/**
* Get the first course returned by getCoursesByField.
*
* @param {string} [field] The field to search. Can be left empty for all courses or:
* id: course id.
* ids: comma separated course ids.
* shortname: course short name.
* idnumber: course id number.
* category: category id the course belongs to.
* @param {any} [value] The value to match.
* @param {string} [siteId] Site ID. If not defined, use current site.
* @return {Promise<any>} Promise resolved with the first course.
* @since 3.2
*/
getCourseByField(field?: string, value?: any, siteId?: string): Promise<any> {
return this.getCoursesByField(field, value, siteId).then((courses) => {
if (courses && courses.length > 0) {
return courses[0];
}
return Promise.reject(null);
});
}
/**
* Get courses. They can be filtered by field.
*
@ -482,13 +506,29 @@ export class CoreCoursesProvider {
}
/**
* Check if get courses by field WS is available.
* Check if get courses by field WS is available in a certain site.
*
* @param {CoreSite} [site] Site to check.
* @return {boolean} Whether get courses by field is available.
* @since 3.2
*/
isGetCoursesByFieldAvailable(): boolean {
return this.sitesProvider.wsAvailableInCurrentSite('core_course_get_courses_by_field');
isGetCoursesByFieldAvailable(site?: CoreSite): boolean {
site = site || this.sitesProvider.getCurrentSite();
return site.wsAvailable('core_course_get_courses_by_field');
}
/**
* Check if get courses by field WS is available in a certain site, by site ID.
*
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<boolean>} Promise resolved with boolean: whether get courses by field is available.
* @since 3.2
*/
isGetCoursesByFieldAvailableInSite(siteId?: string): Promise<boolean> {
return this.sitesProvider.getSite(siteId).then((site) => {
return this.isGetCoursesByFieldAvailable(site);
});
}
/**