MOBILE-3109 addon: Add return types to all addons except mod
parent
0c6c1b6383
commit
b2497a1dd0
|
@ -1,6 +1,6 @@
|
|||
<ion-header>
|
||||
<ion-navbar core-back-button>
|
||||
<ion-title>{{badge.name}}</ion-title>
|
||||
<ion-title>{{badge && badge.name}}</ion-title>
|
||||
</ion-navbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
|
@ -9,7 +9,7 @@
|
|||
</ion-refresher>
|
||||
<core-loading [hideUntil]="badgeLoaded">
|
||||
|
||||
<ion-item-group>
|
||||
<ion-item-group *ngIf="badge">
|
||||
<ion-item text-wrap class="item-avatar-center">
|
||||
<img *ngIf="badge.badgeurl" class="avatar" [src]="badge.badgeurl" core-external-content [alt]="badge.name">
|
||||
<ion-badge color="danger" *ngIf="badge.dateexpire && currentTime >= badge.dateexpire">
|
||||
|
@ -30,7 +30,7 @@
|
|||
</ion-item>
|
||||
</ion-item-group>
|
||||
|
||||
<ion-item-group>
|
||||
<ion-item-group *ngIf="badge">
|
||||
<ion-item-divider>
|
||||
<h2>{{ 'addon.badges.issuerdetails' | translate}}</h2>
|
||||
</ion-item-divider>
|
||||
|
@ -48,7 +48,7 @@
|
|||
</ion-item>
|
||||
</ion-item-group>
|
||||
|
||||
<ion-item-group>
|
||||
<ion-item-group *ngIf="badge">
|
||||
<ion-item-divider>
|
||||
<h2>{{ 'addon.badges.badgedetails' | translate}}</h2>
|
||||
</ion-item-divider>
|
||||
|
@ -99,7 +99,7 @@
|
|||
<!-- Criteria (not yet avalaible) -->
|
||||
</ion-item-group>
|
||||
|
||||
<ion-item-group>
|
||||
<ion-item-group *ngIf="badge">
|
||||
<ion-item-divider>
|
||||
<h2>{{ 'addon.badges.issuancedetails' | translate}}</h2>
|
||||
</ion-item-divider>
|
||||
|
@ -120,7 +120,7 @@
|
|||
</ion-item-group>
|
||||
|
||||
<!-- Endorsement -->
|
||||
<ion-item-group *ngIf="badge.endorsement">
|
||||
<ion-item-group *ngIf="badge && badge.endorsement">
|
||||
<ion-item-divider>
|
||||
<h2>{{ 'addon.badges.bendorsement' | translate}}</h2>
|
||||
</ion-item-divider>
|
||||
|
@ -159,7 +159,7 @@
|
|||
</ion-item-group>
|
||||
|
||||
<!-- Related badges -->
|
||||
<ion-item-group *ngIf="badge.relatedbadges">
|
||||
<ion-item-group *ngIf="badge && badge.relatedbadges">
|
||||
<ion-item-divider>
|
||||
<h2>{{ 'addon.badges.relatedbages' | translate}}</h2>
|
||||
</ion-item-divider>
|
||||
|
@ -172,7 +172,7 @@
|
|||
</ion-item-group>
|
||||
|
||||
<!-- Competencies alignment -->
|
||||
<ion-item-group *ngIf="badge.competencies">
|
||||
<ion-item-group *ngIf="badge && badge.competencies">
|
||||
<ion-item-divider>
|
||||
<h2>{{ 'addon.badges.alignment' | translate}}</h2>
|
||||
</ion-item-divider>
|
||||
|
|
|
@ -19,7 +19,7 @@ import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
|||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||
import { AddonBadgesProvider } from '../../providers/badges';
|
||||
import { AddonBadgesProvider, AddonBadgesUserBadge } from '../../providers/badges';
|
||||
|
||||
/**
|
||||
* Page that displays the list of calendar events.
|
||||
|
@ -38,7 +38,7 @@ export class AddonBadgesIssuedBadgePage {
|
|||
|
||||
user: any = {};
|
||||
course: any = {};
|
||||
badge: any = {};
|
||||
badge: AddonBadgesUserBadge;
|
||||
|
||||
badgeLoaded = false;
|
||||
currentTime = 0;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import { Component, ViewChild } from '@angular/core';
|
||||
import { IonicPage, Content, NavParams } from 'ionic-angular';
|
||||
import { AddonBadgesProvider } from '../../providers/badges';
|
||||
import { AddonBadgesProvider, AddonBadgesUserBadge } from '../../providers/badges';
|
||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
|
@ -36,7 +36,7 @@ export class AddonBadgesUserBadgesPage {
|
|||
userId: number;
|
||||
|
||||
badgesLoaded = false;
|
||||
badges = [];
|
||||
badges: AddonBadgesUserBadge[] = [];
|
||||
currentTime = 0;
|
||||
badgeHash: string;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreWSExternalWarning } from '@providers/ws';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
|
@ -70,7 +71,7 @@ export class AddonBadgesProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise to be resolved when the badges are retrieved.
|
||||
*/
|
||||
getUserBadges(courseId: number, userId: number, siteId?: string): Promise<any> {
|
||||
getUserBadges(courseId: number, userId: number, siteId?: string): Promise<AddonBadgesUserBadge[]> {
|
||||
|
||||
this.logger.debug('Get badges for course ' + courseId);
|
||||
|
||||
|
@ -110,3 +111,76 @@ export class AddonBadgesProvider {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Result of WS core_badges_get_user_badges.
|
||||
*/
|
||||
export type AddonBadgesGetUserBadgesResult = {
|
||||
badges: AddonBadgesUserBadge[]; // List of badges.
|
||||
warnings?: CoreWSExternalWarning[]; // List of warnings.
|
||||
};
|
||||
|
||||
/**
|
||||
* Badge data returned by WS core_badges_get_user_badges.
|
||||
*/
|
||||
export type AddonBadgesUserBadge = {
|
||||
id?: number; // Badge id.
|
||||
name: string; // Badge name.
|
||||
description: string; // Badge description.
|
||||
timecreated?: number; // Time created.
|
||||
timemodified?: number; // Time modified.
|
||||
usercreated?: number; // User created.
|
||||
usermodified?: number; // User modified.
|
||||
issuername: string; // Issuer name.
|
||||
issuerurl: string; // Issuer URL.
|
||||
issuercontact: string; // Issuer contact.
|
||||
expiredate?: number; // Expire date.
|
||||
expireperiod?: number; // Expire period.
|
||||
type?: number; // Type.
|
||||
courseid?: number; // Course id.
|
||||
message?: string; // Message.
|
||||
messagesubject?: string; // Message subject.
|
||||
attachment?: number; // Attachment.
|
||||
notification?: number; // @since 3.6. Whether to notify when badge is awarded.
|
||||
nextcron?: number; // @since 3.6. Next cron.
|
||||
status?: number; // Status.
|
||||
issuedid?: number; // Issued id.
|
||||
uniquehash: string; // Unique hash.
|
||||
dateissued: number; // Date issued.
|
||||
dateexpire: number; // Date expire.
|
||||
visible?: number; // Visible.
|
||||
email?: string; // @since 3.6. User email.
|
||||
version?: string; // @since 3.6. Version.
|
||||
language?: string; // @since 3.6. Language.
|
||||
imageauthorname?: string; // @since 3.6. Name of the image author.
|
||||
imageauthoremail?: string; // @since 3.6. Email of the image author.
|
||||
imageauthorurl?: string; // @since 3.6. URL of the image author.
|
||||
imagecaption?: string; // @since 3.6. Caption of the image.
|
||||
badgeurl: string; // Badge URL.
|
||||
endorsement?: { // @since 3.6.
|
||||
id: number; // Endorsement id.
|
||||
badgeid: number; // Badge id.
|
||||
issuername: string; // Endorsement issuer name.
|
||||
issuerurl: string; // Endorsement issuer URL.
|
||||
issueremail: string; // Endorsement issuer email.
|
||||
claimid: string; // Claim URL.
|
||||
claimcomment: string; // Claim comment.
|
||||
dateissued: number; // Date issued.
|
||||
};
|
||||
alignment: { // @since 3.6. Badge alignments.
|
||||
id?: number; // Alignment id.
|
||||
badgeid?: number; // Badge id.
|
||||
targetName?: string; // Target name.
|
||||
targetUrl?: string; // Target URL.
|
||||
targetDescription?: string; // Target description.
|
||||
targetFramework?: string; // Target framework.
|
||||
targetCode?: string; // Target code.
|
||||
}[];
|
||||
relatedbadges: { // @since 3.6. Related badges.
|
||||
id: number; // Badge id.
|
||||
name: string; // Badge name.
|
||||
version?: string; // Version.
|
||||
language?: string; // Language.
|
||||
type?: number; // Type.
|
||||
}[];
|
||||
};
|
||||
|
|
|
@ -16,7 +16,9 @@ import { Component, OnInit, Injector, Optional } from '@angular/core';
|
|||
import { NavController } from 'ionic-angular';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreBlockBaseComponent } from '@core/block/classes/base-block-component';
|
||||
import { AddonBlockRecentlyAccessedItemsProvider } from '../../providers/recentlyaccesseditems';
|
||||
import {
|
||||
AddonBlockRecentlyAccessedItemsProvider, AddonBlockRecentlyAccessedItemsItem
|
||||
} from '../../providers/recentlyaccesseditems';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
|
||||
|
||||
|
@ -28,7 +30,7 @@ import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/hel
|
|||
templateUrl: 'addon-block-recentlyaccesseditems.html'
|
||||
})
|
||||
export class AddonBlockRecentlyAccessedItemsComponent extends CoreBlockBaseComponent implements OnInit {
|
||||
items = [];
|
||||
items: AddonBlockRecentlyAccessedItemsItem[] = [];
|
||||
|
||||
protected fetchContentDefaultError = 'Error getting recently accessed items data.';
|
||||
|
||||
|
|
|
@ -42,14 +42,16 @@ export class AddonBlockRecentlyAccessedItemsProvider {
|
|||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Promise resolved when the info is retrieved.
|
||||
*/
|
||||
getRecentItems(siteId?: string): Promise<any[]> {
|
||||
getRecentItems(siteId?: string): Promise<AddonBlockRecentlyAccessedItemsItem[]> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const preSets = {
|
||||
cacheKey: this.getRecentItemsCacheKey()
|
||||
};
|
||||
|
||||
return site.read('block_recentlyaccesseditems_get_recent_items', undefined, preSets).then((items) => {
|
||||
return site.read('block_recentlyaccesseditems_get_recent_items', undefined, preSets)
|
||||
.then((items: AddonBlockRecentlyAccessedItemsItem[]) => {
|
||||
|
||||
return items.map((item) => {
|
||||
const modicon = item.icon && this.domUtils.getHTMLElementAttribute(item.icon, 'src');
|
||||
item.iconUrl = this.courseProvider.getModuleIconSrc(item.modname, modicon);
|
||||
|
@ -72,3 +74,27 @@ export class AddonBlockRecentlyAccessedItemsProvider {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Result of WS block_recentlyaccesseditems_get_recent_items.
|
||||
*/
|
||||
export type AddonBlockRecentlyAccessedItemsItem = {
|
||||
id: number; // Id.
|
||||
courseid: number; // Courseid.
|
||||
cmid: number; // Cmid.
|
||||
userid: number; // Userid.
|
||||
modname: string; // Modname.
|
||||
name: string; // Name.
|
||||
coursename: string; // Coursename.
|
||||
timeaccess: number; // Timeaccess.
|
||||
viewurl: string; // Viewurl.
|
||||
courseviewurl: string; // Courseviewurl.
|
||||
icon: string; // Icon.
|
||||
} & AddonBlockRecentlyAccessedItemsItemCalculatedData;
|
||||
|
||||
/**
|
||||
* Calculated data for recently accessed item.
|
||||
*/
|
||||
export type AddonBlockRecentlyAccessedItemsItemCalculatedData = {
|
||||
iconUrl: string; // Icon URL. Calculated by the app.
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@ import { CoreCoursesHelperProvider } from '@core/courses/providers/helper';
|
|||
import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delegate';
|
||||
import { CoreBlockBaseComponent } from '@core/block/classes/base-block-component';
|
||||
import { AddonBlockTimelineProvider } from '../../providers/timeline';
|
||||
import { AddonCalendarEvent } from '@addon/calendar/providers/calendar';
|
||||
|
||||
/**
|
||||
* Component to render a timeline block.
|
||||
|
@ -34,9 +35,9 @@ export class AddonBlockTimelineComponent extends CoreBlockBaseComponent implemen
|
|||
filter = 'next30days';
|
||||
currentSite: any;
|
||||
timeline = {
|
||||
events: [],
|
||||
events: <AddonCalendarEvent[]> [],
|
||||
loaded: false,
|
||||
canLoadMore: undefined
|
||||
canLoadMore: <number> undefined
|
||||
};
|
||||
timelineCourses = {
|
||||
courses: [],
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreCoursesDashboardProvider } from '@core/courses/providers/dashboard';
|
||||
import { AddonCalendarEvents, AddonCalendarEventsGroupedByCourse, AddonCalendarEvent } from '@addon/calendar/providers/calendar';
|
||||
import * as moment from 'moment';
|
||||
|
||||
/**
|
||||
|
@ -38,7 +39,7 @@ export class AddonBlockTimelineProvider {
|
|||
* @return Promise resolved when the info is retrieved.
|
||||
*/
|
||||
getActionEventsByCourse(courseId: number, afterEventId?: number, siteId?: string):
|
||||
Promise<{ events: any[], canLoadMore: number }> {
|
||||
Promise<{ events: AddonCalendarEvent[], canLoadMore: number }> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const time = moment().subtract(14, 'days').unix(), // Check two weeks ago.
|
||||
|
@ -55,7 +56,9 @@ export class AddonBlockTimelineProvider {
|
|||
data.aftereventid = afterEventId;
|
||||
}
|
||||
|
||||
return site.read('core_calendar_get_action_events_by_course', data, preSets).then((courseEvents): any => {
|
||||
return site.read('core_calendar_get_action_events_by_course', data, preSets)
|
||||
.then((courseEvents: AddonCalendarEvents): any => {
|
||||
|
||||
if (courseEvents && courseEvents.events) {
|
||||
return this.treatCourseEvents(courseEvents, time);
|
||||
}
|
||||
|
@ -82,8 +85,9 @@ export class AddonBlockTimelineProvider {
|
|||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Promise resolved when the info is retrieved.
|
||||
*/
|
||||
getActionEventsByCourses(courseIds: number[], siteId?: string): Promise<{ [s: string]:
|
||||
{ events: any[], canLoadMore: number } }> {
|
||||
getActionEventsByCourses(courseIds: number[], siteId?: string): Promise<{ [courseId: string]:
|
||||
{ events: AddonCalendarEvent[], canLoadMore: number } }> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const time = moment().subtract(14, 'days').unix(), // Check two weeks ago.
|
||||
data = {
|
||||
|
@ -95,7 +99,9 @@ export class AddonBlockTimelineProvider {
|
|||
cacheKey: this.getActionEventsByCoursesCacheKey()
|
||||
};
|
||||
|
||||
return site.read('core_calendar_get_action_events_by_courses', data, preSets).then((events): any => {
|
||||
return site.read('core_calendar_get_action_events_by_courses', data, preSets)
|
||||
.then((events: AddonCalendarEventsGroupedByCourse): any => {
|
||||
|
||||
if (events && events.groupedbycourse) {
|
||||
const courseEvents = {};
|
||||
|
||||
|
@ -127,7 +133,9 @@ export class AddonBlockTimelineProvider {
|
|||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Promise resolved when the info is retrieved.
|
||||
*/
|
||||
getActionEventsByTimesort(afterEventId: number, siteId?: string): Promise<{ events: any[], canLoadMore: number }> {
|
||||
getActionEventsByTimesort(afterEventId: number, siteId?: string):
|
||||
Promise<{ events: AddonCalendarEvent[], canLoadMore: number }> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const time = moment().subtract(14, 'days').unix(), // Check two weeks ago.
|
||||
data: any = {
|
||||
|
@ -144,12 +152,14 @@ export class AddonBlockTimelineProvider {
|
|||
data.aftereventid = afterEventId;
|
||||
}
|
||||
|
||||
return site.read('core_calendar_get_action_events_by_timesort', data, preSets).then((events): any => {
|
||||
if (events && events.events) {
|
||||
const canLoadMore = events.events.length >= data.limitnum ? events.lastid : undefined;
|
||||
return site.read('core_calendar_get_action_events_by_timesort', data, preSets)
|
||||
.then((result: AddonCalendarEvents): any => {
|
||||
|
||||
if (result && result.events) {
|
||||
const canLoadMore = result.events.length >= data.limitnum ? result.lastid : undefined;
|
||||
|
||||
// Filter events by time in case it uses cache.
|
||||
events = events.events.filter((element) => {
|
||||
const events = result.events.filter((element) => {
|
||||
return element.timesort >= time;
|
||||
});
|
||||
|
||||
|
@ -236,7 +246,9 @@ export class AddonBlockTimelineProvider {
|
|||
* @param timeFrom Current time to filter events from.
|
||||
* @return Object with course events and last loaded event id if more can be loaded.
|
||||
*/
|
||||
protected treatCourseEvents(course: any, timeFrom: number): { events: any[], canLoadMore: number } {
|
||||
protected treatCourseEvents(course: AddonCalendarEvents, timeFrom: number):
|
||||
{ events: AddonCalendarEvent[], canLoadMore: number } {
|
||||
|
||||
const canLoadMore: number =
|
||||
course.events.length >= AddonBlockTimelineProvider.EVENTS_LIMIT_PER_COURSE ? course.lastid : undefined;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
|||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
import { AddonBlogProvider } from '../../providers/blog';
|
||||
import { AddonBlogProvider, AddonBlogPost } from '../../providers/blog';
|
||||
import { CoreCommentsProvider } from '@core/comments/providers/comments';
|
||||
import { CoreTagProvider } from '@core/tag/providers/tag';
|
||||
|
||||
|
@ -48,7 +48,7 @@ export class AddonBlogEntriesComponent implements OnInit {
|
|||
loaded = false;
|
||||
canLoadMore = false;
|
||||
loadMoreError = false;
|
||||
entries = [];
|
||||
entries: AddonBlogPostFormatted[] = [];
|
||||
currentUserId: number;
|
||||
showMyEntriesToggle = false;
|
||||
onlyMyEntries = false;
|
||||
|
@ -118,7 +118,7 @@ export class AddonBlogEntriesComponent implements OnInit {
|
|||
const loadPage = this.onlyMyEntries ? this.userPageLoaded : this.pageLoaded;
|
||||
|
||||
return this.blogProvider.getEntries(this.filter, loadPage).then((result) => {
|
||||
const promises = result.entries.map((entry) => {
|
||||
const promises = result.entries.map((entry: AddonBlogPostFormatted) => {
|
||||
switch (entry.publishstate) {
|
||||
case 'draft':
|
||||
entry.publishTranslated = 'publishtonoone';
|
||||
|
@ -237,5 +237,12 @@ export class AddonBlogEntriesComponent implements OnInit {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Blog post with some calculated data.
|
||||
*/
|
||||
type AddonBlogPostFormatted = AddonBlogPost & {
|
||||
publishTranslated?: string; // Calculated in the app. Key of the string to translate the publish state of the post.
|
||||
user?: any; // Calculated in the app. Data of the user that wrote the post.
|
||||
};
|
||||
|
|
|
@ -18,6 +18,8 @@ import { CoreSitesProvider } from '@providers/sites';
|
|||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications';
|
||||
import { CoreSite } from '@classes/site';
|
||||
import { CoreWSExternalWarning, CoreWSExternalFile } from '@providers/ws';
|
||||
import { CoreTagItem } from '@core/tag/providers/tag';
|
||||
|
||||
/**
|
||||
* Service to handle blog entries.
|
||||
|
@ -68,7 +70,7 @@ export class AddonBlogProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise to be resolved when the entries are retrieved.
|
||||
*/
|
||||
getEntries(filter: any = {}, page: number = 0, siteId?: string): Promise<any> {
|
||||
getEntries(filter: any = {}, page: number = 0, siteId?: string): Promise<AddonBlogGetEntriesResult> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const data = {
|
||||
filters: this.utils.objectToArrayOfObjects(filter, 'name', 'value'),
|
||||
|
@ -105,7 +107,7 @@ export class AddonBlogProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise to be resolved when done.
|
||||
*/
|
||||
logView(filter: any = {}, siteId?: string): Promise<any> {
|
||||
logView(filter: any = {}, siteId?: string): Promise<AddonBlogViewEntriesResult> {
|
||||
this.pushNotificationsProvider.logViewListEvent('blog', 'core_blog_view_entries', filter, siteId);
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
@ -117,3 +119,48 @@ export class AddonBlogProvider {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data returned by blog's post_exporter.
|
||||
*/
|
||||
export type AddonBlogPost = {
|
||||
id: number; // Post/entry id.
|
||||
module: string; // Where it was published the post (blog, blog_external...).
|
||||
userid: number; // Post author.
|
||||
courseid: number; // Course where the post was created.
|
||||
groupid: number; // Group post was created for.
|
||||
moduleid: number; // Module id where the post was created (not used anymore).
|
||||
coursemoduleid: number; // Course module id where the post was created.
|
||||
subject: string; // Post subject.
|
||||
summary: string; // Post summary.
|
||||
summaryformat: number; // Summary format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||
content: string; // Post content.
|
||||
uniquehash: string; // Post unique hash.
|
||||
rating: number; // Post rating.
|
||||
format: number; // Post content format.
|
||||
attachment: string; // Post atachment.
|
||||
publishstate: string; // Post publish state.
|
||||
lastmodified: number; // When it was last modified.
|
||||
created: number; // When it was created.
|
||||
usermodified: number; // User that updated the post.
|
||||
summaryfiles: CoreWSExternalFile[]; // Summaryfiles.
|
||||
attachmentfiles?: CoreWSExternalFile[]; // Attachmentfiles.
|
||||
tags?: CoreTagItem[]; // @since 3.7. Tags.
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_blog_get_entries.
|
||||
*/
|
||||
export type AddonBlogGetEntriesResult = {
|
||||
entries: AddonBlogPost[];
|
||||
totalentries: number; // The total number of entries found.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_blog_view_entries.
|
||||
*/
|
||||
export type AddonBlogViewEntriesResult = {
|
||||
status: boolean; // Status: true if success.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@ import { CoreCourseProvider } from '@core/course/providers/course';
|
|||
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
||||
import { AddonBlogEntriesComponent } from '../components/entries/entries';
|
||||
import { AddonBlogProvider } from './blog';
|
||||
import { CoreWSExternalFile } from '@providers/ws';
|
||||
|
||||
/**
|
||||
* Course nav handler.
|
||||
|
@ -100,7 +101,7 @@ export class AddonBlogCourseOptionHandler implements CoreCourseOptionsHandler {
|
|||
|
||||
return this.blogProvider.getEntries({courseid: course.id}).then((result) => {
|
||||
return result.entries.map((entry) => {
|
||||
let files = [];
|
||||
let files: CoreWSExternalFile[] = [];
|
||||
|
||||
if (entry.attachmentfiles && entry.attachmentfiles.length) {
|
||||
files = entry.attachmentfiles;
|
||||
|
|
|
@ -19,7 +19,7 @@ import { CoreSitesProvider } from '@providers/sites';
|
|||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { AddonCalendarProvider } from '../../providers/calendar';
|
||||
import { AddonCalendarProvider, AddonCalendarWeek } from '../../providers/calendar';
|
||||
import { AddonCalendarHelperProvider } from '../../providers/helper';
|
||||
import { AddonCalendarOfflineProvider } from '../../providers/calendar-offline';
|
||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||
|
@ -44,7 +44,7 @@ export class AddonCalendarCalendarComponent implements OnInit, OnChanges, OnDest
|
|||
|
||||
periodName: string;
|
||||
weekDays: any[];
|
||||
weeks: any[];
|
||||
weeks: AddonCalendarWeek[];
|
||||
loaded = false;
|
||||
timeFormat: string;
|
||||
isCurrentMonth: boolean;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<ng-container *ngFor="let event of filteredEvents">
|
||||
<a ion-item text-wrap [title]="event.name" (click)="eventClicked(event)" [class.core-split-item-selected]="event.id == eventId" class="addon-calendar-event" [ngClass]="['addon-calendar-eventtype-'+event.eventtype]">
|
||||
<img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" item-start class="core-module-icon">
|
||||
<core-icon *ngIf="event.icon && !event.moduleIcon" [name]="event.icon" item-start></core-icon>
|
||||
<core-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" item-start></core-icon>
|
||||
<h2><core-format-text [text]="event.name"></core-format-text></h2>
|
||||
<p><core-format-text [text]="event.formattedtime"></core-format-text></p>
|
||||
<ion-note *ngIf="event.offline && !event.deleted" item-end>
|
||||
|
|
|
@ -17,7 +17,7 @@ import { CoreEventsProvider } from '@providers/events';
|
|||
import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { AddonCalendarProvider } from '../../providers/calendar';
|
||||
import { AddonCalendarProvider, AddonCalendarCalendarEvent } from '../../providers/calendar';
|
||||
import { AddonCalendarHelperProvider } from '../../providers/helper';
|
||||
import { AddonCalendarOfflineProvider } from '../../providers/calendar-offline';
|
||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||
|
@ -43,8 +43,8 @@ export class AddonCalendarUpcomingEventsComponent implements OnInit, OnChanges,
|
|||
protected categoriesRetrieved = false;
|
||||
protected categories = {};
|
||||
protected currentSiteId: string;
|
||||
protected events = []; // Events (both online and offline).
|
||||
protected onlineEvents = [];
|
||||
protected events: AddonCalendarCalendarEvent[] = []; // Events (both online and offline).
|
||||
protected onlineEvents: AddonCalendarCalendarEvent[] = [];
|
||||
protected offlineEvents = []; // Offline events.
|
||||
protected deletedEvents = []; // Events deleted in offline.
|
||||
protected lookAhead: number;
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<ng-container *ngFor="let event of filteredEvents">
|
||||
<ion-item text-wrap [title]="event.name" (click)="gotoEvent(event.id)" [class.item-dimmed]="event.ispast" class="addon-calendar-event" [ngClass]="['addon-calendar-eventtype-'+event.eventtype]">
|
||||
<img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" item-start class="core-module-icon">
|
||||
<core-icon *ngIf="event.icon && !event.moduleIcon" [name]="event.icon" item-start></core-icon>
|
||||
<core-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" item-start></core-icon>
|
||||
<h2><core-format-text [text]="event.name"></core-format-text></h2>
|
||||
<p><core-format-text [text]="event.formattedtime"></core-format-text></p>
|
||||
<ion-note *ngIf="event.offline && !event.deleted" item-end>
|
||||
|
|
|
@ -20,7 +20,7 @@ import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
|||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||
import { AddonCalendarProvider } from '../../providers/calendar';
|
||||
import { AddonCalendarProvider, AddonCalendarCalendarEvent } from '../../providers/calendar';
|
||||
import { AddonCalendarOfflineProvider } from '../../providers/calendar-offline';
|
||||
import { AddonCalendarHelperProvider } from '../../providers/helper';
|
||||
import { AddonCalendarSyncProvider } from '../../providers/calendar-sync';
|
||||
|
@ -45,7 +45,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
|
|||
protected day: number;
|
||||
protected categories = {};
|
||||
protected events = []; // Events (both online and offline).
|
||||
protected onlineEvents = [];
|
||||
protected onlineEvents: AddonCalendarCalendarEvent[] = [];
|
||||
protected offlineEvents = {}; // Offline events.
|
||||
protected offlineEditedEventsIds = []; // IDs of events edited in offline.
|
||||
protected deletedEvents = []; // Events deleted in offline.
|
||||
|
@ -287,7 +287,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
|
|||
return this.calendarProvider.getDayEvents(this.year, this.month, this.day).catch((error) => {
|
||||
if (!this.appProvider.isOnline()) {
|
||||
// Allow navigating to non-cached days in offline (behave as if using emergency cache).
|
||||
return Promise.resolve({ events: [] });
|
||||
return Promise.resolve({ events: <AddonCalendarCalendarEvent[]> [] });
|
||||
} else {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@
|
|||
<div *ngIf="event && event.repeatid" text-wrap radio-group [formControlName]="'repeateditall'" class="addon-calendar-radio-container">
|
||||
<ion-item class="addon-calendar-radio-title"><h2>{{ 'addon.calendar.repeatedevents' | translate }}</h2></ion-item>
|
||||
<ion-item>
|
||||
<ion-label>{{ 'addon.calendar.repeateditall' | translate:{$a: event.othereventscount} }}</ion-label>
|
||||
<ion-label>{{ 'addon.calendar.repeateditall' | translate:{$a: otherEventsCount} }}</ion-label>
|
||||
<ion-radio [value]="1"></ion-radio>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
|
|
|
@ -27,7 +27,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils';
|
|||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||
import { CoreRichTextEditorComponent } from '@components/rich-text-editor/rich-text-editor.ts';
|
||||
import { AddonCalendarProvider } from '../../providers/calendar';
|
||||
import { AddonCalendarProvider, AddonCalendarGetAccessInfoResult, AddonCalendarEvent } from '../../providers/calendar';
|
||||
import { AddonCalendarOfflineProvider } from '../../providers/calendar-offline';
|
||||
import { AddonCalendarHelperProvider } from '../../providers/helper';
|
||||
import { AddonCalendarSyncProvider } from '../../providers/calendar-sync';
|
||||
|
@ -58,7 +58,8 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
|||
courseGroupSet = false;
|
||||
advanced = false;
|
||||
errors: any;
|
||||
event: any; // The event object (when editing an event).
|
||||
event: AddonCalendarEvent; // The event object (when editing an event).
|
||||
otherEventsCount: number;
|
||||
|
||||
// Form variables.
|
||||
eventForm: FormGroup;
|
||||
|
@ -70,7 +71,7 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
|||
protected courseId: number;
|
||||
protected originalData: any;
|
||||
protected currentSite: CoreSite;
|
||||
protected types: any; // Object with the supported types.
|
||||
protected types: {[name: string]: boolean}; // Object with the supported types.
|
||||
protected showAll: boolean;
|
||||
protected isDestroyed = false;
|
||||
protected error = false;
|
||||
|
@ -152,7 +153,7 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
|||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected fetchData(refresh?: boolean): Promise<any> {
|
||||
let accessInfo;
|
||||
let accessInfo: AddonCalendarGetAccessInfoResult;
|
||||
|
||||
this.error = false;
|
||||
|
||||
|
@ -197,7 +198,7 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
|||
promises.push(this.calendarProvider.getEventById(this.eventId).then((event) => {
|
||||
this.event = event;
|
||||
if (event && event.repeatid) {
|
||||
event.othereventscount = event.eventcount ? event.eventcount - 1 : '';
|
||||
this.otherEventsCount = event.eventcount ? event.eventcount - 1 : 0;
|
||||
}
|
||||
|
||||
return event;
|
||||
|
@ -489,7 +490,7 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
|||
|
||||
// Send the data.
|
||||
const modal = this.domUtils.showModalLoading('core.sending', true);
|
||||
let event;
|
||||
let event: AddonCalendarEvent;
|
||||
|
||||
this.calendarProvider.submitEvent(this.eventId, data).then((result) => {
|
||||
event = result.event;
|
||||
|
@ -497,7 +498,7 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
|||
if (result.sent) {
|
||||
// Event created or edited, invalidate right days & months.
|
||||
const numberOfRepetitions = formData.repeat ? formData.repeats :
|
||||
(data.repeateditall && this.event.othereventscount ? this.event.othereventscount + 1 : 1);
|
||||
(data.repeateditall && this.otherEventsCount ? this.otherEventsCount + 1 : 1);
|
||||
|
||||
return this.calendarHelper.refreshAfterChangeEvent(result.event, numberOfRepetitions).catch(() => {
|
||||
// Ignore errors.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<ion-navbar core-back-button>
|
||||
<ion-title>
|
||||
<img *ngIf="event && event.moduleIcon" src="{{event.moduleIcon}}" alt="" role="presentation" class="core-module-icon">
|
||||
<core-icon *ngIf="event && event.icon && !event.moduleIcon" [name]="event.icon" item-start></core-icon>
|
||||
<core-icon *ngIf="event && event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" item-start></core-icon>
|
||||
<core-format-text *ngIf="event" [text]="event.name"></core-format-text>
|
||||
</ion-title>
|
||||
<ion-buttons end>
|
||||
|
@ -32,7 +32,7 @@
|
|||
<ion-card-content *ngIf="event">
|
||||
<ion-item text-wrap *ngIf="isSplitViewOn">
|
||||
<img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" item-start alt="" role="presentation" class="core-module-icon">
|
||||
<core-icon *ngIf="event.icon && !event.moduleIcon" [name]="event.icon" item-start></core-icon>
|
||||
<core-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" item-start></core-icon>
|
||||
<h2>{{ 'addon.calendar.eventname' | translate }}</h2>
|
||||
<p><core-format-text [text]="event.name"></core-format-text></p>
|
||||
<ion-note item-end *ngIf="event.deleted">
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
</ion-item-divider>
|
||||
<a ion-item text-wrap [title]="event.name" (click)="gotoEvent(event.id)" [class.core-split-item-selected]="event.id == eventId" class="addon-calendar-event" [ngClass]="['addon-calendar-eventtype-'+event.eventtype]">
|
||||
<img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" item-start class="core-module-icon">
|
||||
<core-icon *ngIf="event.icon && !event.moduleIcon" [name]="event.icon" item-start></core-icon>
|
||||
<core-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" item-start></core-icon>
|
||||
<h2><core-format-text [text]="event.name"></core-format-text></h2>
|
||||
<p>
|
||||
{{ event.timestart * 1000 | coreFormatDate: "strftimetime" }}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import { Component, ViewChild, OnDestroy, NgZone } from '@angular/core';
|
||||
import { IonicPage, Content, NavParams, NavController } from 'ionic-angular';
|
||||
import { AddonCalendarProvider } from '../../providers/calendar';
|
||||
import { AddonCalendarProvider, AddonCalendarGetEventsEvent } from '../../providers/calendar';
|
||||
import { AddonCalendarOfflineProvider } from '../../providers/calendar-offline';
|
||||
import { AddonCalendarHelperProvider } from '../../providers/helper';
|
||||
import { AddonCalendarSyncProvider } from '../../providers/calendar-sync';
|
||||
|
@ -62,7 +62,7 @@ export class AddonCalendarListPage implements OnDestroy {
|
|||
protected manualSyncObserver: any;
|
||||
protected onlineObserver: any;
|
||||
protected currentSiteId: string;
|
||||
protected onlineEvents = [];
|
||||
protected onlineEvents: AddonCalendarGetEventsEvent[] = [];
|
||||
protected offlineEvents = [];
|
||||
protected deletedEvents = [];
|
||||
|
||||
|
@ -70,7 +70,7 @@ export class AddonCalendarListPage implements OnDestroy {
|
|||
eventsLoaded = false;
|
||||
events = []; // Events (both online and offline).
|
||||
notificationsEnabled = false;
|
||||
filteredEvents = [];
|
||||
filteredEvents: AddonCalendarGetEventsEvent[] = [];
|
||||
canLoadMore = false;
|
||||
loadMoreError = false;
|
||||
courseId: number;
|
||||
|
@ -402,7 +402,7 @@ export class AddonCalendarListPage implements OnDestroy {
|
|||
*
|
||||
* @return Filtered events.
|
||||
*/
|
||||
protected getFilteredEvents(): any[] {
|
||||
protected getFilteredEvents(): AddonCalendarGetEventsEvent[] {
|
||||
if (!this.courseId) {
|
||||
// No filter, display everything.
|
||||
return this.events;
|
||||
|
@ -581,7 +581,7 @@ export class AddonCalendarListPage implements OnDestroy {
|
|||
* @param event Event info.
|
||||
* @return If date has changed and should be shown.
|
||||
*/
|
||||
protected endsSameDay(event: any): boolean {
|
||||
protected endsSameDay(event: AddonCalendarGetEventsEvent): boolean {
|
||||
if (!event.timeduration) {
|
||||
// No duration.
|
||||
return true;
|
||||
|
|
|
@ -31,6 +31,7 @@ import { SQLiteDB } from '@classes/sqlitedb';
|
|||
import { AddonCalendarOfflineProvider } from './calendar-offline';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreWSExternalWarning, CoreWSDate } from '@providers/ws';
|
||||
import * as moment from 'moment';
|
||||
|
||||
/**
|
||||
|
@ -489,7 +490,7 @@ export class AddonCalendarProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
deleteEventOnline(eventId: number, deleteAll?: boolean, siteId?: string): Promise<any> {
|
||||
deleteEventOnline(eventId: number, deleteAll?: boolean, siteId?: string): Promise<null> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
||||
const params = {
|
||||
|
@ -535,22 +536,6 @@ export class AddonCalendarProvider {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if event ends the same day or not.
|
||||
*
|
||||
* @param event Event info.
|
||||
* @return If the .
|
||||
*/
|
||||
endsSameDay(event: any): boolean {
|
||||
if (!event.timeduration) {
|
||||
// No duration.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if day has changed.
|
||||
return moment(event.timestart * 1000).isSame((event.timestart + event.timeduration) * 1000, 'day');
|
||||
}
|
||||
|
||||
/**
|
||||
* Format event time. Similar to calendar_format_event_time.
|
||||
*
|
||||
|
@ -562,8 +547,8 @@ export class AddonCalendarProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with the formatted event time.
|
||||
*/
|
||||
formatEventTime(event: any, format: string, useCommonWords: boolean = true, seenDay?: number, showTime: number = 0,
|
||||
siteId?: string): Promise<string> {
|
||||
formatEventTime(event: AddonCalendarAnyEvent, format: string, useCommonWords: boolean = true, seenDay?: number,
|
||||
showTime: number = 0, siteId?: string): Promise<string> {
|
||||
|
||||
const start = event.timestart * 1000,
|
||||
end = (event.timestart + event.timeduration) * 1000;
|
||||
|
@ -635,7 +620,7 @@ export class AddonCalendarProvider {
|
|||
* @return Promise resolved with object with access information.
|
||||
* @since 3.7
|
||||
*/
|
||||
getAccessInformation(courseId?: number, siteId?: string): Promise<any> {
|
||||
getAccessInformation(courseId?: number, siteId?: string): Promise<AddonCalendarGetAccessInfoResult> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const params: any = {},
|
||||
preSets = {
|
||||
|
@ -680,7 +665,7 @@ export class AddonCalendarProvider {
|
|||
* @return Promise resolved with an object indicating the types.
|
||||
* @since 3.7
|
||||
*/
|
||||
getAllowedEventTypes(courseId?: number, siteId?: string): Promise<any> {
|
||||
getAllowedEventTypes(courseId?: number, siteId?: string): Promise<{[name: string]: boolean}> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const params: any = {},
|
||||
preSets = {
|
||||
|
@ -691,7 +676,8 @@ export class AddonCalendarProvider {
|
|||
params.courseid = courseId;
|
||||
}
|
||||
|
||||
return site.read('core_calendar_get_allowed_event_types', params, preSets).then((response) => {
|
||||
return site.read('core_calendar_get_allowed_event_types', params, preSets)
|
||||
.then((response: AddonCalendarGetAllowedEventTypesResult) => {
|
||||
// Convert the array to an object.
|
||||
const result = {};
|
||||
|
||||
|
@ -812,11 +798,10 @@ export class AddonCalendarProvider {
|
|||
* Get a calendar event. If the server request fails and data is not cached, try to get it from local DB.
|
||||
*
|
||||
* @param id Event ID.
|
||||
* @param refresh True when we should update the event data.
|
||||
* @param siteId ID of the site. If not defined, use current site.
|
||||
* @return Promise resolved when the event data is retrieved.
|
||||
*/
|
||||
getEvent(id: number, siteId?: string): Promise<any> {
|
||||
getEvent(id: number, siteId?: string): Promise<AddonCalendarGetEventsEvent> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const preSets = {
|
||||
cacheKey: this.getEventCacheKey(id),
|
||||
|
@ -834,7 +819,8 @@ export class AddonCalendarProvider {
|
|||
}
|
||||
};
|
||||
|
||||
return site.read('core_calendar_get_calendar_events', data, preSets).then((response) => {
|
||||
return site.read('core_calendar_get_calendar_events', data, preSets)
|
||||
.then((response: AddonCalendarGetEventsResult) => {
|
||||
// The WebService returns all category events. Check the response to search for the event we want.
|
||||
const event = response.events.find((e) => { return e.id == id; });
|
||||
|
||||
|
@ -849,12 +835,11 @@ export class AddonCalendarProvider {
|
|||
* Get a calendar event by ID. This function returns more data than getEvent, but it isn't available in all Moodles.
|
||||
*
|
||||
* @param id Event ID.
|
||||
* @param refresh True when we should update the event data.
|
||||
* @param siteId ID of the site. If not defined, use current site.
|
||||
* @return Promise resolved when the event data is retrieved.
|
||||
* @since 3.4
|
||||
*/
|
||||
getEventById(id: number, siteId?: string): Promise<any> {
|
||||
getEventById(id: number, siteId?: string): Promise<AddonCalendarEvent> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const preSets = {
|
||||
cacheKey: this.getEventCacheKey(id),
|
||||
|
@ -864,7 +849,8 @@ export class AddonCalendarProvider {
|
|||
eventid: id
|
||||
};
|
||||
|
||||
return site.read('core_calendar_get_calendar_event_by_id', data, preSets).then((response) => {
|
||||
return site.read('core_calendar_get_calendar_event_by_id', data, preSets)
|
||||
.then((response: AddonCalendarGetEventByIdResult) => {
|
||||
return response.event;
|
||||
}).catch((error) => {
|
||||
return this.getEventFromLocalDb(id).catch(() => {
|
||||
|
@ -918,7 +904,7 @@ export class AddonCalendarProvider {
|
|||
* @param siteId ID of the site the event belongs to. If not defined, use current site.
|
||||
* @return Promise resolved when the notification is updated.
|
||||
*/
|
||||
addEventReminder(event: any, time: number, siteId?: string): Promise<any> {
|
||||
addEventReminder(event: AddonCalendarAnyEvent, time: number, siteId?: string): Promise<any> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const reminder = {
|
||||
eventid: event.id,
|
||||
|
@ -976,7 +962,7 @@ export class AddonCalendarProvider {
|
|||
* @return Promise resolved with the response.
|
||||
*/
|
||||
getDayEvents(year: number, month: number, day: number, courseId?: number, categoryId?: number, ignoreCache?: boolean,
|
||||
siteId?: string): Promise<any> {
|
||||
siteId?: string): Promise<AddonCalendarCalendarDay> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
||||
|
@ -1003,7 +989,7 @@ export class AddonCalendarProvider {
|
|||
preSets.emergencyCache = false;
|
||||
}
|
||||
|
||||
return site.read('core_calendar_get_calendar_day_view', data, preSets).then((response) => {
|
||||
return site.read('core_calendar_get_calendar_day_view', data, preSets).then((response: AddonCalendarCalendarDay) => {
|
||||
this.storeEventsInLocalDB(response.events, siteId);
|
||||
|
||||
return response;
|
||||
|
@ -1071,10 +1057,10 @@ export class AddonCalendarProvider {
|
|||
* @param daysToStart Number of days from now to start getting events.
|
||||
* @param daysInterval Number of days between timestart and timeend.
|
||||
* @param siteId Site to get the events from. If not defined, use current site.
|
||||
* @return Promise to be resolved when the participants are retrieved.
|
||||
* @return Promise to be resolved when the events are retrieved.
|
||||
*/
|
||||
getEventsList(initialTime?: number, daysToStart: number = 0, daysInterval: number = AddonCalendarProvider.DAYS_INTERVAL,
|
||||
siteId?: string): Promise<any[]> {
|
||||
siteId?: string): Promise<AddonCalendarGetEventsEvent[]> {
|
||||
|
||||
initialTime = initialTime || this.timeUtils.timestamp();
|
||||
|
||||
|
@ -1122,7 +1108,9 @@ export class AddonCalendarProvider {
|
|||
updateFrequency: CoreSite.FREQUENCY_SOMETIMES
|
||||
};
|
||||
|
||||
return site.read('core_calendar_get_calendar_events', data, preSets).then((response) => {
|
||||
return site.read('core_calendar_get_calendar_events', data, preSets)
|
||||
.then((response: AddonCalendarGetEventsResult) => {
|
||||
|
||||
if (!this.canViewMonthInSite(site)) {
|
||||
// Store events only in 3.1-3.3. In 3.4+ we'll use the new WS that return more info.
|
||||
this.storeEventsInLocalDB(response.events, siteId);
|
||||
|
@ -1178,7 +1166,7 @@ export class AddonCalendarProvider {
|
|||
* @return Promise resolved with the response.
|
||||
*/
|
||||
getMonthlyEvents(year: number, month: number, courseId?: number, categoryId?: number, ignoreCache?: boolean, siteId?: string)
|
||||
: Promise<any> {
|
||||
: Promise<AddonCalendarMonth> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
||||
|
@ -1210,7 +1198,9 @@ export class AddonCalendarProvider {
|
|||
preSets.emergencyCache = false;
|
||||
}
|
||||
|
||||
return site.read('core_calendar_get_calendar_monthly_view', data, preSets).then((response) => {
|
||||
return site.read('core_calendar_get_calendar_monthly_view', data, preSets)
|
||||
.then((response: AddonCalendarMonth) => {
|
||||
|
||||
response.weeks.forEach((week) => {
|
||||
week.days.forEach((day) => {
|
||||
this.storeEventsInLocalDB(day.events, siteId);
|
||||
|
@ -1270,7 +1260,8 @@ export class AddonCalendarProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with the response.
|
||||
*/
|
||||
getUpcomingEvents(courseId?: number, categoryId?: number, ignoreCache?: boolean, siteId?: string): Promise<any> {
|
||||
getUpcomingEvents(courseId?: number, categoryId?: number, ignoreCache?: boolean, siteId?: string)
|
||||
: Promise<AddonCalendarUpcoming> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
||||
|
@ -1293,7 +1284,7 @@ export class AddonCalendarProvider {
|
|||
preSets.emergencyCache = false;
|
||||
}
|
||||
|
||||
return site.read('core_calendar_get_calendar_upcoming_view', data, preSets).then((response) => {
|
||||
return site.read('core_calendar_get_calendar_upcoming_view', data, preSets).then((response: AddonCalendarUpcoming) => {
|
||||
this.storeEventsInLocalDB(response.events, siteId);
|
||||
|
||||
return response;
|
||||
|
@ -1604,11 +1595,14 @@ export class AddonCalendarProvider {
|
|||
* If local notification plugin is not enabled, resolve the promise.
|
||||
*
|
||||
* @param event Event to schedule.
|
||||
* @param reminderId The reminder ID.
|
||||
* @param time Notification setting time (in minutes). E.g. 10 means "notificate 10 minutes before start".
|
||||
* @param siteId Site ID the event belongs to. If not defined, use current site.
|
||||
* @return Promise resolved when the notification is scheduled.
|
||||
*/
|
||||
protected scheduleEventNotification(event: any, reminderId: number, time: number, siteId?: string): Promise<void> {
|
||||
protected scheduleEventNotification(event: AddonCalendarAnyEvent, reminderId: number, time: number, siteId?: string)
|
||||
: Promise<void> {
|
||||
|
||||
if (this.localNotificationsProvider.isAvailable()) {
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
||||
|
@ -1672,7 +1666,7 @@ export class AddonCalendarProvider {
|
|||
* @param siteId ID of the site the events belong to. If not defined, use current site.
|
||||
* @return Promise resolved when all the notifications have been scheduled.
|
||||
*/
|
||||
scheduleEventsNotifications(events: any[], siteId?: string): Promise<any[]> {
|
||||
scheduleEventsNotifications(events: AddonCalendarAnyEvent[], siteId?: string): Promise<any[]> {
|
||||
|
||||
if (this.localNotificationsProvider.isAvailable()) {
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
@ -1803,11 +1797,10 @@ export class AddonCalendarProvider {
|
|||
* @param timeCreated The time the event was created. Only if modifying a new offline event.
|
||||
* @param forceOffline True to always save it in offline.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with the event and a boolean indicating if data was
|
||||
* sent to server or stored in offline.
|
||||
* @return Promise resolved with the event and a boolean indicating if data was sent to server or stored in offline.
|
||||
*/
|
||||
submitEvent(eventId: number, formData: any, timeCreated?: number, forceOffline?: boolean, siteId?: string):
|
||||
Promise<{sent: boolean, event: any}> {
|
||||
Promise<{sent: boolean, event: AddonCalendarEvent}> {
|
||||
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
||||
|
@ -1847,7 +1840,7 @@ export class AddonCalendarProvider {
|
|||
* @param siteId Site ID. If not provided, current site.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
submitEventOnline(eventId: number, formData: any, siteId?: string): Promise<any> {
|
||||
submitEventOnline(eventId: number, formData: any, siteId?: string): Promise<AddonCalendarEvent> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
// Add data that is "hidden" in web.
|
||||
formData.id = eventId || 0;
|
||||
|
@ -1865,10 +1858,12 @@ export class AddonCalendarProvider {
|
|||
formdata: this.utils.objectToGetParams(formData)
|
||||
};
|
||||
|
||||
return site.write('core_calendar_submit_create_update_form', params).then((result) => {
|
||||
return site.write('core_calendar_submit_create_update_form', params)
|
||||
.then((result: AddonCalendarSubmitCreateUpdateFormResult): AddonCalendarEvent => {
|
||||
|
||||
if (result.validationerror) {
|
||||
// Simulate a WS error.
|
||||
return Promise.reject({
|
||||
return <any> Promise.reject({
|
||||
message: this.translate.instant('core.invalidformdata'),
|
||||
errorcode: 'validationerror'
|
||||
});
|
||||
|
@ -1879,3 +1874,337 @@ export class AddonCalendarProvider {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data returned by calendar's events_exporter.
|
||||
*/
|
||||
export type AddonCalendarEvents = {
|
||||
events: AddonCalendarEvent[]; // Events.
|
||||
firstid: number; // Firstid.
|
||||
lastid: number; // Lastid.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by calendar's events_grouped_by_course_exporter.
|
||||
*/
|
||||
export type AddonCalendarEventsGroupedByCourse = {
|
||||
groupedbycourse: AddonCalendarEventsSameCourse[]; // Groupped by course.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by calendar's events_same_course_exporter.
|
||||
*/
|
||||
export type AddonCalendarEventsSameCourse = AddonCalendarEvents & {
|
||||
courseid: number; // Courseid.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by calendar's event_exporter_base.
|
||||
*/
|
||||
export type AddonCalendarEventBase = {
|
||||
id: number; // Id.
|
||||
name: string; // Name.
|
||||
description?: string; // Description.
|
||||
descriptionformat: number; // Description format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||
location?: string; // Location.
|
||||
categoryid?: number; // Categoryid.
|
||||
groupid?: number; // Groupid.
|
||||
userid?: number; // Userid.
|
||||
repeatid?: number; // Repeatid.
|
||||
eventcount?: number; // Eventcount.
|
||||
modulename?: string; // Modulename.
|
||||
instance?: number; // Instance.
|
||||
eventtype: string; // Eventtype.
|
||||
timestart: number; // Timestart.
|
||||
timeduration: number; // Timeduration.
|
||||
timesort: number; // Timesort.
|
||||
visible: number; // Visible.
|
||||
timemodified: number; // Timemodified.
|
||||
icon: {
|
||||
key: string; // Key.
|
||||
component: string; // Component.
|
||||
alttext: string; // Alttext.
|
||||
};
|
||||
category?: {
|
||||
id: number; // Id.
|
||||
name: string; // Name.
|
||||
idnumber: string; // Idnumber.
|
||||
description?: string; // Description.
|
||||
parent: number; // Parent.
|
||||
coursecount: number; // Coursecount.
|
||||
visible: number; // Visible.
|
||||
timemodified: number; // Timemodified.
|
||||
depth: number; // Depth.
|
||||
nestedname: string; // Nestedname.
|
||||
url: string; // Url.
|
||||
};
|
||||
course?: {
|
||||
id: number; // Id.
|
||||
fullname: string; // Fullname.
|
||||
shortname: string; // Shortname.
|
||||
idnumber: string; // Idnumber.
|
||||
summary: string; // Summary.
|
||||
summaryformat: number; // Summary format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||
startdate: number; // Startdate.
|
||||
enddate: number; // Enddate.
|
||||
visible: boolean; // Visible.
|
||||
fullnamedisplay: string; // Fullnamedisplay.
|
||||
viewurl: string; // Viewurl.
|
||||
courseimage: string; // Courseimage.
|
||||
progress?: number; // Progress.
|
||||
hasprogress: boolean; // Hasprogress.
|
||||
isfavourite: boolean; // Isfavourite.
|
||||
hidden: boolean; // Hidden.
|
||||
timeaccess?: number; // Timeaccess.
|
||||
showshortname: boolean; // Showshortname.
|
||||
coursecategory: string; // Coursecategory.
|
||||
};
|
||||
subscription?: {
|
||||
displayeventsource: boolean; // Displayeventsource.
|
||||
subscriptionname?: string; // Subscriptionname.
|
||||
subscriptionurl?: string; // Subscriptionurl.
|
||||
};
|
||||
canedit: boolean; // Canedit.
|
||||
candelete: boolean; // Candelete.
|
||||
deleteurl: string; // Deleteurl.
|
||||
editurl: string; // Editurl.
|
||||
viewurl: string; // Viewurl.
|
||||
formattedtime: string; // Formattedtime.
|
||||
isactionevent: boolean; // Isactionevent.
|
||||
iscourseevent: boolean; // Iscourseevent.
|
||||
iscategoryevent: boolean; // Iscategoryevent.
|
||||
groupname?: string; // Groupname.
|
||||
normalisedeventtype: string; // Normalisedeventtype.
|
||||
normalisedeventtypetext: string; // Normalisedeventtypetext.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by calendar's event_exporter. Don't confuse it with AddonCalendarCalendarEvent.
|
||||
*/
|
||||
export type AddonCalendarEvent = AddonCalendarEventBase & {
|
||||
url: string; // Url.
|
||||
action?: {
|
||||
name: string; // Name.
|
||||
url: string; // Url.
|
||||
itemcount: number; // Itemcount.
|
||||
actionable: boolean; // Actionable.
|
||||
showitemcount: boolean; // Showitemcount.
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by calendar's calendar_event_exporter. Don't confuse it with AddonCalendarEvent.
|
||||
*/
|
||||
export type AddonCalendarCalendarEvent = AddonCalendarEventBase & {
|
||||
url: string; // Url.
|
||||
islastday: boolean; // Islastday.
|
||||
popupname: string; // Popupname.
|
||||
mindaytimestamp?: number; // Mindaytimestamp.
|
||||
mindayerror?: string; // Mindayerror.
|
||||
maxdaytimestamp?: number; // Maxdaytimestamp.
|
||||
maxdayerror?: string; // Maxdayerror.
|
||||
draggable: boolean; // Draggable.
|
||||
} & AddonCalendarCalendarEventCalculatedData;
|
||||
|
||||
/**
|
||||
* Any of the possible types of events.
|
||||
*/
|
||||
export type AddonCalendarAnyEvent = AddonCalendarGetEventsEvent | AddonCalendarEvent | AddonCalendarCalendarEvent;
|
||||
|
||||
/**
|
||||
* Data returned by calendar's calendar_day_exporter. Don't confuse it with AddonCalendarDay.
|
||||
*/
|
||||
export type AddonCalendarCalendarDay = {
|
||||
events: AddonCalendarCalendarEvent[]; // Events.
|
||||
defaulteventcontext: number; // Defaulteventcontext.
|
||||
filter_selector: string; // Filter_selector.
|
||||
courseid: number; // Courseid.
|
||||
categoryid?: number; // Categoryid.
|
||||
neweventtimestamp: number; // Neweventtimestamp.
|
||||
date: CoreWSDate;
|
||||
periodname: string; // Periodname.
|
||||
previousperiod: CoreWSDate;
|
||||
previousperiodlink: string; // Previousperiodlink.
|
||||
previousperiodname: string; // Previousperiodname.
|
||||
nextperiod: CoreWSDate;
|
||||
nextperiodname: string; // Nextperiodname.
|
||||
nextperiodlink: string; // Nextperiodlink.
|
||||
larrow: string; // Larrow.
|
||||
rarrow: string; // Rarrow.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by calendar's month_exporter.
|
||||
*/
|
||||
export type AddonCalendarMonth = {
|
||||
url: string; // Url.
|
||||
courseid: number; // Courseid.
|
||||
categoryid?: number; // Categoryid.
|
||||
filter_selector?: string; // Filter_selector.
|
||||
weeks: AddonCalendarWeek[]; // Weeks.
|
||||
daynames: AddonCalendarDayName[]; // Daynames.
|
||||
view: string; // View.
|
||||
date: CoreWSDate;
|
||||
periodname: string; // Periodname.
|
||||
includenavigation: boolean; // Includenavigation.
|
||||
initialeventsloaded: boolean; // Initialeventsloaded.
|
||||
previousperiod: CoreWSDate;
|
||||
previousperiodlink: string; // Previousperiodlink.
|
||||
previousperiodname: string; // Previousperiodname.
|
||||
nextperiod: CoreWSDate;
|
||||
nextperiodname: string; // Nextperiodname.
|
||||
nextperiodlink: string; // Nextperiodlink.
|
||||
larrow: string; // Larrow.
|
||||
rarrow: string; // Rarrow.
|
||||
defaulteventcontext: number; // Defaulteventcontext.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by calendar's week_exporter.
|
||||
*/
|
||||
export type AddonCalendarWeek = {
|
||||
prepadding: number[]; // Prepadding.
|
||||
postpadding: number[]; // Postpadding.
|
||||
days: AddonCalendarWeekDay[]; // Days.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by calendar's week_day_exporter.
|
||||
*/
|
||||
export type AddonCalendarWeekDay = AddonCalendarDay & {
|
||||
istoday: boolean; // Istoday.
|
||||
isweekend: boolean; // Isweekend.
|
||||
popovertitle: string; // Popovertitle.
|
||||
ispast?: boolean; // Calculated in the app. Whether the day is in the past.
|
||||
filteredEvents?: AddonCalendarCalendarEvent[]; // Calculated in the app. Filtered events.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by calendar's day_exporter. Don't confuse it with AddonCalendarCalendarDay.
|
||||
*/
|
||||
export type AddonCalendarDay = {
|
||||
seconds: number; // Seconds.
|
||||
minutes: number; // Minutes.
|
||||
hours: number; // Hours.
|
||||
mday: number; // Mday.
|
||||
wday: number; // Wday.
|
||||
year: number; // Year.
|
||||
yday: number; // Yday.
|
||||
timestamp: number; // Timestamp.
|
||||
neweventtimestamp: number; // Neweventtimestamp.
|
||||
viewdaylink?: string; // Viewdaylink.
|
||||
events: AddonCalendarCalendarEvent[]; // Events.
|
||||
hasevents: boolean; // Hasevents.
|
||||
calendareventtypes: string[]; // Calendareventtypes.
|
||||
previousperiod: number; // Previousperiod.
|
||||
nextperiod: number; // Nextperiod.
|
||||
navigation: string; // Navigation.
|
||||
haslastdayofevent: boolean; // Haslastdayofevent.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by calendar's day_name_exporter.
|
||||
*/
|
||||
export type AddonCalendarDayName = {
|
||||
dayno: number; // Dayno.
|
||||
shortname: string; // Shortname.
|
||||
fullname: string; // Fullname.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by calendar's calendar_upcoming_exporter.
|
||||
*/
|
||||
export type AddonCalendarUpcoming = {
|
||||
events: AddonCalendarCalendarEvent[]; // Events.
|
||||
defaulteventcontext: number; // Defaulteventcontext.
|
||||
filter_selector: string; // Filter_selector.
|
||||
courseid: number; // Courseid.
|
||||
categoryid?: number; // Categoryid.
|
||||
isloggedin: boolean; // Isloggedin.
|
||||
date: CoreWSDate; // Date.
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_calendar_get_calendar_access_information.
|
||||
*/
|
||||
export type AddonCalendarGetAccessInfoResult = {
|
||||
canmanageentries: boolean; // Whether the user can manage entries.
|
||||
canmanageownentries: boolean; // Whether the user can manage its own entries.
|
||||
canmanagegroupentries: boolean; // Whether the user can manage group entries.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_calendar_get_allowed_event_types.
|
||||
*/
|
||||
export type AddonCalendarGetAllowedEventTypesResult = {
|
||||
allowedeventtypes: string[];
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_calendar_get_calendar_events.
|
||||
*/
|
||||
export type AddonCalendarGetEventsResult = {
|
||||
events: AddonCalendarGetEventsEvent[];
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Event data returned by WS core_calendar_get_calendar_events.
|
||||
*/
|
||||
export type AddonCalendarGetEventsEvent = {
|
||||
id: number; // Event id.
|
||||
name: string; // Event name.
|
||||
description?: string; // Description.
|
||||
format: number; // Description format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||
courseid: number; // Course id.
|
||||
categoryid?: number; // @since 3.4. Category id (only for category events).
|
||||
groupid: number; // Group id.
|
||||
userid: number; // User id.
|
||||
repeatid: number; // Repeat id.
|
||||
modulename?: string; // Module name.
|
||||
instance: number; // Instance id.
|
||||
eventtype: string; // Event type.
|
||||
timestart: number; // Timestart.
|
||||
timeduration: number; // Time duration.
|
||||
visible: number; // Visible.
|
||||
uuid?: string; // Unique id of ical events.
|
||||
sequence: number; // Sequence.
|
||||
timemodified: number; // Time modified.
|
||||
subscriptionid?: number; // Subscription id.
|
||||
showDate?: boolean; // Calculated in the app. Whether date should be shown before this event.
|
||||
endsSameDay?: boolean; // Calculated in the app. Whether the event finishes the same day it starts.
|
||||
deleted?: boolean; // Calculated in the app. Whether it has been deleted in offline.
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_calendar_get_calendar_event_by_id.
|
||||
*/
|
||||
export type AddonCalendarGetEventByIdResult = {
|
||||
event: AddonCalendarEvent; // Event.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_calendar_submit_create_update_form.
|
||||
*/
|
||||
export type AddonCalendarSubmitCreateUpdateFormResult = {
|
||||
event?: AddonCalendarEvent; // Event.
|
||||
validationerror: boolean; // Invalid form data.
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculated data for AddonCalendarCalendarEvent.
|
||||
*/
|
||||
export type AddonCalendarCalendarEventCalculatedData = {
|
||||
eventIcon?: string; // Calculated in the app. Event icon.
|
||||
moduleIcon?: string; // Calculated in the app. Module icon.
|
||||
formattedType?: string; // Calculated in the app. Formatted type.
|
||||
duration?: number; // Calculated in the app. Duration of offline event.
|
||||
format?: number; // Calculated in the app. Format of offline event.
|
||||
timedurationuntil?: number; // Calculated in the app. Time duration until of offline event.
|
||||
timedurationminutes?: number; // Calculated in the app. Time duration in minutes of offline event.
|
||||
deleted?: boolean; // Calculated in the app. Whether it has been deleted in offline.
|
||||
ispast?: boolean; // Calculated in the app. Whether the event is in the past.
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ import { Injectable } from '@angular/core';
|
|||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||
import { AddonCalendarProvider } from './calendar';
|
||||
import { AddonCalendarProvider, AddonCalendarCalendarEvent } from './calendar';
|
||||
import { CoreConstants } from '@core/constants';
|
||||
import { CoreConfigProvider } from '@providers/config';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
|
@ -130,11 +130,11 @@ export class AddonCalendarHelperProvider {
|
|||
*
|
||||
* @param e Event to format.
|
||||
*/
|
||||
formatEventData(e: any): void {
|
||||
e.icon = this.EVENTICONS[e.eventtype] || false;
|
||||
if (!e.icon) {
|
||||
e.icon = this.courseProvider.getModuleIconSrc(e.modulename);
|
||||
e.moduleIcon = e.icon;
|
||||
formatEventData(e: AddonCalendarCalendarEvent): void {
|
||||
e.eventIcon = this.EVENTICONS[e.eventtype] || '';
|
||||
if (!e.eventIcon) {
|
||||
e.eventIcon = this.courseProvider.getModuleIconSrc(e.modulename);
|
||||
e.moduleIcon = e.eventIcon;
|
||||
}
|
||||
|
||||
e.formattedType = this.calendarProvider.getEventType(e);
|
||||
|
@ -160,7 +160,7 @@ export class AddonCalendarHelperProvider {
|
|||
* @param eventTypes Result of getAllowedEventTypes.
|
||||
* @return Options.
|
||||
*/
|
||||
getEventTypeOptions(eventTypes: any): {name: string, value: string}[] {
|
||||
getEventTypeOptions(eventTypes: {[name: string]: boolean}): {name: string, value: string}[] {
|
||||
const options = [];
|
||||
|
||||
if (eventTypes.user) {
|
||||
|
|
|
@ -16,7 +16,7 @@ import { Component, ViewChild, Input } from '@angular/core';
|
|||
import { Content, NavController } from 'ionic-angular';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { AddonCompetencyProvider } from '../../providers/competency';
|
||||
import { AddonCompetencyProvider, AddonCompetencyDataForCourseCompetenciesPageResult } from '../../providers/competency';
|
||||
import { AddonCompetencyHelperProvider } from '../../providers/helper';
|
||||
|
||||
/**
|
||||
|
@ -33,7 +33,7 @@ export class AddonCompetencyCourseComponent {
|
|||
@Input() userId: number;
|
||||
|
||||
competenciesLoaded = false;
|
||||
competencies: any;
|
||||
competencies: AddonCompetencyDataForCourseCompetenciesPageResult;
|
||||
user: any;
|
||||
|
||||
constructor(private navCtrl: NavController, private appProvider: CoreAppProvider, private domUtils: CoreDomUtilsProvider,
|
||||
|
|
|
@ -17,7 +17,10 @@ import { IonicPage, NavParams } from 'ionic-angular';
|
|||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||
import { AddonCompetencyProvider } from '../../providers/competency';
|
||||
import {
|
||||
AddonCompetencyProvider, AddonCompetencyDataForCourseCompetenciesPageResult, AddonCompetencyDataForPlanPageResult,
|
||||
AddonCompetencyDataForPlanPageCompetency, AddonCompetencyDataForCourseCompetenciesPageCompetency
|
||||
} from '../../providers/competency';
|
||||
|
||||
/**
|
||||
* Page that displays the list of competencies of a learning plan.
|
||||
|
@ -36,7 +39,7 @@ export class AddonCompetencyCompetenciesPage {
|
|||
protected userId: number;
|
||||
|
||||
competenciesLoaded = false;
|
||||
competencies = [];
|
||||
competencies: AddonCompetencyDataForPlanPageCompetency[] | AddonCompetencyDataForCourseCompetenciesPageCompetency[] = [];
|
||||
title: string;
|
||||
|
||||
constructor(navParams: NavParams, private translate: TranslateService, private domUtils: CoreDomUtilsProvider,
|
||||
|
@ -59,7 +62,7 @@ export class AddonCompetencyCompetenciesPage {
|
|||
this.fetchCompetencies().then(() => {
|
||||
if (!this.competencyId && this.splitviewCtrl.isOn() && this.competencies.length > 0) {
|
||||
// Take first and load it.
|
||||
this.openCompetency(this.competencies[0].id);
|
||||
this.openCompetency(this.competencies[0].competency.id);
|
||||
}
|
||||
}).finally(() => {
|
||||
this.competenciesLoaded = true;
|
||||
|
@ -72,7 +75,7 @@ export class AddonCompetencyCompetenciesPage {
|
|||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected fetchCompetencies(): Promise<void> {
|
||||
let promise;
|
||||
let promise: Promise<AddonCompetencyDataForPlanPageResult | AddonCompetencyDataForCourseCompetenciesPageResult>;
|
||||
|
||||
if (this.planId) {
|
||||
promise = this.competencyProvider.getLearningPlan(this.planId);
|
||||
|
@ -83,13 +86,16 @@ export class AddonCompetencyCompetenciesPage {
|
|||
}
|
||||
|
||||
return promise.then((response) => {
|
||||
if (response.competencycount <= 0) {
|
||||
return Promise.reject(this.translate.instant('addon.competency.errornocompetenciesfound'));
|
||||
}
|
||||
|
||||
if (this.planId) {
|
||||
this.title = response.plan.name;
|
||||
this.userId = response.plan.userid;
|
||||
const resp = <AddonCompetencyDataForPlanPageResult> response;
|
||||
|
||||
if (resp.competencycount <= 0) {
|
||||
return Promise.reject(this.translate.instant('addon.competency.errornocompetenciesfound'));
|
||||
}
|
||||
|
||||
this.title = resp.plan.name;
|
||||
this.userId = resp.plan.userid;
|
||||
} else {
|
||||
this.title = this.translate.instant('addon.competency.coursecompetencies');
|
||||
}
|
||||
|
|
|
@ -51,22 +51,22 @@
|
|||
<core-format-text [text]="activity.name"></core-format-text>
|
||||
</a>
|
||||
</ion-item>
|
||||
<ion-item text-wrap *ngIf="competency.usercompetency.status">
|
||||
<ion-item text-wrap *ngIf="userCompetency.status">
|
||||
<strong>{{ 'addon.competency.reviewstatus' | translate }}</strong>
|
||||
{{ competency.usercompetency.statusname }}
|
||||
{{ userCompetency.statusname }}
|
||||
</ion-item>
|
||||
<ion-item text-wrap>
|
||||
<strong>{{ 'addon.competency.proficient' | translate }}</strong>
|
||||
<ion-badge color="success" *ngIf="competency.usercompetency.proficiency">
|
||||
<ion-badge color="success" *ngIf="userCompetency.proficiency">
|
||||
{{ 'core.yes' | translate }}
|
||||
</ion-badge>
|
||||
<ion-badge color="danger" *ngIf="!competency.usercompetency.proficiency">
|
||||
<ion-badge color="danger" *ngIf="!userCompetency.proficiency">
|
||||
{{ 'core.no' | translate }}
|
||||
</ion-badge>
|
||||
</ion-item>
|
||||
<ion-item text-wrap>
|
||||
<strong>{{ 'addon.competency.rating' | translate }}</strong>
|
||||
<ion-badge color="dark">{{ competency.usercompetency.gradename }}</ion-badge>
|
||||
<ion-badge color="dark">{{ userCompetency.gradename }}</ion-badge>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
|
||||
|
|
|
@ -18,8 +18,14 @@ import { TranslateService } from '@ngx-translate/core';
|
|||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||
import { AddonCompetencyProvider } from '../../providers/competency';
|
||||
import {
|
||||
AddonCompetencyProvider, AddonCompetencyUserCompetencySummary, AddonCompetencyUserCompetencySummaryInPlan,
|
||||
AddonCompetencyUserCompetencySummaryInCourse, AddonCompetencyUserCompetencyPlan,
|
||||
AddonCompetencyUserCompetency, AddonCompetencyUserCompetencyCourse
|
||||
} from '../../providers/competency';
|
||||
import { AddonCompetencyHelperProvider } from '../../providers/helper';
|
||||
import { CoreUserSummary } from '@core/user/providers/user';
|
||||
import { CoreCourseModuleSummary } from '@core/course/providers/course';
|
||||
|
||||
/**
|
||||
* Page that displays a learning plan.
|
||||
|
@ -36,9 +42,10 @@ export class AddonCompetencyCompetencyPage {
|
|||
courseId: number;
|
||||
userId: number;
|
||||
planStatus: number;
|
||||
coursemodules: any;
|
||||
user: any;
|
||||
competency: any;
|
||||
coursemodules: CoreCourseModuleSummary[];
|
||||
user: CoreUserSummary;
|
||||
competency: AddonCompetencyUserCompetencySummary;
|
||||
userCompetency: AddonCompetencyUserCompetencyPlan | AddonCompetencyUserCompetency | AddonCompetencyUserCompetencyCourse;
|
||||
|
||||
constructor(private navCtrl: NavController, navParams: NavParams, private translate: TranslateService,
|
||||
private sitesProvider: CoreSitesProvider, private domUtils: CoreDomUtilsProvider,
|
||||
|
@ -79,7 +86,8 @@ export class AddonCompetencyCompetencyPage {
|
|||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected fetchCompetency(): Promise<void> {
|
||||
let promise;
|
||||
let promise: Promise<AddonCompetencyUserCompetencySummaryInPlan | AddonCompetencyUserCompetencySummaryInCourse>;
|
||||
|
||||
if (this.planId) {
|
||||
this.planStatus = null;
|
||||
promise = this.competencyProvider.getCompetencyInPlan(this.planId, this.competencyId);
|
||||
|
@ -90,23 +98,21 @@ export class AddonCompetencyCompetencyPage {
|
|||
}
|
||||
|
||||
return promise.then((competency) => {
|
||||
competency.usercompetencysummary.usercompetency = competency.usercompetencysummary.usercompetencyplan ||
|
||||
competency.usercompetencysummary.usercompetency;
|
||||
|
||||
this.competency = competency.usercompetencysummary;
|
||||
this.userCompetency = this.competency.usercompetencyplan || this.competency.usercompetency;
|
||||
|
||||
if (this.planId) {
|
||||
this.planStatus = competency.plan.status;
|
||||
this.planStatus = (<AddonCompetencyUserCompetencySummaryInPlan> competency).plan.status;
|
||||
this.competency.usercompetency.statusname =
|
||||
this.competencyHelperProvider.getCompetencyStatusName(this.competency.usercompetency.status);
|
||||
} else {
|
||||
this.competency.usercompetency = this.competency.usercompetencycourse;
|
||||
this.coursemodules = competency.coursemodules;
|
||||
this.userCompetency = this.competency.usercompetencycourse;
|
||||
this.coursemodules = (<AddonCompetencyUserCompetencySummaryInCourse> competency).coursemodules;
|
||||
}
|
||||
|
||||
if (this.competency.user.id != this.sitesProvider.getCurrentSiteUserId()) {
|
||||
this.competency.user.profileimageurl = this.competency.user.profileimageurl || true;
|
||||
|
||||
// Get the user profile image from the returned object.
|
||||
// Get the user profile from the returned object.
|
||||
this.user = this.competency.user;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ import { Component, Optional } from '@angular/core';
|
|||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||
import { AddonCompetencyProvider } from '../../providers/competency';
|
||||
import { AddonCompetencyProvider, AddonCompetencySummary } from '../../providers/competency';
|
||||
|
||||
/**
|
||||
* Page that displays a learning plan.
|
||||
|
@ -29,7 +29,7 @@ import { AddonCompetencyProvider } from '../../providers/competency';
|
|||
export class AddonCompetencyCompetencySummaryPage {
|
||||
competencyLoaded = false;
|
||||
competencyId: number;
|
||||
competency: any;
|
||||
competency: AddonCompetencySummary;
|
||||
|
||||
constructor(private navCtrl: NavController, navParams: NavParams, private domUtils: CoreDomUtilsProvider,
|
||||
@Optional() private svComponent: CoreSplitViewComponent, private competencyProvider: AddonCompetencyProvider) {
|
||||
|
@ -41,8 +41,7 @@ export class AddonCompetencyCompetencySummaryPage {
|
|||
*/
|
||||
ionViewDidLoad(): void {
|
||||
this.fetchCompetency().then(() => {
|
||||
const name = this.competency.competency && this.competency.competency.competency &&
|
||||
this.competency.competency.competency.shortname;
|
||||
const name = this.competency.competency && this.competency.competency.shortname;
|
||||
|
||||
this.competencyProvider.logCompetencyView(this.competencyId, name).catch(() => {
|
||||
// Ignore errors.
|
||||
|
|
|
@ -46,7 +46,8 @@
|
|||
</ion-item>
|
||||
<a ion-item text-wrap *ngFor="let competency of plan.competencies" (click)="openCompetency(competency.competency.id)" [title]="competency.competency.shortname">
|
||||
<h2>{{competency.competency.shortname}} <em>{{competency.competency.idnumber}}</em></h2>
|
||||
<ion-badge item-end [color]="competency.usercompetency.proficiency ? 'success' : 'danger'">{{ competency.usercompetency.gradename }}</ion-badge>
|
||||
<ion-badge *ngIf="competency.usercompetencyplan" item-end [color]="competency.usercompetencyplan.proficiency ? 'success' : 'danger'">{{ competency.usercompetencyplan.gradename }}</ion-badge>
|
||||
<ion-badge *ngIf="!competency.usercompetencyplan" item-end [color]="competency.usercompetency.proficiency ? 'success' : 'danger'">{{ competency.usercompetency.gradename }}</ion-badge>
|
||||
</a>
|
||||
</ion-list>
|
||||
</ion-card>
|
||||
|
|
|
@ -17,7 +17,7 @@ import { IonicPage, NavController, NavParams } from 'ionic-angular';
|
|||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||
import { AddonCompetencyProvider } from '../../providers/competency';
|
||||
import { AddonCompetencyProvider, AddonCompetencyDataForPlanPageResult } from '../../providers/competency';
|
||||
import { AddonCompetencyHelperProvider } from '../../providers/helper';
|
||||
|
||||
/**
|
||||
|
@ -31,7 +31,7 @@ import { AddonCompetencyHelperProvider } from '../../providers/helper';
|
|||
export class AddonCompetencyPlanPage {
|
||||
protected planId: number;
|
||||
planLoaded = false;
|
||||
plan: any;
|
||||
plan: AddonCompetencyDataForPlanPageResult;
|
||||
user: any;
|
||||
|
||||
constructor(private navCtrl: NavController, navParams: NavParams, private appProvider: CoreAppProvider,
|
||||
|
@ -62,9 +62,6 @@ export class AddonCompetencyPlanPage {
|
|||
this.user = user;
|
||||
});
|
||||
|
||||
plan.competencies.forEach((competency) => {
|
||||
competency.usercompetency = competency.usercompetencyplan || competency.usercompetency;
|
||||
});
|
||||
this.plan = plan;
|
||||
}).catch((message) => {
|
||||
this.domUtils.showErrorModalDefault(message, 'Error getting learning plan data.');
|
||||
|
|
|
@ -16,7 +16,7 @@ import { Component, ViewChild } from '@angular/core';
|
|||
import { IonicPage, NavParams } from 'ionic-angular';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||
import { AddonCompetencyProvider } from '../../providers/competency';
|
||||
import { AddonCompetencyProvider, AddonCompetencyPlan } from '../../providers/competency';
|
||||
import { AddonCompetencyHelperProvider } from '../../providers/helper';
|
||||
|
||||
/**
|
||||
|
@ -33,7 +33,7 @@ export class AddonCompetencyPlanListPage {
|
|||
protected userId: number;
|
||||
protected planId: number;
|
||||
plansLoaded = false;
|
||||
plans = [];
|
||||
plans: AddonCompetencyPlan[] = [];
|
||||
|
||||
constructor(navParams: NavParams, private domUtils: CoreDomUtilsProvider, private competencyProvider: AddonCompetencyProvider,
|
||||
private competencyHelperProvider: AddonCompetencyHelperProvider) {
|
||||
|
@ -66,7 +66,7 @@ export class AddonCompetencyPlanListPage {
|
|||
*/
|
||||
protected fetchLearningPlans(): Promise<void> {
|
||||
return this.competencyProvider.getLearningPlans(this.userId).then((plans) => {
|
||||
plans.forEach((plan) => {
|
||||
plans.forEach((plan: AddonCompetencyPlanFormatted) => {
|
||||
plan.statusname = this.competencyHelperProvider.getPlanStatusName(plan.status);
|
||||
switch (plan.status) {
|
||||
case AddonCompetencyProvider.STATUS_ACTIVE:
|
||||
|
@ -109,3 +109,10 @@ export class AddonCompetencyPlanListPage {
|
|||
this.splitviewCtrl.push('AddonCompetencyPlanPage', { planId });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Competency plan with some calculated data.
|
||||
*/
|
||||
type AddonCompetencyPlanFormatted = AddonCompetencyPlan & {
|
||||
statuscolor?: string; // Calculated in the app. Color of the plan's status.
|
||||
};
|
||||
|
|
|
@ -17,6 +17,9 @@ import { CoreLoggerProvider } from '@providers/logger';
|
|||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications';
|
||||
import { CoreSite } from '@classes/site';
|
||||
import { CoreCommentsArea } from '@core/comments/providers/comments';
|
||||
import { CoreUserSummary } from '@core/user/providers/user';
|
||||
import { CoreCourseSummary, CoreCourseModuleSummary } from '@core/course/providers/course';
|
||||
|
||||
/**
|
||||
* Service to handle caompetency learning plans.
|
||||
|
@ -147,7 +150,7 @@ export class AddonCompetencyProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise to be resolved when the plans are retrieved.
|
||||
*/
|
||||
getLearningPlans(userId?: number, siteId?: string): Promise<any> {
|
||||
getLearningPlans(userId?: number, siteId?: string): Promise<AddonCompetencyPlan[]> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
userId = userId || site.getUserId();
|
||||
|
||||
|
@ -161,7 +164,9 @@ export class AddonCompetencyProvider {
|
|||
updateFrequency: CoreSite.FREQUENCY_RARELY
|
||||
};
|
||||
|
||||
return site.read('tool_lp_data_for_plans_page', params, preSets).then((response) => {
|
||||
return site.read('tool_lp_data_for_plans_page', params, preSets)
|
||||
.then((response: AddonCompetencyDataForPlansPageResult): any => {
|
||||
|
||||
if (response.plans) {
|
||||
return response.plans;
|
||||
}
|
||||
|
@ -176,9 +181,9 @@ export class AddonCompetencyProvider {
|
|||
*
|
||||
* @param planId ID of the plan.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise to be resolved when the plans are retrieved.
|
||||
* @return Promise to be resolved when the plan is retrieved.
|
||||
*/
|
||||
getLearningPlan(planId: number, siteId?: string): Promise<any> {
|
||||
getLearningPlan(planId: number, siteId?: string): Promise<AddonCompetencyDataForPlanPageResult> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
||||
this.logger.debug('Get plan ' + planId);
|
||||
|
@ -191,7 +196,9 @@ export class AddonCompetencyProvider {
|
|||
updateFrequency: CoreSite.FREQUENCY_RARELY
|
||||
};
|
||||
|
||||
return site.read('tool_lp_data_for_plan_page', params, preSets).then((response) => {
|
||||
return site.read('tool_lp_data_for_plan_page', params, preSets)
|
||||
.then((response: AddonCompetencyDataForPlanPageResult): any => {
|
||||
|
||||
if (response.plan) {
|
||||
return response;
|
||||
}
|
||||
|
@ -207,9 +214,11 @@ export class AddonCompetencyProvider {
|
|||
* @param planId ID of the plan.
|
||||
* @param competencyId ID of the competency.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise to be resolved when the plans are retrieved.
|
||||
* @return Promise to be resolved when the competency is retrieved.
|
||||
*/
|
||||
getCompetencyInPlan(planId: number, competencyId: number, siteId?: string): Promise<any> {
|
||||
getCompetencyInPlan(planId: number, competencyId: number, siteId?: string)
|
||||
: Promise<AddonCompetencyUserCompetencySummaryInPlan> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
||||
this.logger.debug('Get competency ' + competencyId + ' in plan ' + planId);
|
||||
|
@ -223,7 +232,9 @@ export class AddonCompetencyProvider {
|
|||
updateFrequency: CoreSite.FREQUENCY_SOMETIMES
|
||||
};
|
||||
|
||||
return site.read('tool_lp_data_for_user_competency_summary_in_plan', params, preSets).then((response) => {
|
||||
return site.read('tool_lp_data_for_user_competency_summary_in_plan', params, preSets)
|
||||
.then((response: AddonCompetencyUserCompetencySummaryInPlan): any => {
|
||||
|
||||
if (response.usercompetencysummary) {
|
||||
return response;
|
||||
}
|
||||
|
@ -241,10 +252,10 @@ export class AddonCompetencyProvider {
|
|||
* @param userId ID of the user. If not defined, current user.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @param ignoreCache True if it should ignore cached data (it will always fail in offline or server down).
|
||||
* @return Promise to be resolved when the plans are retrieved.
|
||||
* @return Promise to be resolved when the competency is retrieved.
|
||||
*/
|
||||
getCompetencyInCourse(courseId: number, competencyId: number, userId?: number, siteId?: string, ignoreCache?: boolean)
|
||||
: Promise<any> {
|
||||
: Promise<AddonCompetencyUserCompetencySummaryInCourse> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
userId = userId || site.getUserId();
|
||||
|
@ -266,7 +277,9 @@ export class AddonCompetencyProvider {
|
|||
preSets.emergencyCache = false;
|
||||
}
|
||||
|
||||
return site.read('tool_lp_data_for_user_competency_summary_in_course', params, preSets).then((response) => {
|
||||
return site.read('tool_lp_data_for_user_competency_summary_in_course', params, preSets)
|
||||
.then((response: AddonCompetencyUserCompetencySummaryInCourse): any => {
|
||||
|
||||
if (response.usercompetencysummary) {
|
||||
return response;
|
||||
}
|
||||
|
@ -283,9 +296,11 @@ export class AddonCompetencyProvider {
|
|||
* @param userId ID of the user. If not defined, current user.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @param ignoreCache True if it should ignore cached data (it will always fail in offline or server down).
|
||||
* @return Promise to be resolved when the plans are retrieved.
|
||||
* @return Promise to be resolved when the competency summary is retrieved.
|
||||
*/
|
||||
getCompetencySummary(competencyId: number, userId?: number, siteId?: string, ignoreCache?: boolean): Promise<any> {
|
||||
getCompetencySummary(competencyId: number, userId?: number, siteId?: string, ignoreCache?: boolean)
|
||||
: Promise<AddonCompetencySummary> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
userId = userId || site.getUserId();
|
||||
|
||||
|
@ -305,7 +320,9 @@ export class AddonCompetencyProvider {
|
|||
preSets.emergencyCache = false;
|
||||
}
|
||||
|
||||
return site.read('tool_lp_data_for_user_competency_summary', params, preSets).then((response) => {
|
||||
return site.read('tool_lp_data_for_user_competency_summary', params, preSets)
|
||||
.then((response: AddonCompetencyUserCompetencySummary): any => {
|
||||
|
||||
if (response.competency) {
|
||||
return response.competency;
|
||||
}
|
||||
|
@ -324,7 +341,9 @@ export class AddonCompetencyProvider {
|
|||
* @param ignoreCache True if it should ignore cached data (it will always fail in offline or server down).
|
||||
* @return Promise to be resolved when the course competencies are retrieved.
|
||||
*/
|
||||
getCourseCompetencies(courseId: number, userId?: number, siteId?: string, ignoreCache?: boolean): Promise<any> {
|
||||
getCourseCompetencies(courseId: number, userId?: number, siteId?: string, ignoreCache?: boolean)
|
||||
: Promise<AddonCompetencyDataForCourseCompetenciesPageResult> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
||||
this.logger.debug('Get course competencies for course ' + courseId);
|
||||
|
@ -342,7 +361,9 @@ export class AddonCompetencyProvider {
|
|||
preSets.emergencyCache = false;
|
||||
}
|
||||
|
||||
return site.read('tool_lp_data_for_course_competencies_page', params, preSets).then((response) => {
|
||||
return site.read('tool_lp_data_for_course_competencies_page', params, preSets)
|
||||
.then((response: AddonCompetencyDataForCourseCompetenciesPageResult): any => {
|
||||
|
||||
if (response.competencies) {
|
||||
return response;
|
||||
}
|
||||
|
@ -356,11 +377,13 @@ export class AddonCompetencyProvider {
|
|||
return response;
|
||||
}
|
||||
|
||||
const promises = response.competencies.map((competency) =>
|
||||
let promises: Promise<AddonCompetencyUserCompetencySummaryInCourse>[];
|
||||
|
||||
promises = response.competencies.map((competency) =>
|
||||
this.getCompetencyInCourse(courseId, competency.competency.id, userId, siteId)
|
||||
);
|
||||
|
||||
return Promise.all(promises).then((responses: any[]) => {
|
||||
return Promise.all(promises).then((responses: AddonCompetencyUserCompetencySummaryInCourse[]) => {
|
||||
responses.forEach((resp, index) => {
|
||||
response.competencies[index].usercompetencycourse = resp.usercompetencysummary.usercompetencycourse;
|
||||
});
|
||||
|
@ -486,7 +509,7 @@ export class AddonCompetencyProvider {
|
|||
* @return Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logCompetencyInPlanView(planId: number, competencyId: number, planStatus: number, name?: string, userId?: number,
|
||||
siteId?: string): Promise<any> {
|
||||
siteId?: string): Promise<void> {
|
||||
if (planId && competencyId) {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
@ -509,7 +532,11 @@ export class AddonCompetencyProvider {
|
|||
userid: userId
|
||||
}, siteId);
|
||||
|
||||
return site.write(wsName, params, preSets);
|
||||
return site.write(wsName, params, preSets).then((success: boolean) => {
|
||||
if (!success) {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -527,7 +554,7 @@ export class AddonCompetencyProvider {
|
|||
* @return Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logCompetencyInCourseView(courseId: number, competencyId: number, name?: string, userId?: number, siteId?: string)
|
||||
: Promise<any> {
|
||||
: Promise<void> {
|
||||
|
||||
if (courseId && competencyId) {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
@ -548,7 +575,11 @@ export class AddonCompetencyProvider {
|
|||
userid: userId
|
||||
}, siteId);
|
||||
|
||||
return site.write(wsName, params, preSets);
|
||||
return site.write(wsName, params, preSets).then((success: boolean) => {
|
||||
if (!success) {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -563,7 +594,7 @@ export class AddonCompetencyProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logCompetencyView(competencyId: number, name?: string, siteId?: string): Promise<any> {
|
||||
logCompetencyView(competencyId: number, name?: string, siteId?: string): Promise<void> {
|
||||
if (competencyId) {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const params = {
|
||||
|
@ -576,10 +607,401 @@ export class AddonCompetencyProvider {
|
|||
|
||||
this.pushNotificationsProvider.logViewEvent(competencyId, name, 'competency', wsName, {}, siteId);
|
||||
|
||||
return site.write('core_competency_competency_viewed', params, preSets);
|
||||
return site.write(wsName, params, preSets).then((success: boolean) => {
|
||||
if (!success) {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data returned by competency's plan_exporter.
|
||||
*/
|
||||
export type AddonCompetencyPlan = {
|
||||
name: string; // Name.
|
||||
description: string; // Description.
|
||||
descriptionformat: number; // Description format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||
userid: number; // Userid.
|
||||
templateid: number; // Templateid.
|
||||
origtemplateid: number; // Origtemplateid.
|
||||
status: number; // Status.
|
||||
duedate: number; // Duedate.
|
||||
reviewerid: number; // Reviewerid.
|
||||
id: number; // Id.
|
||||
timecreated: number; // Timecreated.
|
||||
timemodified: number; // Timemodified.
|
||||
usermodified: number; // Usermodified.
|
||||
statusname: string; // Statusname.
|
||||
isbasedontemplate: boolean; // Isbasedontemplate.
|
||||
canmanage: boolean; // Canmanage.
|
||||
canrequestreview: boolean; // Canrequestreview.
|
||||
canreview: boolean; // Canreview.
|
||||
canbeedited: boolean; // Canbeedited.
|
||||
isactive: boolean; // Isactive.
|
||||
isdraft: boolean; // Isdraft.
|
||||
iscompleted: boolean; // Iscompleted.
|
||||
isinreview: boolean; // Isinreview.
|
||||
iswaitingforreview: boolean; // Iswaitingforreview.
|
||||
isreopenallowed: boolean; // Isreopenallowed.
|
||||
iscompleteallowed: boolean; // Iscompleteallowed.
|
||||
isunlinkallowed: boolean; // Isunlinkallowed.
|
||||
isrequestreviewallowed: boolean; // Isrequestreviewallowed.
|
||||
iscancelreviewrequestallowed: boolean; // Iscancelreviewrequestallowed.
|
||||
isstartreviewallowed: boolean; // Isstartreviewallowed.
|
||||
isstopreviewallowed: boolean; // Isstopreviewallowed.
|
||||
isapproveallowed: boolean; // Isapproveallowed.
|
||||
isunapproveallowed: boolean; // Isunapproveallowed.
|
||||
duedateformatted: string; // Duedateformatted.
|
||||
commentarea: CoreCommentsArea;
|
||||
reviewer?: CoreUserSummary;
|
||||
template?: AddonCompetencyTemplate;
|
||||
url: string; // Url.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's template_exporter.
|
||||
*/
|
||||
export type AddonCompetencyTemplate = {
|
||||
shortname: string; // Shortname.
|
||||
description: string; // Description.
|
||||
descriptionformat: number; // Description format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||
duedate: number; // Duedate.
|
||||
visible: boolean; // Visible.
|
||||
contextid: number; // Contextid.
|
||||
id: number; // Id.
|
||||
timecreated: number; // Timecreated.
|
||||
timemodified: number; // Timemodified.
|
||||
usermodified: number; // Usermodified.
|
||||
duedateformatted: string; // Duedateformatted.
|
||||
cohortscount: number; // Cohortscount.
|
||||
planscount: number; // Planscount.
|
||||
canmanage: boolean; // Canmanage.
|
||||
canread: boolean; // Canread.
|
||||
contextname: string; // Contextname.
|
||||
contextnamenoprefix: string; // Contextnamenoprefix.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's competency_exporter.
|
||||
*/
|
||||
export type AddonCompetencyCompetency = {
|
||||
shortname: string; // Shortname.
|
||||
idnumber: string; // Idnumber.
|
||||
description: string; // Description.
|
||||
descriptionformat: number; // Description format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||
sortorder: number; // Sortorder.
|
||||
parentid: number; // Parentid.
|
||||
path: string; // Path.
|
||||
ruleoutcome: number; // Ruleoutcome.
|
||||
ruletype: string; // Ruletype.
|
||||
ruleconfig: string; // Ruleconfig.
|
||||
scaleid: number; // Scaleid.
|
||||
scaleconfiguration: string; // Scaleconfiguration.
|
||||
competencyframeworkid: number; // Competencyframeworkid.
|
||||
id: number; // Id.
|
||||
timecreated: number; // Timecreated.
|
||||
timemodified: number; // Timemodified.
|
||||
usermodified: number; // Usermodified.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's competency_path_exporter.
|
||||
*/
|
||||
export type AddonCompetencyPath = {
|
||||
ancestors: AddonCompetencyPathNode[]; // Ancestors.
|
||||
framework: AddonCompetencyPathNode;
|
||||
pluginbaseurl: string; // Pluginbaseurl.
|
||||
pagecontextid: number; // Pagecontextid.
|
||||
showlinks: boolean; // Showlinks.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's path_node_exporter.
|
||||
*/
|
||||
export type AddonCompetencyPathNode = {
|
||||
id: number; // Id.
|
||||
name: string; // Name.
|
||||
first: boolean; // First.
|
||||
last: boolean; // Last.
|
||||
position: number; // Position.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's user_competency_exporter.
|
||||
*/
|
||||
export type AddonCompetencyUserCompetency = {
|
||||
userid: number; // Userid.
|
||||
competencyid: number; // Competencyid.
|
||||
status: number; // Status.
|
||||
reviewerid: number; // Reviewerid.
|
||||
proficiency: boolean; // Proficiency.
|
||||
grade: number; // Grade.
|
||||
id: number; // Id.
|
||||
timecreated: number; // Timecreated.
|
||||
timemodified: number; // Timemodified.
|
||||
usermodified: number; // Usermodified.
|
||||
canrequestreview: boolean; // Canrequestreview.
|
||||
canreview: boolean; // Canreview.
|
||||
gradename: string; // Gradename.
|
||||
isrequestreviewallowed: boolean; // Isrequestreviewallowed.
|
||||
iscancelreviewrequestallowed: boolean; // Iscancelreviewrequestallowed.
|
||||
isstartreviewallowed: boolean; // Isstartreviewallowed.
|
||||
isstopreviewallowed: boolean; // Isstopreviewallowed.
|
||||
isstatusidle: boolean; // Isstatusidle.
|
||||
isstatusinreview: boolean; // Isstatusinreview.
|
||||
isstatuswaitingforreview: boolean; // Isstatuswaitingforreview.
|
||||
proficiencyname: string; // Proficiencyname.
|
||||
reviewer?: CoreUserSummary;
|
||||
statusname: string; // Statusname.
|
||||
url: string; // Url.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's user_competency_plan_exporter.
|
||||
*/
|
||||
export type AddonCompetencyUserCompetencyPlan = {
|
||||
userid: number; // Userid.
|
||||
competencyid: number; // Competencyid.
|
||||
proficiency: boolean; // Proficiency.
|
||||
grade: number; // Grade.
|
||||
planid: number; // Planid.
|
||||
sortorder: number; // Sortorder.
|
||||
id: number; // Id.
|
||||
timecreated: number; // Timecreated.
|
||||
timemodified: number; // Timemodified.
|
||||
usermodified: number; // Usermodified.
|
||||
gradename: string; // Gradename.
|
||||
proficiencyname: string; // Proficiencyname.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's user_competency_summary_in_plan_exporter.
|
||||
*/
|
||||
export type AddonCompetencyUserCompetencySummaryInPlan = {
|
||||
usercompetencysummary: AddonCompetencyUserCompetencySummary;
|
||||
plan: AddonCompetencyPlan;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's user_competency_summary_exporter.
|
||||
*/
|
||||
export type AddonCompetencyUserCompetencySummary = {
|
||||
showrelatedcompetencies: boolean; // Showrelatedcompetencies.
|
||||
cangrade: boolean; // Cangrade.
|
||||
competency: AddonCompetencySummary;
|
||||
user: CoreUserSummary;
|
||||
usercompetency?: AddonCompetencyUserCompetency;
|
||||
usercompetencyplan?: AddonCompetencyUserCompetencyPlan;
|
||||
usercompetencycourse?: AddonCompetencyUserCompetencyCourse;
|
||||
evidence: AddonCompetencyEvidence[]; // Evidence.
|
||||
commentarea?: CoreCommentsArea;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's competency_summary_exporter.
|
||||
*/
|
||||
export type AddonCompetencySummary = {
|
||||
linkedcourses: CoreCourseSummary; // Linkedcourses.
|
||||
relatedcompetencies: AddonCompetencyCompetency[]; // Relatedcompetencies.
|
||||
competency: AddonCompetencyCompetency;
|
||||
framework: AddonCompetencyFramework;
|
||||
hascourses: boolean; // Hascourses.
|
||||
hasrelatedcompetencies: boolean; // Hasrelatedcompetencies.
|
||||
scaleid: number; // Scaleid.
|
||||
scaleconfiguration: string; // Scaleconfiguration.
|
||||
taxonomyterm: string; // Taxonomyterm.
|
||||
comppath: AddonCompetencyPath;
|
||||
pluginbaseurl: string; // Pluginbaseurl.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's competency_framework_exporter.
|
||||
*/
|
||||
export type AddonCompetencyFramework = {
|
||||
shortname: string; // Shortname.
|
||||
idnumber: string; // Idnumber.
|
||||
description: string; // Description.
|
||||
descriptionformat: number; // Description format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||
visible: boolean; // Visible.
|
||||
scaleid: number; // Scaleid.
|
||||
scaleconfiguration: string; // Scaleconfiguration.
|
||||
contextid: number; // Contextid.
|
||||
taxonomies: string; // Taxonomies.
|
||||
id: number; // Id.
|
||||
timecreated: number; // Timecreated.
|
||||
timemodified: number; // Timemodified.
|
||||
usermodified: number; // Usermodified.
|
||||
canmanage: boolean; // Canmanage.
|
||||
competenciescount: number; // Competenciescount.
|
||||
contextname: string; // Contextname.
|
||||
contextnamenoprefix: string; // Contextnamenoprefix.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's user_competency_course_exporter.
|
||||
*/
|
||||
export type AddonCompetencyUserCompetencyCourse = {
|
||||
userid: number; // Userid.
|
||||
courseid: number; // Courseid.
|
||||
competencyid: number; // Competencyid.
|
||||
proficiency: boolean; // Proficiency.
|
||||
grade: number; // Grade.
|
||||
id: number; // Id.
|
||||
timecreated: number; // Timecreated.
|
||||
timemodified: number; // Timemodified.
|
||||
usermodified: number; // Usermodified.
|
||||
gradename: string; // Gradename.
|
||||
proficiencyname: string; // Proficiencyname.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's evidence_exporter.
|
||||
*/
|
||||
export type AddonCompetencyEvidence = {
|
||||
usercompetencyid: number; // Usercompetencyid.
|
||||
contextid: number; // Contextid.
|
||||
action: number; // Action.
|
||||
actionuserid: number; // Actionuserid.
|
||||
descidentifier: string; // Descidentifier.
|
||||
desccomponent: string; // Desccomponent.
|
||||
desca: string; // Desca.
|
||||
url: string; // Url.
|
||||
grade: number; // Grade.
|
||||
note: string; // Note.
|
||||
id: number; // Id.
|
||||
timecreated: number; // Timecreated.
|
||||
timemodified: number; // Timemodified.
|
||||
usermodified: number; // Usermodified.
|
||||
actionuser?: CoreUserSummary;
|
||||
description: string; // Description.
|
||||
gradename: string; // Gradename.
|
||||
userdate: string; // Userdate.
|
||||
candelete: boolean; // Candelete.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's user_competency_summary_in_course_exporter.
|
||||
*/
|
||||
export type AddonCompetencyUserCompetencySummaryInCourse = {
|
||||
usercompetencysummary: AddonCompetencyUserCompetencySummary;
|
||||
course: CoreCourseSummary;
|
||||
coursemodules: CoreCourseModuleSummary[]; // Coursemodules.
|
||||
plans: AddonCompetencyPlan[]; // Plans.
|
||||
pluginbaseurl: string; // Pluginbaseurl.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's course_competency_settings_exporter.
|
||||
*/
|
||||
export type AddonCompetencyCourseCompetencySettings = {
|
||||
courseid: number; // Courseid.
|
||||
pushratingstouserplans: boolean; // Pushratingstouserplans.
|
||||
id: number; // Id.
|
||||
timecreated: number; // Timecreated.
|
||||
timemodified: number; // Timemodified.
|
||||
usermodified: number; // Usermodified.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's course_competency_statistics_exporter.
|
||||
*/
|
||||
export type AddonCompetencyCourseCompetencyStatistics = {
|
||||
competencycount: number; // Competencycount.
|
||||
proficientcompetencycount: number; // Proficientcompetencycount.
|
||||
proficientcompetencypercentage: number; // Proficientcompetencypercentage.
|
||||
proficientcompetencypercentageformatted: string; // Proficientcompetencypercentageformatted.
|
||||
leastproficient: AddonCompetencyCompetency[]; // Leastproficient.
|
||||
leastproficientcount: number; // Leastproficientcount.
|
||||
canbegradedincourse: boolean; // Canbegradedincourse.
|
||||
canmanagecoursecompetencies: boolean; // Canmanagecoursecompetencies.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by competency's course_competency_exporter.
|
||||
*/
|
||||
export type AddonCompetencyCourseCompetency = {
|
||||
courseid: number; // Courseid.
|
||||
competencyid: number; // Competencyid.
|
||||
sortorder: number; // Sortorder.
|
||||
ruleoutcome: number; // Ruleoutcome.
|
||||
id: number; // Id.
|
||||
timecreated: number; // Timecreated.
|
||||
timemodified: number; // Timemodified.
|
||||
usermodified: number; // Usermodified.
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS tool_lp_data_for_plans_page.
|
||||
*/
|
||||
export type AddonCompetencyDataForPlansPageResult = {
|
||||
userid: number; // The learning plan user id.
|
||||
plans: AddonCompetencyPlan[];
|
||||
pluginbaseurl: string; // Url to the tool_lp plugin folder on this Moodle site.
|
||||
navigation: string[];
|
||||
canreaduserevidence: boolean; // Can the current user view the user's evidence.
|
||||
canmanageuserplans: boolean; // Can the current user manage the user's plans.
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS tool_lp_data_for_plan_page.
|
||||
*/
|
||||
export type AddonCompetencyDataForPlanPageResult = {
|
||||
plan: AddonCompetencyPlan;
|
||||
contextid: number; // Context ID.
|
||||
pluginbaseurl: string; // Plugin base URL.
|
||||
competencies: AddonCompetencyDataForPlanPageCompetency[];
|
||||
competencycount: number; // Count of competencies.
|
||||
proficientcompetencycount: number; // Count of proficientcompetencies.
|
||||
proficientcompetencypercentage: number; // Percentage of competencies proficient.
|
||||
proficientcompetencypercentageformatted: string; // Displayable percentage.
|
||||
};
|
||||
|
||||
/**
|
||||
* Competency data returned by tool_lp_data_for_plan_page.
|
||||
*/
|
||||
export type AddonCompetencyDataForPlanPageCompetency = {
|
||||
competency: AddonCompetencyCompetency;
|
||||
comppath: AddonCompetencyPath;
|
||||
usercompetency?: AddonCompetencyUserCompetency;
|
||||
usercompetencyplan?: AddonCompetencyUserCompetencyPlan;
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS tool_lp_data_for_course_competencies_page.
|
||||
*/
|
||||
export type AddonCompetencyDataForCourseCompetenciesPageResult = {
|
||||
courseid: number; // The current course id.
|
||||
pagecontextid: number; // The current page context ID.
|
||||
gradableuserid?: number; // Current user id, if the user is a gradable user.
|
||||
canmanagecompetencyframeworks: boolean; // User can manage competency frameworks.
|
||||
canmanagecoursecompetencies: boolean; // User can manage linked course competencies.
|
||||
canconfigurecoursecompetencies: boolean; // User can configure course competency settings.
|
||||
cangradecompetencies: boolean; // User can grade competencies.
|
||||
settings: AddonCompetencyCourseCompetencySettings;
|
||||
statistics: AddonCompetencyCourseCompetencyStatistics;
|
||||
competencies: AddonCompetencyDataForCourseCompetenciesPageCompetency[];
|
||||
manageurl: string; // Url to the manage competencies page.
|
||||
pluginbaseurl: string; // Url to the course competencies page.
|
||||
};
|
||||
|
||||
/**
|
||||
* Competency data returned by tool_lp_data_for_course_competencies_page.
|
||||
*/
|
||||
export type AddonCompetencyDataForCourseCompetenciesPageCompetency = {
|
||||
competency: AddonCompetencyCompetency;
|
||||
coursecompetency: AddonCompetencyCourseCompetency;
|
||||
coursemodules: CoreCourseModuleSummary[];
|
||||
usercompetencycourse?: AddonCompetencyUserCompetencyCourse;
|
||||
ruleoutcomeoptions: {
|
||||
value: number; // The option value.
|
||||
text: string; // The name of the option.
|
||||
selected: boolean; // If this is the currently selected option.
|
||||
}[];
|
||||
comppath: AddonCompetencyPath;
|
||||
plans: AddonCompetencyPlan[];
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<ion-card *ngIf="completion && tracked">
|
||||
<ion-item text-wrap>
|
||||
<h2>{{ 'addon.coursecompletion.status' | translate }}</h2>
|
||||
<p>{{ completion.statusText | translate }}</p>
|
||||
<p>{{ statusText | translate }}</p>
|
||||
</ion-item>
|
||||
<ion-item text-wrap>
|
||||
<h2>{{ 'addon.coursecompletion.required' | translate }}</h2>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { AddonCourseCompletionProvider } from '../../providers/coursecompletion';
|
||||
import { AddonCourseCompletionProvider, AddonCourseCompletionCourseCompletionStatus } from '../../providers/coursecompletion';
|
||||
|
||||
/**
|
||||
* Component that displays the course completion report.
|
||||
|
@ -29,9 +29,10 @@ export class AddonCourseCompletionReportComponent implements OnInit {
|
|||
@Input() userId: number;
|
||||
|
||||
completionLoaded = false;
|
||||
completion: any;
|
||||
completion: AddonCourseCompletionCourseCompletionStatus;
|
||||
showSelfComplete: boolean;
|
||||
tracked = true; // Whether completion is tracked.
|
||||
statusText: string;
|
||||
|
||||
constructor(
|
||||
private sitesProvider: CoreSitesProvider,
|
||||
|
@ -59,7 +60,7 @@ export class AddonCourseCompletionReportComponent implements OnInit {
|
|||
protected fetchCompletion(): Promise<any> {
|
||||
return this.courseCompletionProvider.getCompletion(this.courseId, this.userId).then((completion) => {
|
||||
|
||||
completion.statusText = this.courseCompletionProvider.getCompletedStatusText(completion);
|
||||
this.statusText = this.courseCompletionProvider.getCompletedStatusText(completion);
|
||||
|
||||
this.completion = completion;
|
||||
this.showSelfComplete = this.courseCompletionProvider.canMarkSelfCompleted(this.userId, completion);
|
||||
|
|
|
@ -18,6 +18,7 @@ import { CoreSitesProvider } from '@providers/sites';
|
|||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||
import { CoreSite } from '@classes/site';
|
||||
import { CoreWSExternalWarning } from '@providers/ws';
|
||||
|
||||
/**
|
||||
* Service to handle course completion.
|
||||
|
@ -43,7 +44,7 @@ export class AddonCourseCompletionProvider {
|
|||
* @param completion Course completion.
|
||||
* @return True if user can mark course as self completed, false otherwise.
|
||||
*/
|
||||
canMarkSelfCompleted(userId: number, completion: any): boolean {
|
||||
canMarkSelfCompleted(userId: number, completion: AddonCourseCompletionCourseCompletionStatus): boolean {
|
||||
let selfCompletionActive = false,
|
||||
alreadyMarked = false;
|
||||
|
||||
|
@ -68,7 +69,7 @@ export class AddonCourseCompletionProvider {
|
|||
* @param completion Course completion.
|
||||
* @return Language code of the text to show.
|
||||
*/
|
||||
getCompletedStatusText(completion: any): string {
|
||||
getCompletedStatusText(completion: AddonCourseCompletionCourseCompletionStatus): string {
|
||||
if (completion.completed) {
|
||||
return 'addon.coursecompletion.completed';
|
||||
} else {
|
||||
|
@ -96,7 +97,9 @@ export class AddonCourseCompletionProvider {
|
|||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Promise to be resolved when the completion is retrieved.
|
||||
*/
|
||||
getCompletion(courseId: number, userId?: number, preSets?: any, siteId?: string): Promise<any> {
|
||||
getCompletion(courseId: number, userId?: number, preSets?: any, siteId?: string)
|
||||
: Promise<AddonCourseCompletionCourseCompletionStatus> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
userId = userId || site.getUserId();
|
||||
preSets = preSets || {};
|
||||
|
@ -112,7 +115,9 @@ export class AddonCourseCompletionProvider {
|
|||
preSets.updateFrequency = preSets.updateFrequency || CoreSite.FREQUENCY_SOMETIMES;
|
||||
preSets.cacheErrors = ['notenroled'];
|
||||
|
||||
return site.read('core_completion_get_course_completion_status', data, preSets).then((data) => {
|
||||
return site.read('core_completion_get_course_completion_status', data, preSets)
|
||||
.then((data: AddonCourseCompletionGetCourseCompletionStatusResult): any => {
|
||||
|
||||
if (data.completionstatus) {
|
||||
return data.completionstatus;
|
||||
}
|
||||
|
@ -243,17 +248,56 @@ export class AddonCourseCompletionProvider {
|
|||
* Mark a course as self completed.
|
||||
*
|
||||
* @param courseId Course ID.
|
||||
* @return Resolved on success.
|
||||
* @return Promise resolved on success.
|
||||
*/
|
||||
markCourseAsSelfCompleted(courseId: number): Promise<any> {
|
||||
markCourseAsSelfCompleted(courseId: number): Promise<void> {
|
||||
const params = {
|
||||
courseid: courseId
|
||||
};
|
||||
|
||||
return this.sitesProvider.getCurrentSite().write('core_completion_mark_course_self_completed', params).then((response) => {
|
||||
return this.sitesProvider.getCurrentSite().write('core_completion_mark_course_self_completed', params)
|
||||
.then((response: AddonCourseCompletionMarkCourseSelfCompletedResult) => {
|
||||
|
||||
if (!response.status) {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completion status returned by core_completion_get_course_completion_status.
|
||||
*/
|
||||
export type AddonCourseCompletionCourseCompletionStatus = {
|
||||
completed: boolean; // True if the course is complete, false otherwise.
|
||||
aggregation: number; // Aggregation method 1 means all, 2 means any.
|
||||
completions: {
|
||||
type: number; // Completion criteria type.
|
||||
title: string; // Completion criteria Title.
|
||||
status: string; // Completion status (Yes/No) a % or number.
|
||||
complete: boolean; // Completion status (true/false).
|
||||
timecompleted: number; // Timestamp for criteria completetion.
|
||||
details: {
|
||||
type: string; // Type description.
|
||||
criteria: string; // Criteria description.
|
||||
requirement: string; // Requirement description.
|
||||
status: string; // Status description, can be anything.
|
||||
}; // Details.
|
||||
}[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_completion_get_course_completion_status.
|
||||
*/
|
||||
export type AddonCourseCompletionGetCourseCompletionStatusResult = {
|
||||
completionstatus: AddonCourseCompletionCourseCompletionStatus; // Course status.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_completion_mark_course_self_completed.
|
||||
*/
|
||||
export type AddonCourseCompletionMarkCourseSelfCompletedResult = {
|
||||
status: boolean; // Status, true if success.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@ import { CoreEventsProvider } from '@providers/events';
|
|||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { AddonFilesProvider } from '../../providers/files';
|
||||
import { AddonFilesProvider, AddonFilesFile, AddonFilesGetUserPrivateFilesInfoResult } from '../../providers/files';
|
||||
import { AddonFilesHelperProvider } from '../../providers/helper';
|
||||
|
||||
/**
|
||||
|
@ -40,10 +40,10 @@ export class AddonFilesListPage implements OnDestroy {
|
|||
root: string; // The root of the files loaded: 'my' or 'site'.
|
||||
path: string; // The path of the directory being loaded. If empty path it means the root is being loaded.
|
||||
userQuota: number; // The user quota (in bytes).
|
||||
filesInfo: any; // Info about private files (size, number of files, etc.).
|
||||
filesInfo: AddonFilesGetUserPrivateFilesInfoResult; // Info about private files (size, number of files, etc.).
|
||||
spaceUsed: string; // Space used in a readable format.
|
||||
userQuotaReadable: string; // User quota in a readable format.
|
||||
files: any[]; // List of files.
|
||||
files: AddonFilesFile[]; // List of files.
|
||||
component: string; // Component to link the file downloads to.
|
||||
filesLoaded: boolean; // Whether the files are loaded.
|
||||
|
||||
|
@ -147,7 +147,7 @@ export class AddonFilesListPage implements OnDestroy {
|
|||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected fetchFiles(): Promise<any> {
|
||||
let promise;
|
||||
let promise: Promise<AddonFilesFile[]>;
|
||||
|
||||
if (!this.path) {
|
||||
// The path is unknown, the user must be requesting a root.
|
||||
|
|
|
@ -16,6 +16,7 @@ import { Injectable } from '@angular/core';
|
|||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype';
|
||||
import { CoreSite } from '@classes/site';
|
||||
import { CoreWSExternalWarning } from '@providers/ws';
|
||||
|
||||
/**
|
||||
* Service to handle my files and site files.
|
||||
|
@ -73,7 +74,7 @@ export class AddonFilesProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with the files.
|
||||
*/
|
||||
getFiles(params: any, siteId?: string): Promise<any[]> {
|
||||
getFiles(params: any, siteId?: string): Promise<AddonFilesFile[]> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const preSets = {
|
||||
|
@ -82,15 +83,15 @@ export class AddonFilesProvider {
|
|||
};
|
||||
|
||||
return site.read('core_files_get_files', params, preSets);
|
||||
}).then((result) => {
|
||||
const entries = [];
|
||||
}).then((result: AddonFilesGetFilesResult) => {
|
||||
const entries: AddonFilesFile[] = [];
|
||||
|
||||
if (result.files) {
|
||||
result.files.forEach((entry) => {
|
||||
if (entry.isdir) {
|
||||
// Create a "link" to load the folder.
|
||||
entry.link = {
|
||||
contextid: entry.contextid || '',
|
||||
contextid: entry.contextid || null,
|
||||
component: entry.component || '',
|
||||
filearea: entry.filearea || '',
|
||||
itemid: entry.itemid || 0,
|
||||
|
@ -135,7 +136,7 @@ export class AddonFilesProvider {
|
|||
*
|
||||
* @return Promise resolved with the files.
|
||||
*/
|
||||
getPrivateFiles(): Promise<any[]> {
|
||||
getPrivateFiles(): Promise<AddonFilesFile[]> {
|
||||
return this.getFiles(this.getPrivateFilesRootParams());
|
||||
}
|
||||
|
||||
|
@ -164,7 +165,7 @@ export class AddonFilesProvider {
|
|||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Promise resolved with the info.
|
||||
*/
|
||||
getPrivateFilesInfo(userId?: number, siteId?: string): Promise<any> {
|
||||
getPrivateFilesInfo(userId?: number, siteId?: string): Promise<AddonFilesGetUserPrivateFilesInfoResult> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
userId = userId || site.getUserId();
|
||||
|
||||
|
@ -204,7 +205,7 @@ export class AddonFilesProvider {
|
|||
*
|
||||
* @return Promise resolved with the files.
|
||||
*/
|
||||
getSiteFiles(): Promise<any[]> {
|
||||
getSiteFiles(): Promise<AddonFilesFile[]> {
|
||||
return this.getFiles(this.getSiteFilesRootParams());
|
||||
}
|
||||
|
||||
|
@ -388,7 +389,7 @@ export class AddonFilesProvider {
|
|||
* @param siteid ID of the site. If not defined, use current site.
|
||||
* @return Promise resolved in success, rejected otherwise.
|
||||
*/
|
||||
moveFromDraftToPrivate(draftId: number, siteId?: string): Promise<any> {
|
||||
moveFromDraftToPrivate(draftId: number, siteId?: string): Promise<null> {
|
||||
const params = {
|
||||
draftid: draftId
|
||||
},
|
||||
|
@ -414,3 +415,63 @@ export class AddonFilesProvider {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* File data returned by core_files_get_files.
|
||||
*/
|
||||
export type AddonFilesFile = {
|
||||
contextid: number;
|
||||
component: string;
|
||||
filearea: string;
|
||||
itemid: number;
|
||||
filepath: string;
|
||||
filename: string;
|
||||
isdir: boolean;
|
||||
url: string;
|
||||
timemodified: number;
|
||||
timecreated?: number; // Time created.
|
||||
filesize?: number; // File size.
|
||||
author?: string; // File owner.
|
||||
license?: string; // File license.
|
||||
} & AddonFilesFileCalculatedData;
|
||||
|
||||
/**
|
||||
* Result of WS core_files_get_files.
|
||||
*/
|
||||
export type AddonFilesGetFilesResult = {
|
||||
parents: {
|
||||
contextid: number;
|
||||
component: string;
|
||||
filearea: string;
|
||||
itemid: number;
|
||||
filepath: string;
|
||||
filename: string;
|
||||
}[];
|
||||
files: AddonFilesFile[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_user_get_private_files_info.
|
||||
*/
|
||||
export type AddonFilesGetUserPrivateFilesInfoResult = {
|
||||
filecount: number; // Number of files in the area.
|
||||
foldercount: number; // Number of folders in the area.
|
||||
filesize: number; // Total size of the files in the area.
|
||||
filesizewithoutreferences: number; // Total size of the area excluding file references.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculated data for AddonFilesFile.
|
||||
*/
|
||||
export type AddonFilesFileCalculatedData = {
|
||||
link?: { // Calculated in the app. A link to open the folder.
|
||||
contextid?: number; // Folder's contextid.
|
||||
component?: string; // Folder's component.
|
||||
filearea?: string; // Folder's filearea.
|
||||
itemid?: number; // Folder's itemid.
|
||||
filepath?: string; // Folder's filepath.
|
||||
filename?: string; // Folder's filename.
|
||||
};
|
||||
imgPath?: string; // Path to file icon's image.
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ import { Component, OnDestroy } from '@angular/core';
|
|||
import { IonicPage } from 'ionic-angular';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications';
|
||||
import { AddonMessageOutputAirnotifierProvider } from '../../providers/airnotifier';
|
||||
import { AddonMessageOutputAirnotifierProvider, AddonMessageOutputAirnotifierDevice } from '../../providers/airnotifier';
|
||||
|
||||
/**
|
||||
* Page that displays the list of devices.
|
||||
|
@ -28,7 +28,7 @@ import { AddonMessageOutputAirnotifierProvider } from '../../providers/airnotifi
|
|||
})
|
||||
export class AddonMessageOutputAirnotifierDevicesPage implements OnDestroy {
|
||||
|
||||
devices = [];
|
||||
devices: AddonMessageOutputAirnotifierDeviceFormatted[] = [];
|
||||
devicesLoaded = false;
|
||||
|
||||
protected updateTimeout: any;
|
||||
|
@ -54,7 +54,7 @@ export class AddonMessageOutputAirnotifierDevicesPage implements OnDestroy {
|
|||
const pushId = this.pushNotificationsProvider.getPushId();
|
||||
|
||||
// Convert enabled to boolean and search current device.
|
||||
devices.forEach((device) => {
|
||||
devices.forEach((device: AddonMessageOutputAirnotifierDeviceFormatted) => {
|
||||
device.enable = !!device.enable;
|
||||
device.current = pushId && pushId == device.pushid;
|
||||
});
|
||||
|
@ -110,8 +110,9 @@ export class AddonMessageOutputAirnotifierDevicesPage implements OnDestroy {
|
|||
* @param device The device object.
|
||||
* @param enable True to enable the device, false to disable it.
|
||||
*/
|
||||
enableDevice(device: any, enable: boolean): void {
|
||||
enableDevice(device: AddonMessageOutputAirnotifierDeviceFormatted, enable: boolean): void {
|
||||
device.updating = true;
|
||||
|
||||
this.airnotifierProivder.enableDevice(device.id, enable).then(() => {
|
||||
// Update the list of devices since it was modified.
|
||||
this.updateDevicesAfterDelay();
|
||||
|
@ -135,3 +136,11 @@ export class AddonMessageOutputAirnotifierDevicesPage implements OnDestroy {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* User device with some calculated data.
|
||||
*/
|
||||
type AddonMessageOutputAirnotifierDeviceFormatted = AddonMessageOutputAirnotifierDevice & {
|
||||
current?: boolean; // Calculated in the app. Whether it's the current device.
|
||||
updating?: boolean; // Calculated in the app. Whether the device enable is being updated right now.
|
||||
};
|
||||
|
|
|
@ -17,6 +17,7 @@ import { CoreLoggerProvider } from '@providers/logger';
|
|||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreConfigConstants } from '../../../../configconstants';
|
||||
import { CoreSite } from '@classes/site';
|
||||
import { CoreWSExternalWarning } from '@providers/ws';
|
||||
|
||||
/**
|
||||
* Service to handle Airnotifier message output.
|
||||
|
@ -39,14 +40,16 @@ export class AddonMessageOutputAirnotifierProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved if success.
|
||||
*/
|
||||
enableDevice(deviceId: number, enable: boolean, siteId?: string): Promise<any> {
|
||||
enableDevice(deviceId: number, enable: boolean, siteId?: string): Promise<void> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const data = {
|
||||
deviceid: deviceId,
|
||||
enable: enable ? 1 : 0
|
||||
};
|
||||
|
||||
return site.write('message_airnotifier_enable_device', data).then((result) => {
|
||||
return site.write('message_airnotifier_enable_device', data)
|
||||
.then((result: AddonMessageOutputAirnotifierEnableDeviceResult) => {
|
||||
|
||||
if (!result.success) {
|
||||
// Fail. Reject with warning message if any.
|
||||
if (result.warnings && result.warnings.length) {
|
||||
|
@ -74,7 +77,7 @@ export class AddonMessageOutputAirnotifierProvider {
|
|||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Promise resolved with the devices.
|
||||
*/
|
||||
getUserDevices(siteId?: string): Promise<any> {
|
||||
getUserDevices(siteId?: string): Promise<AddonMessageOutputAirnotifierDevice[]> {
|
||||
this.logger.debug('Get user devices');
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
@ -86,7 +89,8 @@ export class AddonMessageOutputAirnotifierProvider {
|
|||
updateFrequency: CoreSite.FREQUENCY_RARELY
|
||||
};
|
||||
|
||||
return site.read('message_airnotifier_get_user_devices', data, preSets).then((data) => {
|
||||
return site.read('message_airnotifier_get_user_devices', data, preSets)
|
||||
.then((data: AddonMessageOutputAirnotifierGetUserDevicesResult) => {
|
||||
return data.devices;
|
||||
});
|
||||
});
|
||||
|
@ -115,3 +119,36 @@ export class AddonMessageOutputAirnotifierProvider {
|
|||
this.sitesProvider.wsAvailableInCurrentSite('message_airnotifier_get_user_devices');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Device data returned by WS message_airnotifier_get_user_devices.
|
||||
*/
|
||||
export type AddonMessageOutputAirnotifierDevice = {
|
||||
id: number; // Device id (in the message_airnotifier table).
|
||||
appid: string; // The app id, something like com.moodle.moodlemobile.
|
||||
name: string; // The device name, 'occam' or 'iPhone' etc.
|
||||
model: string; // The device model 'Nexus4' or 'iPad1,1' etc.
|
||||
platform: string; // The device platform 'iOS' or 'Android' etc.
|
||||
version: string; // The device version '6.1.2' or '4.2.2' etc.
|
||||
pushid: string; // The device PUSH token/key/identifier/registration id.
|
||||
uuid: string; // The device UUID.
|
||||
enable: number | boolean; // Whether the device is enabled or not.
|
||||
timecreated: number; // Time created.
|
||||
timemodified: number; // Time modified.
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS message_airnotifier_enable_device.
|
||||
*/
|
||||
export type AddonMessageOutputAirnotifierEnableDeviceResult = {
|
||||
success: boolean; // True if success.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS message_airnotifier_get_user_devices.
|
||||
*/
|
||||
export type AddonMessageOutputAirnotifierGetUserDevicesResult = {
|
||||
devices: AddonMessageOutputAirnotifierDevice[]; // List of devices.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@
|
|||
import { Content } from 'ionic-angular';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { AddonMessagesProvider } from '../../providers/messages';
|
||||
import { AddonMessagesProvider, AddonMessagesConversationMember } from '../../providers/messages';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
|
||||
/**
|
||||
|
@ -33,7 +33,7 @@ export class AddonMessagesConfirmedContactsComponent implements OnInit, OnDestro
|
|||
loaded = false;
|
||||
canLoadMore = false;
|
||||
loadMoreError = false;
|
||||
contacts = [];
|
||||
contacts: AddonMessagesConversationMember[] = [];
|
||||
selectedUserId: number;
|
||||
|
||||
protected memberInfoObserver;
|
||||
|
|
|
@ -16,7 +16,7 @@ import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@
|
|||
import { Content } from 'ionic-angular';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { AddonMessagesProvider } from '../../providers/messages';
|
||||
import { AddonMessagesProvider, AddonMessagesConversationMember } from '../../providers/messages';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
|
||||
/**
|
||||
|
@ -33,7 +33,7 @@ export class AddonMessagesContactRequestsComponent implements OnInit, OnDestroy
|
|||
loaded = false;
|
||||
canLoadMore = false;
|
||||
loadMoreError = false;
|
||||
requests = [];
|
||||
requests: AddonMessagesConversationMember[] = [];
|
||||
selectedUserId: number;
|
||||
|
||||
protected memberInfoObserver;
|
||||
|
|
|
@ -16,7 +16,9 @@ import { Component } from '@angular/core';
|
|||
import { NavParams } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { AddonMessagesProvider } from '../../providers/messages';
|
||||
import {
|
||||
AddonMessagesProvider, AddonMessagesGetContactsResult, AddonMessagesSearchContactsContact
|
||||
} from '../../providers/messages';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
|
@ -42,7 +44,10 @@ export class AddonMessagesContactsComponent {
|
|||
searchType = 'search';
|
||||
loadingMessage = '';
|
||||
hasContacts = false;
|
||||
contacts = {
|
||||
contacts: AddonMessagesGetContactsFormatted = {
|
||||
online: [],
|
||||
offline: [],
|
||||
strangers: [],
|
||||
search: []
|
||||
};
|
||||
searchString = '';
|
||||
|
@ -205,7 +210,7 @@ export class AddonMessagesContactsComponent {
|
|||
this.searchString = query;
|
||||
this.contactTypes = ['search'];
|
||||
|
||||
this.contacts['search'] = this.sortUsers(result);
|
||||
this.contacts.search = this.sortUsers(result);
|
||||
}).catch((error) => {
|
||||
this.domUtils.showErrorModalDefault(error, 'addon.messages.errorwhileretrievingcontacts', true);
|
||||
});
|
||||
|
@ -234,3 +239,10 @@ export class AddonMessagesContactsComponent {
|
|||
this.memberInfoObserver && this.memberInfoObserver.off();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contacts with some calculated data.
|
||||
*/
|
||||
export type AddonMessagesGetContactsFormatted = AddonMessagesGetContactsResult & {
|
||||
search?: AddonMessagesSearchContactsContact[]; // Calculated in the app. Result of searching users.
|
||||
};
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { IonicPage, NavParams, ViewController } from 'ionic-angular';
|
||||
import { AddonMessagesProvider } from '../../providers/messages';
|
||||
import {
|
||||
AddonMessagesProvider, AddonMessagesConversationFormatted, AddonMessagesConversationMember
|
||||
} from '../../providers/messages';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
|
||||
/**
|
||||
|
@ -28,8 +30,8 @@ import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
|||
export class AddonMessagesConversationInfoPage implements OnInit {
|
||||
|
||||
loaded = false;
|
||||
conversation: any;
|
||||
members = [];
|
||||
conversation: AddonMessagesConversationFormatted;
|
||||
members: AddonMessagesConversationMember[] = [];
|
||||
canLoadMore = false;
|
||||
loadMoreError = false;
|
||||
|
||||
|
|
|
@ -17,7 +17,10 @@ import { IonicPage, NavParams, NavController, Content, ModalController } from 'i
|
|||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { AddonMessagesProvider } from '../../providers/messages';
|
||||
import {
|
||||
AddonMessagesProvider, AddonMessagesConversationFormatted, AddonMessagesConversationMember, AddonMessagesConversationMessage,
|
||||
AddonMessagesGetMessagesMessage
|
||||
} from '../../providers/messages';
|
||||
import { AddonMessagesOfflineProvider } from '../../providers/messages-offline';
|
||||
import { AddonMessagesSyncProvider } from '../../providers/sync';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
|
@ -54,7 +57,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
protected messagesBeingSent = 0;
|
||||
protected pagesLoaded = 1;
|
||||
protected lastMessage = {text: '', timecreated: 0};
|
||||
protected keepMessageMap = {};
|
||||
protected keepMessageMap: {[hash: string]: boolean} = {};
|
||||
protected syncObserver: any;
|
||||
protected oldContentHeight = 0;
|
||||
protected keyboardObserver: any;
|
||||
|
@ -64,7 +67,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
protected showLoadingModal = false; // Whether to show a loading modal while fetching data.
|
||||
|
||||
conversationId: number; // Conversation ID. Undefined if it's a new individual conversation.
|
||||
conversation: any; // The conversation object (if it exists).
|
||||
conversation: AddonMessagesConversationFormatted; // The conversation object (if it exists).
|
||||
userId: number; // User ID you're talking to (only if group messaging not enabled or it's a new individual conversation).
|
||||
currentUserId: number;
|
||||
title: string;
|
||||
|
@ -74,18 +77,18 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
showKeyboard = false;
|
||||
canLoadMore = false;
|
||||
loadMoreError = false;
|
||||
messages = [];
|
||||
messages: (AddonMessagesConversationMessageFormatted | AddonMessagesGetMessagesMessageFormatted)[] = [];
|
||||
showDelete = false;
|
||||
canDelete = false;
|
||||
groupMessagingEnabled: boolean;
|
||||
isGroup = false;
|
||||
members: any = {}; // Members that wrote a message, indexed by ID.
|
||||
members: {[id: number]: AddonMessagesConversationMember} = {}; // Members that wrote a message, indexed by ID.
|
||||
favouriteIcon = 'fa-star';
|
||||
favouriteIconSlash = false;
|
||||
deleteIcon = 'trash';
|
||||
blockIcon = 'close-circle';
|
||||
addRemoveIcon = 'person';
|
||||
otherMember: any; // Other member information (individual conversations only).
|
||||
otherMember: AddonMessagesConversationMember; // Other member information (individual conversations only).
|
||||
footerType: 'message' | 'blocked' | 'requiresContact' | 'requestSent' | 'requestReceived' | 'unable';
|
||||
requestContactSent = false;
|
||||
requestContactReceived = false;
|
||||
|
@ -139,7 +142,9 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
* @param message Message to be added.
|
||||
* @param keep If set the keep flag or not.
|
||||
*/
|
||||
protected addMessage(message: any, keep: boolean = true): void {
|
||||
protected addMessage(message: AddonMessagesConversationMessageFormatted | AddonMessagesGetMessagesMessageFormatted,
|
||||
keep: boolean = true): void {
|
||||
|
||||
/* Create a hash to identify the message. The text of online messages isn't reliable because it can have random data
|
||||
like VideoJS ID. Try to use id and fallback to text for offline messages. */
|
||||
message.hash = Md5.hashAsciiStr(String(message.id || message.text || '')) + '#' + message.timecreated + '#' +
|
||||
|
@ -158,7 +163,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
*
|
||||
* @param hash Hash of the message to be removed.
|
||||
*/
|
||||
protected removeMessage(hash: any): void {
|
||||
protected removeMessage(hash: string): void {
|
||||
if (this.keepMessageMap[hash]) {
|
||||
// Selected to keep it, clear the flag.
|
||||
this.keepMessageMap[hash] = false;
|
||||
|
@ -261,10 +266,11 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
if (!this.title && this.messages.length) {
|
||||
// Didn't receive the fullname via argument. Try to get it from messages.
|
||||
// It's possible that name cannot be resolved when no messages were yet exchanged.
|
||||
if (this.messages[0].useridto != this.currentUserId) {
|
||||
this.title = this.messages[0].usertofullname || '';
|
||||
const firstMessage = <AddonMessagesGetMessagesMessageFormatted> this.messages[0];
|
||||
if (firstMessage.useridto != this.currentUserId) {
|
||||
this.title = firstMessage.usertofullname || '';
|
||||
} else {
|
||||
this.title = this.messages[0].userfromfullname || '';
|
||||
this.title = firstMessage.userfromfullname || '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -302,7 +308,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
*
|
||||
* @return Resolved when done.
|
||||
*/
|
||||
protected fetchMessages(): Promise<any> {
|
||||
protected fetchMessages(): Promise<void> {
|
||||
this.loadMoreError = false;
|
||||
|
||||
if (this.messagesBeingSent > 0) {
|
||||
|
@ -341,7 +347,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
return this.getDiscussionMessages(this.pagesLoaded);
|
||||
});
|
||||
}
|
||||
}).then((messages) => {
|
||||
}).then((messages: (AddonMessagesConversationMessageFormatted | AddonMessagesGetMessagesMessageFormatted)[]) => {
|
||||
this.loadMessages(messages);
|
||||
}).finally(() => {
|
||||
this.fetching = false;
|
||||
|
@ -353,7 +359,9 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
*
|
||||
* @param messages Messages to load.
|
||||
*/
|
||||
protected loadMessages(messages: any[]): void {
|
||||
protected loadMessages(messages: (AddonMessagesConversationMessageFormatted | AddonMessagesGetMessagesMessageFormatted)[])
|
||||
: void {
|
||||
|
||||
if (this.viewDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
@ -382,7 +390,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
this.messagesProvider.sortMessages(this.messages);
|
||||
|
||||
// Calculate which messages need to display the date or user data.
|
||||
this.messages.forEach((message, index): any => {
|
||||
this.messages.forEach((message, index) => {
|
||||
message.showDate = this.showDate(message, this.messages[index - 1]);
|
||||
message.showUserData = this.showUserData(message, this.messages[index - 1]);
|
||||
message.showTail = this.showTail(message, this.messages[index + 1]);
|
||||
|
@ -411,20 +419,22 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
* @return Promise resolved with a boolean: whether the conversation exists or not.
|
||||
*/
|
||||
protected getConversation(conversationId: number, userId: number): Promise<boolean> {
|
||||
let promise,
|
||||
fallbackConversation;
|
||||
let promise: Promise<number>,
|
||||
fallbackConversation: AddonMessagesConversationFormatted;
|
||||
|
||||
// Try to get the conversationId if we don't have it.
|
||||
if (conversationId) {
|
||||
promise = Promise.resolve(conversationId);
|
||||
} else {
|
||||
let subPromise: Promise<AddonMessagesConversationFormatted>;
|
||||
|
||||
if (userId == this.currentUserId && this.messagesProvider.isSelfConversationEnabled()) {
|
||||
promise = this.messagesProvider.getSelfConversation();
|
||||
subPromise = this.messagesProvider.getSelfConversation();
|
||||
} else {
|
||||
promise = this.messagesProvider.getConversationBetweenUsers(userId, undefined, true);
|
||||
subPromise = this.messagesProvider.getConversationBetweenUsers(userId, undefined, true);
|
||||
}
|
||||
|
||||
promise = promise.then((conversation) => {
|
||||
promise = subPromise.then((conversation) => {
|
||||
fallbackConversation = conversation;
|
||||
|
||||
return conversation.id;
|
||||
|
@ -437,14 +447,14 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
// Ignore errors.
|
||||
}).then(() => {
|
||||
return this.messagesProvider.getConversation(conversationId, undefined, true);
|
||||
}).catch((error) => {
|
||||
}).catch((error): any => {
|
||||
// Get conversation failed, use the fallback one if we have it.
|
||||
if (fallbackConversation) {
|
||||
return fallbackConversation;
|
||||
}
|
||||
|
||||
return Promise.reject(error);
|
||||
}).then((conversation) => {
|
||||
}).then((conversation: AddonMessagesConversationFormatted) => {
|
||||
this.conversation = conversation;
|
||||
|
||||
if (conversation) {
|
||||
|
@ -495,7 +505,9 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
* @param offset Offset for message list.
|
||||
* @return Promise resolved with the list of messages.
|
||||
*/
|
||||
protected getConversationMessages(pagesToLoad: number, offset: number = 0): Promise<any[]> {
|
||||
protected getConversationMessages(pagesToLoad: number, offset: number = 0)
|
||||
: Promise<AddonMessagesConversationMessageFormatted[]> {
|
||||
|
||||
const excludePending = offset > 0;
|
||||
|
||||
return this.messagesProvider.getConversationMessages(this.conversationId, excludePending, offset).then((result) => {
|
||||
|
@ -535,7 +547,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
* @return Resolved when done.
|
||||
*/
|
||||
protected getDiscussionMessages(pagesToLoad: number, lfReceivedUnread: number = 0, lfReceivedRead: number = 0,
|
||||
lfSentUnread: number = 0, lfSentRead: number = 0): Promise<any> {
|
||||
lfSentUnread: number = 0, lfSentRead: number = 0): Promise<AddonMessagesGetMessagesMessageFormatted[]> {
|
||||
|
||||
// Only get offline messages if we're loading the first "page".
|
||||
const excludePending = lfReceivedUnread > 0 || lfReceivedRead > 0 || lfSentUnread > 0 || lfSentRead > 0;
|
||||
|
@ -547,7 +559,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
pagesToLoad--;
|
||||
if (pagesToLoad > 0 && result.canLoadMore) {
|
||||
// More pages to load. Calculate new limit froms.
|
||||
result.messages.forEach((message) => {
|
||||
result.messages.forEach((message: AddonMessagesGetMessagesMessageFormatted) => {
|
||||
if (!message.pending) {
|
||||
if (message.useridfrom == this.userId) {
|
||||
if (message.read) {
|
||||
|
@ -598,7 +610,8 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
for (const x in this.messages) {
|
||||
const message = this.messages[x];
|
||||
// If an unread message is found, mark all messages as read.
|
||||
if (message.useridfrom != this.currentUserId && message.read == 0) {
|
||||
if (message.useridfrom != this.currentUserId &&
|
||||
(<AddonMessagesGetMessagesMessageFormatted> message).read == 0) {
|
||||
messageUnreadFound = true;
|
||||
break;
|
||||
}
|
||||
|
@ -616,7 +629,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
promise = this.messagesProvider.markAllMessagesRead(this.userId).then(() => {
|
||||
// Mark all messages as read.
|
||||
this.messages.forEach((message) => {
|
||||
message.read = 1;
|
||||
(<AddonMessagesGetMessagesMessageFormatted> message).read = 1;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -630,10 +643,10 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
// Mark each message as read one by one.
|
||||
this.messages.forEach((message) => {
|
||||
// If the message is unread, call this.messagesProvider.markMessageRead.
|
||||
if (message.useridfrom != this.currentUserId && message.read == 0) {
|
||||
if (message.useridfrom != this.currentUserId && (<AddonMessagesGetMessagesMessageFormatted> message).read == 0) {
|
||||
promises.push(this.messagesProvider.markMessageRead(message.id).then(() => {
|
||||
readChanged = true;
|
||||
message.read = 1;
|
||||
(<AddonMessagesGetMessagesMessageFormatted> message).read = 1;
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
@ -703,7 +716,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
if (!message.pending && message.useridfrom != this.currentUserId) {
|
||||
found++;
|
||||
if (found == this.conversation.unreadcount) {
|
||||
this.unreadMessageFrom = parseInt(message.id, 10);
|
||||
this.unreadMessageFrom = Number(message.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -713,13 +726,13 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
let previousMessageRead = false;
|
||||
|
||||
for (const x in this.messages) {
|
||||
const message = this.messages[x];
|
||||
const message = <AddonMessagesGetMessagesMessageFormatted> this.messages[x];
|
||||
if (message.useridfrom != this.currentUserId) {
|
||||
const unreadFrom = message.read == 0 && previousMessageRead;
|
||||
|
||||
if (unreadFrom) {
|
||||
// Save where the label is placed.
|
||||
this.unreadMessageFrom = parseInt(message.id, 10);
|
||||
this.unreadMessageFrom = Number(message.id);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -808,8 +821,9 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
*
|
||||
* @param message Message to be copied.
|
||||
*/
|
||||
copyMessage(message: any): void {
|
||||
const text = this.textUtils.decodeHTMLEntities(message.smallmessage || message.text || '');
|
||||
copyMessage(message: AddonMessagesConversationMessageFormatted | AddonMessagesGetMessagesMessageFormatted): void {
|
||||
const text = this.textUtils.decodeHTMLEntities(
|
||||
(<AddonMessagesGetMessagesMessageFormatted> message).smallmessage || message.text || '');
|
||||
this.utils.copyToClipboard(text);
|
||||
}
|
||||
|
||||
|
@ -819,7 +833,9 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
* @param message Message object to delete.
|
||||
* @param index Index where the message is to delete it from the view.
|
||||
*/
|
||||
deleteMessage(message: any, index: number): void {
|
||||
deleteMessage(message: AddonMessagesConversationMessageFormatted | AddonMessagesGetMessagesMessageFormatted, index: number)
|
||||
: void {
|
||||
|
||||
const canDeleteAll = this.conversation && this.conversation.candeletemessagesforallusers,
|
||||
langKey = message.pending || canDeleteAll || this.isSelf ? 'core.areyousure' :
|
||||
'addon.messages.deletemessageconfirmation',
|
||||
|
@ -860,7 +876,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
* @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading.
|
||||
* @return Resolved when done.
|
||||
*/
|
||||
loadPrevious(infiniteComplete?: any): Promise<any> {
|
||||
loadPrevious(infiniteComplete?: any): Promise<void> {
|
||||
let infiniteHeight = this.infinite ? this.infinite.getHeight() : 0;
|
||||
const scrollHeight = this.domUtils.getScrollHeight(this.content);
|
||||
|
||||
|
@ -962,7 +978,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
* @param text Message text.
|
||||
*/
|
||||
sendMessage(text: string): void {
|
||||
let message;
|
||||
let message: AddonMessagesConversationMessageFormatted | AddonMessagesGetMessagesMessageFormatted;
|
||||
|
||||
this.hideUnreadLabel();
|
||||
|
||||
|
@ -970,6 +986,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
this.scrollBottom = true;
|
||||
|
||||
message = {
|
||||
id: null,
|
||||
pending: true,
|
||||
sending: true,
|
||||
useridfrom: this.currentUserId,
|
||||
|
@ -985,7 +1002,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
// If there is an ongoing fetch, wait for it to finish.
|
||||
// Otherwise, if a message is sent while fetching it could disappear until the next fetch.
|
||||
this.waitForFetch().finally(() => {
|
||||
let promise;
|
||||
let promise: Promise<{sent: boolean, message: any}>;
|
||||
|
||||
if (this.conversationId) {
|
||||
promise = this.messagesProvider.sendMessageToConversation(this.conversation, text);
|
||||
|
@ -1050,7 +1067,9 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
* @param prevMessage Previous message where to compare the date with.
|
||||
* @return If date has changed and should be shown.
|
||||
*/
|
||||
showDate(message: any, prevMessage?: any): boolean {
|
||||
showDate(message: AddonMessagesConversationMessageFormatted | AddonMessagesGetMessagesMessageFormatted,
|
||||
prevMessage?: AddonMessagesConversationMessageFormatted | AddonMessagesGetMessagesMessageFormatted): boolean {
|
||||
|
||||
if (!prevMessage) {
|
||||
// First message, show it.
|
||||
return true;
|
||||
|
@ -1068,7 +1087,9 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
* @param prevMessage Previous message.
|
||||
* @return Whether user data should be shown.
|
||||
*/
|
||||
showUserData(message: any, prevMessage?: any): boolean {
|
||||
showUserData(message: AddonMessagesConversationMessageFormatted | AddonMessagesGetMessagesMessageFormatted,
|
||||
prevMessage?: AddonMessagesConversationMessageFormatted | AddonMessagesGetMessagesMessageFormatted): boolean {
|
||||
|
||||
return this.isGroup && message.useridfrom != this.currentUserId && this.members[message.useridfrom] &&
|
||||
(!prevMessage || prevMessage.useridfrom != message.useridfrom || message.showDate);
|
||||
}
|
||||
|
@ -1080,7 +1101,8 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
* @param nextMessage Next message.
|
||||
* @return Whether user data should be shown.
|
||||
*/
|
||||
showTail(message: any, nextMessage?: any): boolean {
|
||||
showTail(message: AddonMessagesConversationMessageFormatted | AddonMessagesGetMessagesMessageFormatted,
|
||||
nextMessage?: AddonMessagesConversationMessageFormatted | AddonMessagesGetMessagesMessageFormatted): boolean {
|
||||
return !nextMessage || nextMessage.useridfrom != message.useridfrom || nextMessage.showDate;
|
||||
}
|
||||
|
||||
|
@ -1422,3 +1444,26 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
|
|||
this.viewDestroyed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Conversation message with some calculated data.
|
||||
*/
|
||||
type AddonMessagesConversationMessageFormatted = AddonMessagesConversationMessage & {
|
||||
pending?: boolean; // Calculated in the app. Whether the message is pending to be sent.
|
||||
sending?: boolean; // Calculated in the app. Whether the message is being sent right now.
|
||||
hash?: string; // Calculated in the app. A hash to identify the message.
|
||||
showDate?: boolean; // Calculated in the app. Whether to show the date before the message.
|
||||
showUserData?: boolean; // Calculated in the app. Whether to show the user data in the message.
|
||||
showTail?: boolean; // Calculated in the app. Whether to show a "tail" in the message.
|
||||
};
|
||||
|
||||
/**
|
||||
* Message with some calculated data.
|
||||
*/
|
||||
type AddonMessagesGetMessagesMessageFormatted = AddonMessagesGetMessagesMessage & {
|
||||
sending?: boolean; // Calculated in the app. Whether the message is being sent right now.
|
||||
hash?: string; // Calculated in the app. A hash to identify the message.
|
||||
showDate?: boolean; // Calculated in the app. Whether to show the date before the message.
|
||||
showUserData?: boolean; // Calculated in the app. Whether to show the user data in the message.
|
||||
showTail?: boolean; // Calculated in the app. Whether to show a "tail" in the message.
|
||||
};
|
||||
|
|
|
@ -17,7 +17,9 @@ import { IonicPage, Platform, NavController, NavParams, Content } from 'ionic-an
|
|||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { AddonMessagesProvider } from '../../providers/messages';
|
||||
import {
|
||||
AddonMessagesProvider, AddonMessagesConversationFormatted, AddonMessagesConversationMessage
|
||||
} from '../../providers/messages';
|
||||
import { AddonMessagesOfflineProvider } from '../../providers/messages-offline';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
|
@ -45,19 +47,19 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
selectedConversationId: number;
|
||||
selectedUserId: number;
|
||||
contactRequestsCount = 0;
|
||||
favourites: any = {
|
||||
favourites: AddonMessagesGroupConversationOption = {
|
||||
type: null,
|
||||
favourites: true,
|
||||
count: 0,
|
||||
unread: 0
|
||||
unread: 0,
|
||||
};
|
||||
group: any = {
|
||||
group: AddonMessagesGroupConversationOption = {
|
||||
type: AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_GROUP,
|
||||
favourites: false,
|
||||
count: 0,
|
||||
unread: 0
|
||||
};
|
||||
individual: any = {
|
||||
individual: AddonMessagesGroupConversationOption = {
|
||||
type: AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
favourites: false,
|
||||
count: 0,
|
||||
|
@ -331,7 +333,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
*
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected fetchDataForExpandedOption(): Promise<any> {
|
||||
protected fetchDataForExpandedOption(): Promise<void> {
|
||||
const expandedOption = this.getExpandedOption();
|
||||
|
||||
if (expandedOption) {
|
||||
|
@ -349,12 +351,12 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
* @param getCounts Whether to get counts data.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
fetchDataForOption(option: any, loadingMore?: boolean, getCounts?: boolean): Promise<void> {
|
||||
fetchDataForOption(option: AddonMessagesGroupConversationOption, loadingMore?: boolean, getCounts?: boolean): Promise<void> {
|
||||
option.loadMoreError = false;
|
||||
|
||||
const limitFrom = loadingMore ? option.conversations.length : 0,
|
||||
promises = [];
|
||||
let data,
|
||||
let data: {conversations: AddonMessagesConversationForList[], canLoadMore: boolean},
|
||||
offlineMessages;
|
||||
|
||||
// Get the conversations and, if needed, the offline messages. Always try to get the latest data.
|
||||
|
@ -422,7 +424,9 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
* @param option The option to search in. If not defined, search in all options.
|
||||
* @return Conversation.
|
||||
*/
|
||||
protected findConversation(conversationId: number, userId?: number, option?: any): any {
|
||||
protected findConversation(conversationId: number, userId?: number, option?: AddonMessagesGroupConversationOption)
|
||||
: AddonMessagesConversationForList {
|
||||
|
||||
if (conversationId) {
|
||||
const conversations = option ? (option.conversations || []) : ((this.favourites.conversations || [])
|
||||
.concat(this.group.conversations || []).concat(this.individual.conversations || []));
|
||||
|
@ -445,7 +449,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
*
|
||||
* @return Option currently expanded.
|
||||
*/
|
||||
protected getExpandedOption(): any {
|
||||
protected getExpandedOption(): AddonMessagesGroupConversationOption {
|
||||
if (this.favourites.expanded) {
|
||||
return this.favourites;
|
||||
} else if (this.group.expanded) {
|
||||
|
@ -495,9 +499,9 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
*
|
||||
* @param option The option to fetch data for.
|
||||
* @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading.
|
||||
* @return Resolved when done.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
loadMoreConversations(option: any, infiniteComplete?: any): Promise<any> {
|
||||
loadMoreConversations(option: AddonMessagesGroupConversationOption, infiniteComplete?: any): Promise<void> {
|
||||
return this.fetchDataForOption(option, true).catch((error) => {
|
||||
this.domUtils.showErrorModalDefault(error, 'addon.messages.errorwhileretrievingdiscussions', true);
|
||||
option.loadMoreError = true;
|
||||
|
@ -513,7 +517,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
* @param messages Offline messages.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected loadOfflineMessages(option: any, messages: any[]): Promise<any> {
|
||||
protected loadOfflineMessages(option: AddonMessagesGroupConversationOption, messages: any[]): Promise<any> {
|
||||
const promises = [];
|
||||
|
||||
messages.forEach((message) => {
|
||||
|
@ -588,7 +592,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
* @param conversation Conversation where to put the last message.
|
||||
* @param message Offline message to add.
|
||||
*/
|
||||
protected addLastOfflineMessage(conversation: any, message: any): void {
|
||||
protected addLastOfflineMessage(conversation: any, message: AddonMessagesConversationMessage): void {
|
||||
conversation.lastmessage = message.text;
|
||||
conversation.lastmessagedate = message.timecreated / 1000;
|
||||
conversation.lastmessagepending = true;
|
||||
|
@ -601,7 +605,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
* @param conversation Conversation to check.
|
||||
* @return Option object.
|
||||
*/
|
||||
protected getConversationOption(conversation: any): any {
|
||||
protected getConversationOption(conversation: AddonMessagesConversationForList): AddonMessagesGroupConversationOption {
|
||||
if (conversation.isfavourite) {
|
||||
return this.favourites;
|
||||
} else if (conversation.type == AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_GROUP) {
|
||||
|
@ -618,7 +622,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
* @param refreshUnreadCounts Whether to refresh unread counts.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
refreshData(refresher?: any, refreshUnreadCounts: boolean = true): Promise<any> {
|
||||
refreshData(refresher?: any, refreshUnreadCounts: boolean = true): Promise<void> {
|
||||
// Don't invalidate conversations and so, they always try to get latest data.
|
||||
const promises = [
|
||||
this.messagesProvider.invalidateContactRequestsCountCache(this.siteId)
|
||||
|
@ -638,7 +642,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
*
|
||||
* @param option The option to expand/collapse.
|
||||
*/
|
||||
toggle(option: any): void {
|
||||
toggle(option: AddonMessagesGroupConversationOption): void {
|
||||
if (option.expanded) {
|
||||
// Already expanded, close it.
|
||||
option.expanded = false;
|
||||
|
@ -658,7 +662,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
* @param getCounts Whether to get counts data.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected expandOption(option: any, getCounts?: boolean): Promise<any> {
|
||||
protected expandOption(option: AddonMessagesGroupConversationOption, getCounts?: boolean): Promise<void> {
|
||||
// Collapse all and expand the right one.
|
||||
this.favourites.expanded = false;
|
||||
this.group.expanded = false;
|
||||
|
@ -715,3 +719,25 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
this.memberInfoObserver && this.memberInfoObserver.off();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Conversation options.
|
||||
*/
|
||||
export type AddonMessagesGroupConversationOption = {
|
||||
type: number; // Option type.
|
||||
favourites: boolean; // Whether it contains favourites conversations.
|
||||
count: number; // Number of conversations.
|
||||
unread?: number; // Number of unread conversations.
|
||||
expanded?: boolean; // Whether the option is currently expanded.
|
||||
loading?: boolean; // Whether the option is being loaded.
|
||||
canLoadMore?: boolean; // Whether it can load more data.
|
||||
loadMoreError?: boolean; // Whether there was an error loading more conversations.
|
||||
conversations?: AddonMessagesConversationForList[]; // List of conversations.
|
||||
};
|
||||
|
||||
/**
|
||||
* Formatted conversation with some calculated data for the list.
|
||||
*/
|
||||
export type AddonMessagesConversationForList = AddonMessagesConversationFormatted & {
|
||||
lastmessagepending?: boolean; // Calculated in the app. Whether last message is pending to be sent.
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ import { Component, OnDestroy, ViewChild } from '@angular/core';
|
|||
import { IonicPage } from 'ionic-angular';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { AddonMessagesProvider } from '../../providers/messages';
|
||||
import { AddonMessagesProvider, AddonMessagesConversationMember, AddonMessagesMessageAreaContact } from '../../providers/messages';
|
||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
|
@ -38,21 +38,21 @@ export class AddonMessagesSearchPage implements OnDestroy {
|
|||
contacts = {
|
||||
type: 'contacts',
|
||||
titleString: 'addon.messages.contacts',
|
||||
results: [],
|
||||
results: <AddonMessagesConversationMember[]> [],
|
||||
canLoadMore: false,
|
||||
loadingMore: false
|
||||
};
|
||||
nonContacts = {
|
||||
type: 'noncontacts',
|
||||
titleString: 'addon.messages.noncontacts',
|
||||
results: [],
|
||||
results: <AddonMessagesConversationMember[]> [],
|
||||
canLoadMore: false,
|
||||
loadingMore: false
|
||||
};
|
||||
messages = {
|
||||
type: 'messages',
|
||||
titleString: 'addon.messages.messages',
|
||||
results: [],
|
||||
results: <AddonMessagesMessageAreaContact[]> [],
|
||||
canLoadMore: false,
|
||||
loadingMore: false,
|
||||
loadMoreError: false
|
||||
|
@ -116,9 +116,9 @@ export class AddonMessagesSearchPage implements OnDestroy {
|
|||
this.displaySearching = !loadMore;
|
||||
|
||||
const promises = [];
|
||||
let newContacts = [];
|
||||
let newNonContacts = [];
|
||||
let newMessages = [];
|
||||
let newContacts: AddonMessagesConversationMember[] = [];
|
||||
let newNonContacts: AddonMessagesConversationMember[] = [];
|
||||
let newMessages: AddonMessagesMessageAreaContact[] = [];
|
||||
let canLoadMoreContacts = false;
|
||||
let canLoadMoreNonContacts = false;
|
||||
let canLoadMoreMessages = false;
|
||||
|
|
|
@ -14,7 +14,10 @@
|
|||
|
||||
import { Component, OnDestroy } from '@angular/core';
|
||||
import { IonicPage } from 'ionic-angular';
|
||||
import { AddonMessagesProvider } from '../../providers/messages';
|
||||
import {
|
||||
AddonMessagesProvider, AddonMessagesMessagePreferences, AddonMessagesMessagePreferencesNotification,
|
||||
AddonMessagesMessagePreferencesNotificationProcessor
|
||||
} from '../../providers/messages';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreConfigProvider } from '@providers/config';
|
||||
|
@ -34,7 +37,7 @@ import { CoreConstants } from '@core/constants';
|
|||
export class AddonMessagesSettingsPage implements OnDestroy {
|
||||
protected updateTimeout: any;
|
||||
|
||||
preferences: any;
|
||||
preferences: AddonMessagesMessagePreferences;
|
||||
preferencesLoaded: boolean;
|
||||
contactablePrivacy: number | boolean;
|
||||
advancedContactable = false; // Whether the site supports "advanced" contactable privacy.
|
||||
|
@ -78,9 +81,9 @@ export class AddonMessagesSettingsPage implements OnDestroy {
|
|||
/**
|
||||
* Fetches preference data.
|
||||
*
|
||||
* @return Resolved when done.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected fetchPreferences(): Promise<any> {
|
||||
protected fetchPreferences(): Promise<void> {
|
||||
return this.messagesProvider.getMessagePreferences().then((preferences) => {
|
||||
if (this.groupMessagingEnabled) {
|
||||
// Simplify the preferences.
|
||||
|
@ -90,11 +93,12 @@ export class AddonMessagesSettingsPage implements OnDestroy {
|
|||
return notification.preferencekey == AddonMessagesProvider.NOTIFICATION_PREFERENCES_KEY;
|
||||
});
|
||||
|
||||
for (const notification of component.notifications) {
|
||||
for (const processor of notification.processors) {
|
||||
component.notifications.forEach((notification) => {
|
||||
notification.processors.forEach(
|
||||
(processor: AddonMessagesMessagePreferencesNotificationProcessorFormatted) => {
|
||||
processor.checked = processor.loggedin.checked || processor.loggedoff.checked;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,14 +172,16 @@ export class AddonMessagesSettingsPage implements OnDestroy {
|
|||
* @param state State name, ['loggedin', 'loggedoff'].
|
||||
* @param processor Notification processor.
|
||||
*/
|
||||
changePreference(notification: any, state: string, processor: any): void {
|
||||
changePreference(notification: AddonMessagesMessagePreferencesNotificationFormatted, state: string,
|
||||
processor: AddonMessagesMessagePreferencesNotificationProcessorFormatted): void {
|
||||
|
||||
if (this.groupMessagingEnabled) {
|
||||
// Update both states at the same time.
|
||||
const valueArray = [],
|
||||
promises = [];
|
||||
let value = 'none';
|
||||
|
||||
notification.processors.forEach((processor) => {
|
||||
notification.processors.forEach((processor: AddonMessagesMessagePreferencesNotificationProcessorFormatted) => {
|
||||
if (processor.checked) {
|
||||
valueArray.push(processor.name);
|
||||
}
|
||||
|
@ -268,3 +274,17 @@ export class AddonMessagesSettingsPage implements OnDestroy {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Message preferences notification with some caclulated data.
|
||||
*/
|
||||
type AddonMessagesMessagePreferencesNotificationFormatted = AddonMessagesMessagePreferencesNotification & {
|
||||
updating?: boolean | {[state: string]: boolean}; // Calculated in the app. Whether the notification is being updated.
|
||||
};
|
||||
|
||||
/**
|
||||
* Message preferences notification processor with some caclulated data.
|
||||
*/
|
||||
type AddonMessagesMessagePreferencesNotificationProcessorFormatted = AddonMessagesMessagePreferencesNotificationProcessor & {
|
||||
checked?: boolean; // Calculated in the app. Whether the processor is checked either for loggedin or loggedoff.
|
||||
};
|
||||
|
|
|
@ -248,7 +248,7 @@ export class AddonMessagesMainMenuHandler implements CoreMainMenuHandler, CoreCr
|
|||
}
|
||||
|
||||
const currentUserId = site.getUserId(),
|
||||
message = conv.messages[0]; // Treat only the last message, is the one we're interested.
|
||||
message: any = conv.messages[0]; // Treat only the last message, is the one we're interested.
|
||||
|
||||
if (!message || message.useridfrom == currentUserId) {
|
||||
// No last message or not from current user. Return empty list.
|
||||
|
|
|
@ -23,6 +23,7 @@ import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
|||
import { CoreEmulatorHelperProvider } from '@core/emulator/providers/helper';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreSite } from '@classes/site';
|
||||
import { CoreWSExternalWarning } from '@providers/ws';
|
||||
|
||||
/**
|
||||
* Service to handle messages.
|
||||
|
@ -89,9 +90,9 @@ export class AddonMessagesProvider {
|
|||
*
|
||||
* @param userId User ID of the person to block.
|
||||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Resolved when done.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
blockContact(userId: number, siteId?: string): Promise<any> {
|
||||
blockContact(userId: number, siteId?: string): Promise<void> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
let promise;
|
||||
if (site.wsAvailable('core_message_block_user')) {
|
||||
|
@ -313,7 +314,9 @@ export class AddonMessagesProvider {
|
|||
* @param userId User ID viewing the conversation.
|
||||
* @return Formatted conversation.
|
||||
*/
|
||||
protected formatConversation(conversation: any, userId: number): any {
|
||||
protected formatConversation(conversation: AddonMessagesConversationFormatted, userId: number)
|
||||
: AddonMessagesConversationFormatted {
|
||||
|
||||
const numMessages = conversation.messages.length,
|
||||
lastMessage = numMessages ? conversation.messages[numMessages - 1] : null;
|
||||
|
||||
|
@ -536,10 +539,10 @@ export class AddonMessagesProvider {
|
|||
* Get all the contacts of the current user.
|
||||
*
|
||||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Resolved with the WS data.
|
||||
* @return Promise resolved with the WS data.
|
||||
* @deprecated since Moodle 3.6
|
||||
*/
|
||||
getAllContacts(siteId?: string): Promise<any> {
|
||||
getAllContacts(siteId?: string): Promise<AddonMessagesGetContactsResult> {
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
||||
return this.getContacts(siteId).then((contacts) => {
|
||||
|
@ -562,9 +565,9 @@ export class AddonMessagesProvider {
|
|||
* Get all the users blocked by the current user.
|
||||
*
|
||||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Resolved with the WS data.
|
||||
* @return Promise resolved with the WS data.
|
||||
*/
|
||||
getBlockedContacts(siteId?: string): Promise<any> {
|
||||
getBlockedContacts(siteId?: string): Promise<AddonMessagesGetBlockedUsersResult> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const userId = site.getUserId(),
|
||||
params = {
|
||||
|
@ -585,19 +588,24 @@ export class AddonMessagesProvider {
|
|||
* This excludes the blocked users.
|
||||
*
|
||||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Resolved with the WS data.
|
||||
* @return Promise resolved with the WS data.
|
||||
* @deprecated since Moodle 3.6
|
||||
*/
|
||||
getContacts(siteId?: string): Promise<any> {
|
||||
getContacts(siteId?: string): Promise<AddonMessagesGetContactsResult> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const preSets = {
|
||||
cacheKey: this.getCacheKeyForContacts(),
|
||||
updateFrequency: CoreSite.FREQUENCY_OFTEN
|
||||
};
|
||||
|
||||
return site.read('core_message_get_contacts', undefined, preSets).then((contacts) => {
|
||||
return site.read('core_message_get_contacts', undefined, preSets).then((contacts: AddonMessagesGetContactsResult) => {
|
||||
// Filter contacts with negative ID, they are notifications.
|
||||
const validContacts = {};
|
||||
const validContacts: AddonMessagesGetContactsResult = {
|
||||
online: [],
|
||||
offline: [],
|
||||
strangers: []
|
||||
};
|
||||
|
||||
for (const typeName in contacts) {
|
||||
if (!validContacts[typeName]) {
|
||||
validContacts[typeName] = [];
|
||||
|
@ -621,11 +629,11 @@ export class AddonMessagesProvider {
|
|||
* @param limitFrom Position of the first contact to fetch.
|
||||
* @param limitNum Number of contacts to fetch. Default is AddonMessagesProvider.LIMIT_CONTACTS.
|
||||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Resolved with the list of user contacts.
|
||||
* @return Promise resolved with the list of user contacts.
|
||||
* @since 3.6
|
||||
*/
|
||||
getUserContacts(limitFrom: number = 0, limitNum: number = AddonMessagesProvider.LIMIT_CONTACTS , siteId?: string):
|
||||
Promise<{contacts: any[], canLoadMore: boolean}> {
|
||||
Promise<{contacts: AddonMessagesConversationMember[], canLoadMore: boolean}> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const params = {
|
||||
|
@ -638,7 +646,9 @@ export class AddonMessagesProvider {
|
|||
updateFrequency: CoreSite.FREQUENCY_OFTEN
|
||||
};
|
||||
|
||||
return site.read('core_message_get_user_contacts', params, preSets).then((contacts) => {
|
||||
return site.read('core_message_get_user_contacts', params, preSets)
|
||||
.then((contacts: AddonMessagesConversationMember[]) => {
|
||||
|
||||
if (!contacts || !contacts.length) {
|
||||
return { contacts: [], canLoadMore: false };
|
||||
}
|
||||
|
@ -663,11 +673,11 @@ export class AddonMessagesProvider {
|
|||
* @param limitFrom Position of the first contact request to fetch.
|
||||
* @param limitNum Number of contact requests to fetch. Default is AddonMessagesProvider.LIMIT_CONTACTS.
|
||||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Resolved with the list of contact requests.
|
||||
* @return Promise resolved with the list of contact requests.
|
||||
* @since 3.6
|
||||
*/
|
||||
getContactRequests(limitFrom: number = 0, limitNum: number = AddonMessagesProvider.LIMIT_CONTACTS, siteId?: string):
|
||||
Promise<{requests: any[], canLoadMore: boolean}> {
|
||||
Promise<{requests: AddonMessagesConversationMember[], canLoadMore: boolean}> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const data = {
|
||||
|
@ -680,7 +690,9 @@ export class AddonMessagesProvider {
|
|||
updateFrequency: CoreSite.FREQUENCY_OFTEN
|
||||
};
|
||||
|
||||
return site.read('core_message_get_contact_requests', data, preSets).then((requests) => {
|
||||
return site.read('core_message_get_contact_requests', data, preSets)
|
||||
.then((requests: AddonMessagesConversationMember[]) => {
|
||||
|
||||
if (!requests || !requests.length) {
|
||||
return { requests: [], canLoadMore: false };
|
||||
}
|
||||
|
@ -716,7 +728,7 @@ export class AddonMessagesProvider {
|
|||
typeExpected: 'number'
|
||||
};
|
||||
|
||||
return site.read('core_message_get_received_contact_requests_count', data, preSets).then((count) => {
|
||||
return site.read('core_message_get_received_contact_requests_count', data, preSets).then((count: number) => {
|
||||
// Notify the new count so all badges are updated.
|
||||
this.eventsProvider.trigger(AddonMessagesProvider.CONTACT_REQUESTS_COUNT_EVENT, { count }, site.id);
|
||||
|
||||
|
@ -745,7 +757,7 @@ export class AddonMessagesProvider {
|
|||
*/
|
||||
getConversation(conversationId: number, includeContactRequests?: boolean, includePrivacyInfo?: boolean,
|
||||
messageOffset: number = 0, messageLimit: number = 1, memberOffset: number = 0, memberLimit: number = 2,
|
||||
newestFirst: boolean = true, siteId?: string, userId?: number): Promise<any> {
|
||||
newestFirst: boolean = true, siteId?: string, userId?: number): Promise<AddonMessagesConversationFormatted> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
userId = userId || site.getUserId();
|
||||
|
@ -765,7 +777,7 @@ export class AddonMessagesProvider {
|
|||
newestmessagesfirst: newestFirst ? 1 : 0
|
||||
};
|
||||
|
||||
return site.read('core_message_get_conversation', params, preSets).then((conversation) => {
|
||||
return site.read('core_message_get_conversation', params, preSets).then((conversation: AddonMessagesConversation) => {
|
||||
return this.formatConversation(conversation, userId);
|
||||
});
|
||||
});
|
||||
|
@ -792,7 +804,8 @@ export class AddonMessagesProvider {
|
|||
*/
|
||||
getConversationBetweenUsers(otherUserId: number, includeContactRequests?: boolean, includePrivacyInfo?: boolean,
|
||||
messageOffset: number = 0, messageLimit: number = 1, memberOffset: number = 0, memberLimit: number = 2,
|
||||
newestFirst: boolean = true, siteId?: string, userId?: number, preferCache?: boolean): Promise<any> {
|
||||
newestFirst: boolean = true, siteId?: string, userId?: number, preferCache?: boolean)
|
||||
: Promise<AddonMessagesConversationFormatted> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
userId = userId || site.getUserId();
|
||||
|
@ -813,7 +826,8 @@ export class AddonMessagesProvider {
|
|||
newestmessagesfirst: newestFirst ? 1 : 0
|
||||
};
|
||||
|
||||
return site.read('core_message_get_conversation_between_users', params, preSets).then((conversation) => {
|
||||
return site.read('core_message_get_conversation_between_users', params, preSets)
|
||||
.then((conversation: AddonMessagesConversation) => {
|
||||
return this.formatConversation(conversation, userId);
|
||||
});
|
||||
});
|
||||
|
@ -826,12 +840,11 @@ export class AddonMessagesProvider {
|
|||
* @param limitFrom Offset for members list.
|
||||
* @param limitTo Limit of members.
|
||||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @param userId User ID. If not defined, current user in the site.
|
||||
* @return Promise resolved with the response.
|
||||
* @param userId User ID. If not defined, current user in
|
||||
* @since 3.6
|
||||
*/
|
||||
getConversationMembers(conversationId: number, limitFrom: number = 0, limitTo?: number, includeContactRequests?: boolean,
|
||||
siteId?: string, userId?: number): Promise<any> {
|
||||
siteId?: string, userId?: number): Promise<{members: AddonMessagesConversationMember[], canLoadMore: boolean}> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
userId = userId || site.getUserId();
|
||||
|
@ -853,18 +866,21 @@ export class AddonMessagesProvider {
|
|||
includeprivacyinfo: 1,
|
||||
};
|
||||
|
||||
return site.read('core_message_get_conversation_members', params, preSets).then((members) => {
|
||||
const result: any = {};
|
||||
return site.read('core_message_get_conversation_members', params, preSets)
|
||||
.then((members: AddonMessagesConversationMember[]) => {
|
||||
|
||||
if (limitTo < 1) {
|
||||
result.canLoadMore = false;
|
||||
result.members = members;
|
||||
return {
|
||||
canLoadMore: false,
|
||||
members: members
|
||||
};
|
||||
} else {
|
||||
result.canLoadMore = members.length > limitTo;
|
||||
result.members = members.slice(0, limitTo);
|
||||
return {
|
||||
canLoadMore: members.length > limitTo,
|
||||
members: members.slice(0, limitTo)
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -884,7 +900,8 @@ export class AddonMessagesProvider {
|
|||
* @since 3.6
|
||||
*/
|
||||
getConversationMessages(conversationId: number, excludePending: boolean, limitFrom: number = 0, limitTo?: number,
|
||||
newestFirst: boolean = true, timeFrom: number = 0, siteId?: string, userId?: number): Promise<any> {
|
||||
newestFirst: boolean = true, timeFrom: number = 0, siteId?: string, userId?: number)
|
||||
: Promise<AddonMessagesGetConversationMessagesResult> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
userId = userId || site.getUserId();
|
||||
|
@ -913,7 +930,9 @@ export class AddonMessagesProvider {
|
|||
preSets['emergencyCache'] = false;
|
||||
}
|
||||
|
||||
return site.read('core_message_get_conversation_messages', params, preSets).then((result) => {
|
||||
return site.read('core_message_get_conversation_messages', params, preSets)
|
||||
.then((result: AddonMessagesGetConversationMessagesResult) => {
|
||||
|
||||
if (limitTo < 1) {
|
||||
result.canLoadMore = false;
|
||||
result.messages = result.messages;
|
||||
|
@ -975,7 +994,8 @@ export class AddonMessagesProvider {
|
|||
* @since 3.6
|
||||
*/
|
||||
getConversations(type?: number, favourites?: boolean, limitFrom: number = 0, siteId?: string, userId?: number,
|
||||
forceCache?: boolean, ignoreCache?: boolean): Promise<{conversations: any[], canLoadMore: boolean}> {
|
||||
forceCache?: boolean, ignoreCache?: boolean)
|
||||
: Promise<{conversations: AddonMessagesConversationFormatted[], canLoadMore: boolean}> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
userId = userId || site.getUserId();
|
||||
|
@ -1017,7 +1037,7 @@ export class AddonMessagesProvider {
|
|||
}
|
||||
|
||||
return Promise.reject(error);
|
||||
}).then((response) => {
|
||||
}).then((response: AddonMessagesGetConversationsResult) => {
|
||||
// Format the conversations, adding some calculated fields.
|
||||
const conversations = response.conversations.slice(0, this.LIMIT_MESSAGES).map((conversation) => {
|
||||
return this.formatConversation(conversation, userId);
|
||||
|
@ -1053,7 +1073,9 @@ export class AddonMessagesProvider {
|
|||
cacheKey: this.getCacheKeyForConversationCounts()
|
||||
};
|
||||
|
||||
return site.read('core_message_get_conversation_counts', {}, preSets).then((result) => {
|
||||
return site.read('core_message_get_conversation_counts', {}, preSets)
|
||||
.then((result: AddonMessagesGetConversationCountsResult) => {
|
||||
|
||||
const counts = {
|
||||
favourites: result.favourites,
|
||||
individual: result.types[AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_INDIVIDUAL],
|
||||
|
@ -1080,10 +1102,14 @@ export class AddonMessagesProvider {
|
|||
* @return Promise resolved with messages and a boolean telling if can load more messages.
|
||||
*/
|
||||
getDiscussion(userId: number, excludePending: boolean, lfReceivedUnread: number = 0, lfReceivedRead: number = 0,
|
||||
lfSentUnread: number = 0, lfSentRead: number = 0, toDisplay: boolean = true, siteId?: string): Promise<any> {
|
||||
lfSentUnread: number = 0, lfSentRead: number = 0, toDisplay: boolean = true, siteId?: string)
|
||||
: Promise<{messages: AddonMessagesGetMessagesMessage[], canLoadMore: boolean}> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const result = {},
|
||||
const result = {
|
||||
messages: <AddonMessagesGetMessagesMessage[]> [],
|
||||
canLoadMore: false
|
||||
},
|
||||
preSets = {
|
||||
cacheKey: this.getCacheKeyForDiscussion(userId)
|
||||
},
|
||||
|
@ -1107,7 +1133,7 @@ export class AddonMessagesProvider {
|
|||
// Get message received by current user.
|
||||
return this.getRecentMessages(params, preSets, lfReceivedUnread, lfReceivedRead, toDisplay, site.getId())
|
||||
.then((response) => {
|
||||
result['messages'] = response;
|
||||
result.messages = response;
|
||||
params.useridto = userId;
|
||||
params.useridfrom = site.getUserId();
|
||||
hasReceived = response.length > 0;
|
||||
|
@ -1115,16 +1141,16 @@ export class AddonMessagesProvider {
|
|||
// Get message sent by current user.
|
||||
return this.getRecentMessages(params, preSets, lfSentUnread, lfSentRead, toDisplay, siteId);
|
||||
}).then((response) => {
|
||||
result['messages'] = result['messages'].concat(response);
|
||||
result.messages = result.messages.concat(response);
|
||||
hasSent = response.length > 0;
|
||||
|
||||
if (result['messages'].length > this.LIMIT_MESSAGES) {
|
||||
if (result.messages.length > this.LIMIT_MESSAGES) {
|
||||
// Sort messages and get the more recent ones.
|
||||
result['canLoadMore'] = true;
|
||||
result['messages'] = this.sortMessages(result['messages']);
|
||||
result['messages'] = result['messages'].slice(-this.LIMIT_MESSAGES);
|
||||
result.canLoadMore = true;
|
||||
result.messages = this.sortMessages(result['messages']);
|
||||
result.messages = result.messages.slice(-this.LIMIT_MESSAGES);
|
||||
} else {
|
||||
result['canLoadMore'] = result['messages'].length == this.LIMIT_MESSAGES && (!hasReceived || !hasSent);
|
||||
result.canLoadMore = result.messages.length == this.LIMIT_MESSAGES && (!hasReceived || !hasSent);
|
||||
}
|
||||
|
||||
if (excludePending) {
|
||||
|
@ -1140,7 +1166,7 @@ export class AddonMessagesProvider {
|
|||
message.text = message.smallmessage;
|
||||
});
|
||||
|
||||
result['messages'] = result['messages'].concat(offlineMessages);
|
||||
result.messages = result.messages.concat(offlineMessages);
|
||||
|
||||
return result;
|
||||
});
|
||||
|
@ -1153,11 +1179,11 @@ export class AddonMessagesProvider {
|
|||
* If the site is 3.6 or higher, please use getConversations.
|
||||
*
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Resolved with an object where the keys are the user ID of the other user.
|
||||
* @return Promise resolved with an object where the keys are the user ID of the other user.
|
||||
*/
|
||||
getDiscussions(siteId?: string): Promise<any> {
|
||||
getDiscussions(siteId?: string): Promise<{[userId: number]: AddonMessagesDiscussion}> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const discussions = {},
|
||||
const discussions: {[userId: number]: AddonMessagesDiscussion} = {},
|
||||
currentUserId = site.getUserId(),
|
||||
params = {
|
||||
useridto: currentUserId,
|
||||
|
@ -1171,7 +1197,7 @@ export class AddonMessagesProvider {
|
|||
/**
|
||||
* Convenience function to treat a recent message, adding it to discussions list if needed.
|
||||
*/
|
||||
const treatRecentMessage = (message: any, userId: number, userFullname: string): void => {
|
||||
const treatRecentMessage = (message: AddonMessagesGetMessagesMessage, userId: number, userFullname: string): void => {
|
||||
if (typeof discussions[userId] === 'undefined') {
|
||||
discussions[userId] = {
|
||||
fullname: userFullname,
|
||||
|
@ -1272,7 +1298,7 @@ export class AddonMessagesProvider {
|
|||
* @return Promise resolved with the member info.
|
||||
* @since 3.6
|
||||
*/
|
||||
getMemberInfo(otherUserId: number, siteId?: string, userId?: number): Promise<any> {
|
||||
getMemberInfo(otherUserId: number, siteId?: string, userId?: number): Promise<AddonMessagesConversationMember> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
userId = userId || site.getUserId();
|
||||
|
||||
|
@ -1287,7 +1313,9 @@ export class AddonMessagesProvider {
|
|||
includeprivacyinfo: 1,
|
||||
};
|
||||
|
||||
return site.read('core_message_get_member_info', params, preSets).then((members) => {
|
||||
return site.read('core_message_get_member_info', params, preSets)
|
||||
.then((members: AddonMessagesConversationMember[]): any => {
|
||||
|
||||
if (!members || members.length < 1) {
|
||||
// Should never happen.
|
||||
return Promise.reject(null);
|
||||
|
@ -1313,7 +1341,7 @@ export class AddonMessagesProvider {
|
|||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Promise resolved with the message preferences.
|
||||
*/
|
||||
getMessagePreferences(siteId?: string): Promise<any> {
|
||||
getMessagePreferences(siteId?: string): Promise<AddonMessagesMessagePreferences> {
|
||||
this.logger.debug('Get message preferences');
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
@ -1322,7 +1350,9 @@ export class AddonMessagesProvider {
|
|||
updateFrequency: CoreSite.FREQUENCY_SOMETIMES
|
||||
};
|
||||
|
||||
return site.read('core_message_get_user_message_preferences', {}, preSets).then((data) => {
|
||||
return site.read('core_message_get_user_message_preferences', {}, preSets)
|
||||
.then((data: AddonMessagesGetUserMessagePreferencesResult): any => {
|
||||
|
||||
if (data.preferences) {
|
||||
data.preferences.blocknoncontacts = data.blocknoncontacts;
|
||||
|
||||
|
@ -1341,15 +1371,18 @@ export class AddonMessagesProvider {
|
|||
* @param preSets Set of presets for the WS.
|
||||
* @param toDisplay True if messages will be displayed to the user, either in view or in a notification.
|
||||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Promise resolved with the data.
|
||||
*/
|
||||
protected getMessages(params: any, preSets: any, toDisplay: boolean = true, siteId?: string): Promise<any> {
|
||||
protected getMessages(params: any, preSets: any, toDisplay: boolean = true, siteId?: string)
|
||||
: Promise<AddonMessagesGetMessagesResult> {
|
||||
|
||||
params['type'] = 'conversations';
|
||||
params['newestfirst'] = 1;
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const userId = site.getUserId();
|
||||
|
||||
return site.read('core_message_get_messages', params, preSets).then((response) => {
|
||||
return site.read('core_message_get_messages', params, preSets).then((response: AddonMessagesGetMessagesResult) => {
|
||||
response.messages.forEach((message) => {
|
||||
message.read = params.read == 0 ? 0 : 1;
|
||||
// Convert times to milliseconds.
|
||||
|
@ -1377,9 +1410,10 @@ export class AddonMessagesProvider {
|
|||
* @param limitFromRead Number of unread messages already fetched, so fetch will be done from this number.
|
||||
* @param toDisplay True if messages will be displayed to the user, either in view or in a notification.
|
||||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Promise resolved with the data.
|
||||
*/
|
||||
protected getRecentMessages(params: any, preSets: any, limitFromUnread: number = 0, limitFromRead: number = 0,
|
||||
toDisplay: boolean = true, siteId?: string): Promise<any> {
|
||||
toDisplay: boolean = true, siteId?: string): Promise<AddonMessagesGetMessagesMessage[]> {
|
||||
limitFromUnread = limitFromUnread || 0;
|
||||
limitFromRead = limitFromRead || 0;
|
||||
|
||||
|
@ -1427,7 +1461,7 @@ export class AddonMessagesProvider {
|
|||
* @since 3.7
|
||||
*/
|
||||
getSelfConversation(messageOffset: number = 0, messageLimit: number = 1, newestFirst: boolean = true, siteId?: string,
|
||||
userId?: number): Promise<any> {
|
||||
userId?: number): Promise<AddonMessagesConversationFormatted> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
userId = userId || site.getUserId();
|
||||
|
@ -1442,7 +1476,8 @@ export class AddonMessagesProvider {
|
|||
newestmessagesfirst: newestFirst ? 1 : 0
|
||||
};
|
||||
|
||||
return site.read('core_message_get_self_conversation', params, preSets).then((conversation) => {
|
||||
return site.read('core_message_get_self_conversation', params, preSets)
|
||||
.then((conversation: AddonMessagesConversation) => {
|
||||
return this.formatConversation(conversation, userId);
|
||||
});
|
||||
});
|
||||
|
@ -1466,7 +1501,8 @@ export class AddonMessagesProvider {
|
|||
cacheKey: this.getCacheKeyForUnreadConversationCounts()
|
||||
};
|
||||
|
||||
promise = site.read('core_message_get_unread_conversation_counts', {}, preSets).then((result) => {
|
||||
promise = site.read('core_message_get_unread_conversation_counts', {}, preSets)
|
||||
.then((result: AddonMessagesGetUnreadConversationCountsResult) => {
|
||||
return {
|
||||
favourites: result.favourites,
|
||||
individual: result.types[AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_INDIVIDUAL],
|
||||
|
@ -1485,7 +1521,7 @@ export class AddonMessagesProvider {
|
|||
typeExpected: 'number'
|
||||
};
|
||||
|
||||
promise = site.read('core_message_get_unread_conversations_count', params, preSets).then((count) => {
|
||||
promise = site.read('core_message_get_unread_conversations_count', params, preSets).then((count: number) => {
|
||||
return { favourites: 0, individual: count, group: 0, self: 0 };
|
||||
});
|
||||
} else {
|
||||
|
@ -1536,7 +1572,7 @@ export class AddonMessagesProvider {
|
|||
* @return Promise resolved with the message unread count.
|
||||
*/
|
||||
getUnreadReceivedMessages(toDisplay: boolean = true, forceCache: boolean = false, ignoreCache: boolean = false,
|
||||
siteId?: string): Promise<any> {
|
||||
siteId?: string): Promise<AddonMessagesGetMessagesResult> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const params = {
|
||||
read: 0,
|
||||
|
@ -2049,7 +2085,7 @@ export class AddonMessagesProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with boolean marking success or not.
|
||||
*/
|
||||
markMessageRead(messageId: number, siteId?: string): Promise<any> {
|
||||
markMessageRead(messageId: number, siteId?: string): Promise<AddonMessagesMarkMessageReadResult> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const params = {
|
||||
messageid: messageId,
|
||||
|
@ -2067,7 +2103,7 @@ export class AddonMessagesProvider {
|
|||
* @return Promise resolved if success.
|
||||
* @since 3.6
|
||||
*/
|
||||
markAllConversationMessagesRead(conversationId?: number): Promise<any> {
|
||||
markAllConversationMessagesRead(conversationId?: number): Promise<null> {
|
||||
const params = {
|
||||
userid: this.sitesProvider.getCurrentSiteUserId(),
|
||||
conversationid: conversationId
|
||||
|
@ -2085,7 +2121,7 @@ export class AddonMessagesProvider {
|
|||
* @param userIdFrom User Id for the sender.
|
||||
* @return Promise resolved with boolean marking success or not.
|
||||
*/
|
||||
markAllMessagesRead(userIdFrom?: number): Promise<any> {
|
||||
markAllMessagesRead(userIdFrom?: number): Promise<boolean> {
|
||||
const params = {
|
||||
useridto: this.sitesProvider.getCurrentSiteUserId(),
|
||||
useridfrom: userIdFrom
|
||||
|
@ -2217,8 +2253,9 @@ export class AddonMessagesProvider {
|
|||
* @param query The query string.
|
||||
* @param limit The number of results to return, 0 for none.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with the contacts.
|
||||
*/
|
||||
searchContacts(query: string, limit: number = 100, siteId?: string): Promise<any> {
|
||||
searchContacts(query: string, limit: number = 100, siteId?: string): Promise<AddonMessagesSearchContactsContact[]> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const data = {
|
||||
searchtext: query,
|
||||
|
@ -2228,7 +2265,9 @@ export class AddonMessagesProvider {
|
|||
getFromCache: false // Always try to get updated data. If it fails, it will get it from cache.
|
||||
};
|
||||
|
||||
return site.read('core_message_search_contacts', data, preSets).then((contacts) => {
|
||||
return site.read('core_message_search_contacts', data, preSets)
|
||||
.then((contacts: AddonMessagesSearchContactsContact[]) => {
|
||||
|
||||
if (limit && contacts.length > limit) {
|
||||
contacts = contacts.splice(0, limit);
|
||||
}
|
||||
|
@ -2250,7 +2289,7 @@ export class AddonMessagesProvider {
|
|||
* @return Promise resolved with the results.
|
||||
*/
|
||||
searchMessages(query: string, userId?: number, limitFrom: number = 0, limitNum: number = AddonMessagesProvider.LIMIT_SEARCH,
|
||||
siteId?: string): Promise<{messages: any[], canLoadMore: boolean}> {
|
||||
siteId?: string): Promise<{messages: AddonMessagesMessageAreaContact[], canLoadMore: boolean}> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const params = {
|
||||
|
@ -2263,13 +2302,15 @@ export class AddonMessagesProvider {
|
|||
getFromCache: false // Always try to get updated data. If it fails, it will get it from cache.
|
||||
};
|
||||
|
||||
return site.read('core_message_data_for_messagearea_search_messages', params, preSets).then((result) => {
|
||||
return site.read('core_message_data_for_messagearea_search_messages', params, preSets)
|
||||
.then((result: AddonMessagesDataForMessageAreaSearchMessagesResult) => {
|
||||
|
||||
if (!result.contacts || !result.contacts.length) {
|
||||
return { messages: [], canLoadMore: false };
|
||||
}
|
||||
|
||||
result.contacts.forEach((result) => {
|
||||
result.id = result.userid;
|
||||
result.contacts.forEach((contact) => {
|
||||
contact.id = contact.userid;
|
||||
});
|
||||
|
||||
this.userProvider.storeUsers(result.contacts, site.id);
|
||||
|
@ -2297,7 +2338,8 @@ export class AddonMessagesProvider {
|
|||
* @since 3.6
|
||||
*/
|
||||
searchUsers(query: string, limitFrom: number = 0, limitNum: number = AddonMessagesProvider.LIMIT_SEARCH, siteId?: string):
|
||||
Promise<{contacts: any[], nonContacts: any[], canLoadMoreContacts: boolean, canLoadMoreNonContacts: boolean}> {
|
||||
Promise<{contacts: AddonMessagesConversationMember[], nonContacts: AddonMessagesConversationMember[],
|
||||
canLoadMoreContacts: boolean, canLoadMoreNonContacts: boolean}> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const data = {
|
||||
|
@ -2310,7 +2352,7 @@ export class AddonMessagesProvider {
|
|||
getFromCache: false // Always try to get updated data. If it fails, it will get it from cache.
|
||||
};
|
||||
|
||||
return site.read('core_message_message_search_users', data, preSets).then((result) => {
|
||||
return site.read('core_message_message_search_users', data, preSets).then((result: AddonMessagesSearchUsersResult) => {
|
||||
const contacts = result.contacts || [];
|
||||
const nonContacts = result.noncontacts || [];
|
||||
|
||||
|
@ -2341,7 +2383,9 @@ export class AddonMessagesProvider {
|
|||
* - sent (Boolean) True if message was sent to server, false if stored in device.
|
||||
* - message (Object) If sent=false, contains the stored message.
|
||||
*/
|
||||
sendMessage(toUserId: number, message: string, siteId?: string): Promise<any> {
|
||||
sendMessage(toUserId: number, message: string, siteId?: string)
|
||||
: Promise<{sent: boolean, message: AddonMessagesSendInstantMessagesMessage}> {
|
||||
|
||||
// Convenience function to store a message to be synchronized later.
|
||||
const storeOffline = (): Promise<any> => {
|
||||
return this.messagesOffline.saveMessage(toUserId, message, siteId).then((entry) => {
|
||||
|
@ -2395,7 +2439,7 @@ export class AddonMessagesProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved if success, rejected if failure.
|
||||
*/
|
||||
sendMessageOnline(toUserId: number, message: string, siteId?: string): Promise<any> {
|
||||
sendMessageOnline(toUserId: number, message: string, siteId?: string): Promise<AddonMessagesSendInstantMessagesMessage> {
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
||||
const messages = [
|
||||
|
@ -2430,7 +2474,7 @@ export class AddonMessagesProvider {
|
|||
* @return Promise resolved if success, rejected if failure. Promise resolved doesn't mean that messages
|
||||
* have been sent, the resolve param can contain errors for messages not sent.
|
||||
*/
|
||||
sendMessagesOnline(messages: any, siteId?: string): Promise<any> {
|
||||
sendMessagesOnline(messages: any[], siteId?: string): Promise<AddonMessagesSendInstantMessagesMessage[]> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const data = {
|
||||
messages: messages
|
||||
|
@ -2451,7 +2495,9 @@ export class AddonMessagesProvider {
|
|||
* - message (any) If sent=false, contains the stored message.
|
||||
* @since 3.6
|
||||
*/
|
||||
sendMessageToConversation(conversation: any, message: string, siteId?: string): Promise<any> {
|
||||
sendMessageToConversation(conversation: any, message: string, siteId?: string)
|
||||
: Promise<{sent: boolean, message: AddonMessagesSendMessagesToConversationMessage}> {
|
||||
|
||||
// Convenience function to store a message to be synchronized later.
|
||||
const storeOffline = (): Promise<any> => {
|
||||
return this.messagesOffline.saveConversationMessage(conversation, message, siteId).then((entry) => {
|
||||
|
@ -2506,7 +2552,8 @@ export class AddonMessagesProvider {
|
|||
* @return Promise resolved if success, rejected if failure.
|
||||
* @since 3.6
|
||||
*/
|
||||
sendMessageToConversationOnline(conversationId: number, message: string, siteId?: string): Promise<any> {
|
||||
sendMessageToConversationOnline(conversationId: number, message: string, siteId?: string)
|
||||
: Promise<AddonMessagesSendMessagesToConversationMessage> {
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
||||
const messages = [
|
||||
|
@ -2534,7 +2581,9 @@ export class AddonMessagesProvider {
|
|||
* @return Promise resolved if success, rejected if failure.
|
||||
* @since 3.6
|
||||
*/
|
||||
sendMessagesToConversationOnline(conversationId: number, messages: any, siteId?: string): Promise<any> {
|
||||
sendMessagesToConversationOnline(conversationId: number, messages: any[], siteId?: string)
|
||||
: Promise<AddonMessagesSendMessagesToConversationMessage[]> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const params = {
|
||||
conversationid: conversationId,
|
||||
|
@ -2603,10 +2652,10 @@ export class AddonMessagesProvider {
|
|||
* @param conversations Array of conversations.
|
||||
* @return Conversations sorted with most recent last.
|
||||
*/
|
||||
sortConversations(conversations: any[]): any[] {
|
||||
sortConversations(conversations: AddonMessagesConversationFormatted[]): AddonMessagesConversationFormatted[] {
|
||||
return conversations.sort((a, b) => {
|
||||
const timeA = parseInt(a.lastmessagedate, 10),
|
||||
timeB = parseInt(b.lastmessagedate, 10);
|
||||
const timeA = Number(a.lastmessagedate),
|
||||
timeB = Number(b.lastmessagedate);
|
||||
|
||||
if (timeA == timeB && a.id) {
|
||||
// Same time, sort by ID.
|
||||
|
@ -2651,7 +2700,9 @@ export class AddonMessagesProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected storeLastReceivedMessageIfNeeded(convIdOrUserIdFrom: number, message: any, siteId?: string): Promise<any> {
|
||||
protected storeLastReceivedMessageIfNeeded(convIdOrUserIdFrom: number,
|
||||
message: AddonMessagesGetMessagesMessage | AddonMessagesConversationMessage, siteId?: string): Promise<any> {
|
||||
|
||||
const component = AddonMessagesProvider.PUSH_SIMULATION_COMPONENT;
|
||||
|
||||
// Get the last received message.
|
||||
|
@ -2675,7 +2726,7 @@ export class AddonMessagesProvider {
|
|||
*
|
||||
* @param contactTypes List of contacts grouped in types.
|
||||
*/
|
||||
protected storeUsersFromAllContacts(contactTypes: any): void {
|
||||
protected storeUsersFromAllContacts(contactTypes: AddonMessagesGetContactsResult): void {
|
||||
for (const x in contactTypes) {
|
||||
this.userProvider.storeUsers(contactTypes[x]);
|
||||
}
|
||||
|
@ -2735,3 +2786,377 @@ export class AddonMessagesProvider {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Conversation.
|
||||
*/
|
||||
export type AddonMessagesConversation = {
|
||||
id: number; // The conversation id.
|
||||
name: string; // The conversation name, if set.
|
||||
subname: string; // A subtitle for the conversation name, if set.
|
||||
imageurl: string; // A link to the conversation picture, if set.
|
||||
type: number; // The type of the conversation (1=individual,2=group,3=self).
|
||||
membercount: number; // Total number of conversation members.
|
||||
ismuted: boolean; // If the user muted this conversation.
|
||||
isfavourite: boolean; // If the user marked this conversation as a favourite.
|
||||
isread: boolean; // If the user has read all messages in the conversation.
|
||||
unreadcount: number; // The number of unread messages in this conversation.
|
||||
members: AddonMessagesConversationMember[];
|
||||
messages: AddonMessagesConversationMessage[];
|
||||
candeletemessagesforallusers: boolean; // @since 3.7. If the user can delete messages in the conversation for all users.
|
||||
};
|
||||
|
||||
/**
|
||||
* Conversation with some calculated data.
|
||||
*/
|
||||
export type AddonMessagesConversationFormatted = AddonMessagesConversation & {
|
||||
lastmessage?: string; // Calculated in the app. Last message.
|
||||
lastmessagedate?: number; // Calculated in the app. Date the last message was sent.
|
||||
sentfromcurrentuser?: boolean; // Calculated in the app. Whether last message was sent by the current user.
|
||||
name?: string; // Calculated in the app. If private conversation, name of the other user.
|
||||
userid?: number; // Calculated in the app. URL. If private conversation, ID of the other user.
|
||||
showonlinestatus?: boolean; // Calculated in the app. If private conversation, whether to show online status of the other user.
|
||||
isonline?: boolean; // Calculated in the app. If private conversation, whether the other user is online.
|
||||
isblocked?: boolean; // Calculated in the app. If private conversation, whether the other user is blocked.
|
||||
otherUser?: AddonMessagesConversationMember; // Calculated in the app. Other user in the conversation.
|
||||
};
|
||||
|
||||
/**
|
||||
* Conversation member.
|
||||
*/
|
||||
export type AddonMessagesConversationMember = {
|
||||
id: number; // The user id.
|
||||
fullname: string; // The user's name.
|
||||
profileurl: string; // The link to the user's profile page.
|
||||
profileimageurl: string; // User picture URL.
|
||||
profileimageurlsmall: string; // Small user picture URL.
|
||||
isonline: boolean; // The user's online status.
|
||||
showonlinestatus: boolean; // Show the user's online status?.
|
||||
isblocked: boolean; // If the user has been blocked.
|
||||
iscontact: boolean; // Is the user a contact?.
|
||||
isdeleted: boolean; // Is the user deleted?.
|
||||
canmessageevenifblocked: boolean; // If the user can still message even if they get blocked.
|
||||
canmessage: boolean; // If the user can be messaged.
|
||||
requirescontact: boolean; // If the user requires to be contacts.
|
||||
contactrequests?: { // The contact requests.
|
||||
id: number; // The id of the contact request.
|
||||
userid: number; // The id of the user who created the contact request.
|
||||
requesteduserid: number; // The id of the user confirming the request.
|
||||
timecreated: number; // The timecreated timestamp for the contact request.
|
||||
}[];
|
||||
conversations?: { // Conversations between users.
|
||||
id: number; // Conversations id.
|
||||
type: number; // Conversation type: private or public.
|
||||
name: string; // Multilang compatible conversation name2.
|
||||
timecreated: number; // The timecreated timestamp for the conversation.
|
||||
}[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Conversation message.
|
||||
*/
|
||||
export type AddonMessagesConversationMessage = {
|
||||
id: number; // The id of the message.
|
||||
useridfrom: number; // The id of the user who sent the message.
|
||||
text: string; // The text of the message.
|
||||
timecreated: number; // The timecreated timestamp for the message.
|
||||
};
|
||||
|
||||
/**
|
||||
* Message preferences.
|
||||
*/
|
||||
export type AddonMessagesMessagePreferences = {
|
||||
userid: number; // User id.
|
||||
disableall: number; // Whether all the preferences are disabled.
|
||||
processors: { // Config form values.
|
||||
displayname: string; // Display name.
|
||||
name: string; // Processor name.
|
||||
hassettings: boolean; // Whether has settings.
|
||||
contextid: number; // Context id.
|
||||
userconfigured: number; // Whether is configured by the user.
|
||||
}[];
|
||||
components: { // Available components.
|
||||
displayname: string; // Display name.
|
||||
notifications: AddonMessagesMessagePreferencesNotification[]; // List of notificaitons for the component.
|
||||
}[];
|
||||
} & AddonMessagesMessagePreferencesCalculatedData;
|
||||
|
||||
/**
|
||||
* Notification processor in message preferences.
|
||||
*/
|
||||
export type AddonMessagesMessagePreferencesNotification = {
|
||||
displayname: string; // Display name.
|
||||
preferencekey: string; // Preference key.
|
||||
processors: AddonMessagesMessagePreferencesNotificationProcessor[]; // Processors values for this notification.
|
||||
};
|
||||
|
||||
/**
|
||||
* Notification processor in message preferences.
|
||||
*/
|
||||
export type AddonMessagesMessagePreferencesNotificationProcessor = {
|
||||
displayname: string; // Display name.
|
||||
name: string; // Processor name.
|
||||
locked: boolean; // Is locked by admin?.
|
||||
lockedmessage?: string; // Text to display if locked.
|
||||
userconfigured: number; // Is configured?.
|
||||
loggedin: {
|
||||
name: string; // Name.
|
||||
displayname: string; // Display name.
|
||||
checked: boolean; // Is checked?.
|
||||
};
|
||||
loggedoff: {
|
||||
name: string; // Name.
|
||||
displayname: string; // Display name.
|
||||
checked: boolean; // Is checked?.
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Message discussion (before 3.6).
|
||||
*/
|
||||
export type AddonMessagesDiscussion = {
|
||||
fullname: string; // Full name of the other user in the discussion.
|
||||
profileimageurl: string; // Profile image of the other user in the discussion.
|
||||
message?: { // Last message.
|
||||
id: number; // Message ID.
|
||||
user: number; // User ID that sent the message.
|
||||
message: string; // Text of the message.
|
||||
timecreated: number; // Time the message was sent.
|
||||
pending?: boolean; // Whether the message is pending to be sent.
|
||||
};
|
||||
unread?: boolean; // Whether the discussion has unread messages.
|
||||
};
|
||||
|
||||
/**
|
||||
* Contact for message area.
|
||||
*/
|
||||
export type AddonMessagesMessageAreaContact = {
|
||||
userid: number; // The user's id.
|
||||
fullname: string; // The user's name.
|
||||
profileimageurl: string; // User picture URL.
|
||||
profileimageurlsmall: string; // Small user picture URL.
|
||||
ismessaging: boolean; // If we are messaging the user.
|
||||
sentfromcurrentuser: boolean; // Was the last message sent from the current user?.
|
||||
lastmessage: string; // The user's last message.
|
||||
lastmessagedate: number; // Timestamp for last message.
|
||||
messageid: number; // The unique search message id.
|
||||
showonlinestatus: boolean; // Show the user's online status?.
|
||||
isonline: boolean; // The user's online status.
|
||||
isread: boolean; // If the user has read the message.
|
||||
isblocked: boolean; // If the user has been blocked.
|
||||
unreadcount: number; // The number of unread messages in this conversation.
|
||||
conversationid: number; // The id of the conversation.
|
||||
} & AddonMessagesMessageAreaContactCalculatedData;
|
||||
|
||||
/**
|
||||
* Result of WS core_message_get_blocked_users.
|
||||
*/
|
||||
export type AddonMessagesGetBlockedUsersResult = {
|
||||
users: AddonMessagesBlockedUser[]; // List of blocked users.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* User data returned by core_message_get_blocked_users.
|
||||
*/
|
||||
export type AddonMessagesBlockedUser = {
|
||||
id: number; // User ID.
|
||||
fullname: string; // User full name.
|
||||
profileimageurl?: string; // User picture URL.
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_message_get_contacts.
|
||||
*/
|
||||
export type AddonMessagesGetContactsResult = {
|
||||
online: AddonMessagesGetContactsContact[]; // List of online contacts.
|
||||
offline: AddonMessagesGetContactsContact[]; // List of offline contacts.
|
||||
strangers: AddonMessagesGetContactsContact[]; // List of users that are not in the user's contact list but have sent a message.
|
||||
} & AddonMessagesGetContactsCalculatedData;
|
||||
|
||||
/**
|
||||
* User data returned by core_message_get_contacts.
|
||||
*/
|
||||
export type AddonMessagesGetContactsContact = {
|
||||
id: number; // User ID.
|
||||
fullname: string; // User full name.
|
||||
profileimageurl?: string; // User picture URL.
|
||||
profileimageurlsmall?: string; // Small user picture URL.
|
||||
unread: number; // Unread message count.
|
||||
};
|
||||
|
||||
/**
|
||||
* User data returned by core_message_search_contacts.
|
||||
*/
|
||||
export type AddonMessagesSearchContactsContact = {
|
||||
id: number; // User ID.
|
||||
fullname: string; // User full name.
|
||||
profileimageurl?: string; // User picture URL.
|
||||
profileimageurlsmall?: string; // Small user picture URL.
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_message_get_conversation_messages.
|
||||
*/
|
||||
export type AddonMessagesGetConversationMessagesResult = {
|
||||
id: number; // The conversation id.
|
||||
members: AddonMessagesConversationMember[];
|
||||
messages: AddonMessagesConversationMessage[];
|
||||
} & AddonMessagesGetConversationMessagesCalculatedData;
|
||||
|
||||
/**
|
||||
* Result of WS core_message_get_conversations.
|
||||
*/
|
||||
export type AddonMessagesGetConversationsResult = {
|
||||
conversations: AddonMessagesConversation[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_message_get_conversation_counts.
|
||||
*/
|
||||
export type AddonMessagesGetConversationCountsResult = {
|
||||
favourites: number; // Total number of favourite conversations.
|
||||
types: {
|
||||
1: number; // Total number of individual conversations.
|
||||
2: number; // Total number of group conversations.
|
||||
3: number; // Total number of self conversations.
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_message_get_unread_conversation_counts.
|
||||
*/
|
||||
export type AddonMessagesGetUnreadConversationCountsResult = {
|
||||
favourites: number; // Total number of unread favourite conversations.
|
||||
types: {
|
||||
1: number; // Total number of unread individual conversations.
|
||||
2: number; // Total number of unread group conversations.
|
||||
3: number; // Total number of unread self conversations.
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_message_get_user_message_preferences.
|
||||
*/
|
||||
export type AddonMessagesGetUserMessagePreferencesResult = {
|
||||
preferences: AddonMessagesMessagePreferences;
|
||||
blocknoncontacts: number; // Privacy messaging setting to define who can message you.
|
||||
entertosend: boolean; // User preference for using enter to send messages.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_message_get_messages.
|
||||
*/
|
||||
export type AddonMessagesGetMessagesResult = {
|
||||
messages: AddonMessagesGetMessagesMessage[];
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Message data returned by core_message_get_messages.
|
||||
*/
|
||||
export type AddonMessagesGetMessagesMessage = {
|
||||
id: number; // Message id.
|
||||
useridfrom: number; // User from id.
|
||||
useridto: number; // User to id.
|
||||
subject: string; // The message subject.
|
||||
text: string; // The message text formated.
|
||||
fullmessage: string; // The message.
|
||||
fullmessageformat: number; // Fullmessage format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||
fullmessagehtml: string; // The message in html.
|
||||
smallmessage: string; // The shorten message.
|
||||
notification: number; // Is a notification?.
|
||||
contexturl: string; // Context URL.
|
||||
contexturlname: string; // Context URL link name.
|
||||
timecreated: number; // Time created.
|
||||
timeread: number; // Time read.
|
||||
usertofullname: string; // User to full name.
|
||||
userfromfullname: string; // User from full name.
|
||||
component?: string; // The component that generated the notification.
|
||||
eventtype?: string; // The type of notification.
|
||||
customdata?: string; // Custom data to be passed to the message processor.
|
||||
} & AddonMessagesGetMessagesMessageCalculatedData;
|
||||
|
||||
/**
|
||||
* Result of WS core_message_data_for_messagearea_search_messages.
|
||||
*/
|
||||
export type AddonMessagesDataForMessageAreaSearchMessagesResult = {
|
||||
contacts: AddonMessagesMessageAreaContact[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_message_message_search_users.
|
||||
*/
|
||||
export type AddonMessagesSearchUsersResult = {
|
||||
contacts: AddonMessagesConversationMember[];
|
||||
noncontacts: AddonMessagesConversationMember[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_message_mark_message_read.
|
||||
*/
|
||||
export type AddonMessagesMarkMessageReadResult = {
|
||||
messageid: number; // The id of the message in the messages table.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_message_send_instant_messages.
|
||||
*/
|
||||
export type AddonMessagesSendInstantMessagesMessage = {
|
||||
msgid: number; // Test this to know if it succeeds: id of the created message if it succeeded, -1 when failed.
|
||||
clientmsgid?: string; // Your own id for the message.
|
||||
errormessage?: string; // Error message - if it failed.
|
||||
text?: string; // The text of the message.
|
||||
timecreated?: number; // The timecreated timestamp for the message.
|
||||
conversationid?: number; // The conversation id for this message.
|
||||
useridfrom?: number; // The user id who sent the message.
|
||||
candeletemessagesforallusers: boolean; // If the user can delete messages in the conversation for all users.
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_message_send_messages_to_conversation.
|
||||
*/
|
||||
export type AddonMessagesSendMessagesToConversationMessage = {
|
||||
id: number; // The id of the message.
|
||||
useridfrom: number; // The id of the user who sent the message.
|
||||
text: string; // The text of the message.
|
||||
timecreated: number; // The timecreated timestamp for the message.
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculated data for core_message_get_contacts.
|
||||
*/
|
||||
export type AddonMessagesGetContactsCalculatedData = {
|
||||
blocked?: AddonMessagesBlockedUser[]; // Calculated in the app. List of blocked users.
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculated data for core_message_get_conversation_messages.
|
||||
*/
|
||||
export type AddonMessagesGetConversationMessagesCalculatedData = {
|
||||
canLoadMore?: boolean; // Calculated in the app. Whether more messages can be loaded.
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculated data for message preferences.
|
||||
*/
|
||||
export type AddonMessagesMessagePreferencesCalculatedData = {
|
||||
blocknoncontacts?: number; // Calculated in the app. Based on the result of core_message_get_user_message_preferences.
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculated data for messages returned by core_message_get_messages.
|
||||
*/
|
||||
export type AddonMessagesGetMessagesMessageCalculatedData = {
|
||||
pending?: boolean; // Calculated in the app. Whether the message is pending to be sent.
|
||||
read?: number; // Calculated in the app. Whether the message has been read.
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculated data for contact for message area.
|
||||
*/
|
||||
export type AddonMessagesMessageAreaContactCalculatedData = {
|
||||
id?: number; // Calculated in the app. User ID.
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@ import { CoreSitesProvider } from '@providers/sites';
|
|||
import { CoreSyncBaseProvider } from '@classes/base-sync';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
import { AddonMessagesOfflineProvider } from './messages-offline';
|
||||
import { AddonMessagesProvider } from './messages';
|
||||
import { AddonMessagesProvider, AddonMessagesConversationFormatted } from './messages';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
|
@ -258,7 +258,7 @@ export class AddonMessagesSyncProvider extends CoreSyncBaseProvider {
|
|||
// Get conversation name and add errors to warnings array.
|
||||
return this.messagesProvider.getConversation(conversationId, false, false).catch(() => {
|
||||
// Ignore errors.
|
||||
return {};
|
||||
return <AddonMessagesConversationFormatted> {};
|
||||
}).then((conversation) => {
|
||||
errors.forEach((error) => {
|
||||
warnings.push(this.translate.instant('addon.messages.warningconversationmessagenotsent', {
|
||||
|
|
|
@ -21,7 +21,7 @@ import { CoreSitesProvider } from '@providers/sites';
|
|||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
import { coreSlideInOut } from '@classes/animations';
|
||||
import { AddonNotesProvider } from '../../providers/notes';
|
||||
import { AddonNotesProvider, AddonNotesNoteFormatted } from '../../providers/notes';
|
||||
import { AddonNotesOfflineProvider } from '../../providers/notes-offline';
|
||||
import { AddonNotesSyncProvider } from '../../providers/notes-sync';
|
||||
|
||||
|
@ -44,7 +44,7 @@ export class AddonNotesListComponent implements OnInit, OnDestroy {
|
|||
type = 'course';
|
||||
refreshIcon = 'spinner';
|
||||
syncIcon = 'spinner';
|
||||
notes: any[];
|
||||
notes: AddonNotesNoteFormatted[];
|
||||
hasOffline = false;
|
||||
notesLoaded = false;
|
||||
user: any;
|
||||
|
@ -101,21 +101,21 @@ export class AddonNotesListComponent implements OnInit, OnDestroy {
|
|||
// Ignore errors.
|
||||
}).then(() => {
|
||||
return this.notesProvider.getNotes(this.courseId, this.userId).then((notes) => {
|
||||
notes = notes[this.type + 'notes'] || [];
|
||||
const notesList: AddonNotesNoteFormatted[] = notes[this.type + 'notes'] || [];
|
||||
|
||||
return this.notesProvider.setOfflineDeletedNotes(notes, this.courseId).then((notes) => {
|
||||
return this.notesProvider.setOfflineDeletedNotes(notesList, this.courseId).then((notesList) => {
|
||||
|
||||
this.hasOffline = notes.some((note) => note.offline || note.deleted);
|
||||
this.hasOffline = notesList.some((note) => note.offline || note.deleted);
|
||||
|
||||
if (this.userId) {
|
||||
this.notes = notes;
|
||||
this.notes = notesList;
|
||||
|
||||
// Get the user profile to retrieve the user image.
|
||||
return this.userProvider.getProfile(this.userId, this.courseId, true).then((user) => {
|
||||
this.user = user;
|
||||
});
|
||||
} else {
|
||||
return this.notesProvider.getNotesUserData(notes, this.courseId).then((notes) => {
|
||||
return this.notesProvider.getNotesUserData(notesList, this.courseId).then((notes) => {
|
||||
this.notes = notes;
|
||||
});
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ export class AddonNotesListComponent implements OnInit, OnDestroy {
|
|||
}).finally(() => {
|
||||
let canDelete = this.notes && this.notes.length > 0;
|
||||
if (canDelete && this.type == 'personal') {
|
||||
canDelete = this.notes.find((note) => {
|
||||
canDelete = !!this.notes.find((note) => {
|
||||
return note.usermodified == this.currentUserId;
|
||||
});
|
||||
}
|
||||
|
@ -178,6 +178,7 @@ export class AddonNotesListComponent implements OnInit, OnDestroy {
|
|||
addNote(e: Event): void {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const modal = this.modalCtrl.create('AddonNotesAddPage', { userId: this.userId, courseId: this.courseId, type: this.type });
|
||||
modal.onDidDismiss((data) => {
|
||||
if (data && data.sent && data.type) {
|
||||
|
@ -192,6 +193,7 @@ export class AddonNotesListComponent implements OnInit, OnDestroy {
|
|||
this.typeChanged();
|
||||
}
|
||||
});
|
||||
|
||||
modal.present();
|
||||
}
|
||||
|
||||
|
@ -201,7 +203,7 @@ export class AddonNotesListComponent implements OnInit, OnDestroy {
|
|||
* @param e Click event.
|
||||
* @param note Note to delete.
|
||||
*/
|
||||
deleteNote(e: Event, note: any): void {
|
||||
deleteNote(e: Event, note: AddonNotesNoteFormatted): void {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
|
@ -226,7 +228,7 @@ export class AddonNotesListComponent implements OnInit, OnDestroy {
|
|||
* @param e Click event.
|
||||
* @param note Note to delete.
|
||||
*/
|
||||
undoDeleteNote(e: Event, note: any): void {
|
||||
undoDeleteNote(e: Event, note: AddonNotesNoteFormatted): void {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
import { AddonNotesOfflineProvider } from './notes-offline';
|
||||
import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications';
|
||||
import { CoreWSExternalWarning } from '@providers/ws';
|
||||
|
||||
/**
|
||||
* Service to handle notes.
|
||||
|
@ -119,9 +120,9 @@ export class AddonNotesProvider {
|
|||
* @return Promise resolved when added, rejected otherwise. Promise resolved doesn't mean that notes
|
||||
* have been added, the resolve param can contain errors for notes not sent.
|
||||
*/
|
||||
addNotesOnline(notes: any[], siteId?: string): Promise<any> {
|
||||
addNotesOnline(notes: any[], siteId?: string): Promise<AddonNotesCreateNotesNote[]> {
|
||||
if (!notes || !notes.length) {
|
||||
return Promise.resolve();
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
@ -142,7 +143,7 @@ export class AddonNotesProvider {
|
|||
* @return Promise resolved when deleted, rejected otherwise. Promise resolved doesn't mean that notes
|
||||
* have been deleted, the resolve param can contain errors for notes not deleted.
|
||||
*/
|
||||
deleteNote(note: any, courseId: number, siteId?: string): Promise<void> {
|
||||
deleteNote(note: AddonNotesNoteFormatted, courseId: number, siteId?: string): Promise<void> {
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
||||
if (note.offline) {
|
||||
|
@ -190,7 +191,7 @@ export class AddonNotesProvider {
|
|||
notes: noteIds
|
||||
};
|
||||
|
||||
return site.write('core_notes_delete_notes', data).then((response) => {
|
||||
return site.write('core_notes_delete_notes', data).then((response: CoreWSExternalWarning[]) => {
|
||||
// A note was deleted, invalidate the course notes.
|
||||
return this.invalidateNotes(courseId, undefined, siteId).catch(() => {
|
||||
// Ignore errors.
|
||||
|
@ -288,7 +289,9 @@ export class AddonNotesProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise to be resolved when the notes are retrieved.
|
||||
*/
|
||||
getNotes(courseId: number, userId?: number, ignoreCache?: boolean, onlyOnline?: boolean, siteId?: string): Promise<any> {
|
||||
getNotes(courseId: number, userId?: number, ignoreCache?: boolean, onlyOnline?: boolean, siteId?: string)
|
||||
: Promise<AddonNotesGetCourseNotesResult> {
|
||||
|
||||
this.logger.debug('Get notes for course ' + courseId);
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
@ -310,7 +313,7 @@ export class AddonNotesProvider {
|
|||
preSets.emergencyCache = false;
|
||||
}
|
||||
|
||||
return site.read('core_notes_get_course_notes', data, preSets).then((notes) => {
|
||||
return site.read('core_notes_get_course_notes', data, preSets).then((notes: AddonNotesGetCourseNotesResult) => {
|
||||
if (onlyOnline) {
|
||||
return notes;
|
||||
}
|
||||
|
@ -339,9 +342,11 @@ export class AddonNotesProvider {
|
|||
* @param notes Array of notes.
|
||||
* @param courseId ID of the course the notes belong to.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return [description]
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
setOfflineDeletedNotes(notes: any[], courseId: number, siteId?: string): Promise<any> {
|
||||
setOfflineDeletedNotes(notes: AddonNotesNoteFormatted[], courseId: number, siteId?: string)
|
||||
: Promise<AddonNotesNoteFormatted[]> {
|
||||
|
||||
return this.notesOffline.getCourseDeletedNotes(courseId, siteId).then((deletedNotes) => {
|
||||
notes.forEach((note) => {
|
||||
note.deleted = deletedNotes.some((n) => n.noteid == note.id);
|
||||
|
@ -358,7 +363,7 @@ export class AddonNotesProvider {
|
|||
* @param courseId ID of the course the notes belong to.
|
||||
* @return Promise always resolved. Resolve param is the formatted notes.
|
||||
*/
|
||||
getNotesUserData(notes: any[], courseId: number): Promise<any> {
|
||||
getNotesUserData(notes: AddonNotesNoteFormatted[], courseId: number): Promise<AddonNotesNoteFormatted[]> {
|
||||
const promises = notes.map((note) => {
|
||||
// Get the user profile to retrieve the user image.
|
||||
return this.userProvider.getProfile(note.userid, note.courseid, true).then((user) => {
|
||||
|
@ -400,7 +405,7 @@ export class AddonNotesProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logView(courseId: number, userId?: number, siteId?: string): Promise<any> {
|
||||
logView(courseId: number, userId?: number, siteId?: string): Promise<AddonNotesViewNotesResult> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const params = {
|
||||
courseid: courseId,
|
||||
|
@ -413,3 +418,57 @@ export class AddonNotesProvider {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Note data returned by core_notes_get_course_notes.
|
||||
*/
|
||||
export type AddonNotesNote = {
|
||||
id: number; // Id of this note.
|
||||
courseid: number; // Id of the course.
|
||||
userid: number; // User id.
|
||||
content: string; // The content text formated.
|
||||
format: number; // Content format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||
created: number; // Time created (timestamp).
|
||||
lastmodified: number; // Time of last modification (timestamp).
|
||||
usermodified: number; // User id of the creator of this note.
|
||||
publishstate: string; // State of the note (i.e. draft, public, site).
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_notes_get_course_notes.
|
||||
*/
|
||||
export type AddonNotesGetCourseNotesResult = {
|
||||
sitenotes?: AddonNotesNote[]; // Site notes.
|
||||
coursenotes?: AddonNotesNote[]; // Couse notes.
|
||||
personalnotes?: AddonNotesNote[]; // Personal notes.
|
||||
canmanagesystemnotes?: boolean; // Whether the user can manage notes at system level.
|
||||
canmanagecoursenotes?: boolean; // Whether the user can manage notes at the given course.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Note returned by WS core_notes_create_notes.
|
||||
*/
|
||||
export type AddonNotesCreateNotesNote = {
|
||||
clientnoteid?: string; // Your own id for the note.
|
||||
noteid: number; // ID of the created note when successful, -1 when failed.
|
||||
errormessage?: string; // Error message - if failed.
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_notes_view_notes.
|
||||
*/
|
||||
export type AddonNotesViewNotesResult = {
|
||||
status: boolean; // Status: true if success.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Notes with some calculated data.
|
||||
*/
|
||||
export type AddonNotesNoteFormatted = AddonNotesNote & {
|
||||
offline?: boolean; // Calculated in the app. Whether it's an offline note.
|
||||
deleted?: boolean; // Calculated in the app. Whether the note was deleted in offline.
|
||||
userfullname?: string; // Calculated in the app. Full name of the user the note refers to.
|
||||
userprofileimageurl?: string; // Calculated in the app. Avatar url of the user the note refers to.
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@ import { CoreTextUtilsProvider } from '@providers/utils/text';
|
|||
import { CoreEventsProvider, CoreEventObserver } from '@providers/events';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { AddonNotificationsProvider } from '../../providers/notifications';
|
||||
import { AddonNotificationsProvider, AddonNotificationsAnyNotification } from '../../providers/notifications';
|
||||
import { AddonNotificationsHelperProvider } from '../../providers/helper';
|
||||
import { CorePushNotificationsDelegate } from '@core/pushnotifications/providers/delegate';
|
||||
|
||||
|
@ -34,7 +34,7 @@ import { CorePushNotificationsDelegate } from '@core/pushnotifications/providers
|
|||
})
|
||||
export class AddonNotificationsListPage {
|
||||
|
||||
notifications = [];
|
||||
notifications: AddonNotificationsAnyNotification[] = [];
|
||||
notificationsLoaded = false;
|
||||
canLoadMore = false;
|
||||
loadMoreError = false;
|
||||
|
@ -130,11 +130,12 @@ export class AddonNotificationsListPage {
|
|||
*
|
||||
* @param notifications Array of notification objects.
|
||||
*/
|
||||
protected markNotificationsAsRead(notifications: any[]): void {
|
||||
protected markNotificationsAsRead(notifications: AddonNotificationsAnyNotification[]): void {
|
||||
|
||||
let promise;
|
||||
|
||||
if (notifications.length > 0) {
|
||||
const promises = notifications.map((notification) => {
|
||||
const promises: Promise<any>[] = notifications.map((notification) => {
|
||||
if (notification.read) {
|
||||
// Already read, don't mark it.
|
||||
return Promise.resolve();
|
||||
|
@ -202,7 +203,7 @@ export class AddonNotificationsListPage {
|
|||
*
|
||||
* @param notification The notification object.
|
||||
*/
|
||||
protected formatText(notification: any): void {
|
||||
protected formatText(notification: AddonNotificationsAnyNotification): void {
|
||||
const text = notification.mobiletext.replace(/-{4,}/ig, '');
|
||||
notification.mobiletext = this.textUtils.replaceNewLines(text, '<br>');
|
||||
}
|
||||
|
|
|
@ -14,7 +14,11 @@
|
|||
|
||||
import { Component, OnDestroy, Optional } from '@angular/core';
|
||||
import { IonicPage, NavController } from 'ionic-angular';
|
||||
import { AddonNotificationsProvider } from '../../providers/notifications';
|
||||
import {
|
||||
AddonNotificationsProvider, AddonNotificationsNotificationPreferences, AddonNotificationsNotificationPreferencesProcessor,
|
||||
AddonNotificationsNotificationPreferencesComponent, AddonNotificationsNotificationPreferencesNotification,
|
||||
AddonNotificationsNotificationPreferencesNotificationProcessorState
|
||||
} from '../../providers/notifications';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreSettingsHelper } from '@core/settings/providers/helper';
|
||||
|
@ -38,10 +42,10 @@ import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
|||
export class AddonNotificationsSettingsPage implements OnDestroy {
|
||||
protected updateTimeout: any;
|
||||
|
||||
components: any[];
|
||||
preferences: any;
|
||||
components: AddonNotificationsNotificationPreferencesComponent[];
|
||||
preferences: AddonNotificationsNotificationPreferences;
|
||||
preferencesLoaded: boolean;
|
||||
currentProcessor: any;
|
||||
currentProcessor: AddonNotificationsNotificationPreferencesProcessorFormatted;
|
||||
notifPrefsEnabled: boolean;
|
||||
canChangeSound: boolean;
|
||||
notificationSound: boolean;
|
||||
|
@ -99,7 +103,7 @@ export class AddonNotificationsSettingsPage implements OnDestroy {
|
|||
// Get display data of message output handlers (thery are displayed in the context menu),
|
||||
this.processorHandlers = [];
|
||||
if (preferences.processors) {
|
||||
preferences.processors.forEach((processor) => {
|
||||
preferences.processors.forEach((processor: AddonNotificationsNotificationPreferencesProcessorFormatted) => {
|
||||
processor.supported = this.messageOutputDelegate.hasHandler(processor.name, true);
|
||||
if (processor.hassettings && processor.supported) {
|
||||
this.processorHandlers.push(this.messageOutputDelegate.getDisplayData(processor));
|
||||
|
@ -118,7 +122,7 @@ export class AddonNotificationsSettingsPage implements OnDestroy {
|
|||
*
|
||||
* @param processor Processor object.
|
||||
*/
|
||||
protected loadProcessor(processor: any): void {
|
||||
protected loadProcessor(processor: AddonNotificationsNotificationPreferencesProcessorFormatted): void {
|
||||
if (!processor) {
|
||||
return;
|
||||
}
|
||||
|
@ -191,8 +195,9 @@ export class AddonNotificationsSettingsPage implements OnDestroy {
|
|||
* @param notification Notification object.
|
||||
* @param state State name, ['loggedin', 'loggedoff'].
|
||||
*/
|
||||
changePreference(notification: any, state: string): void {
|
||||
const processorState = notification.currentProcessor[state];
|
||||
changePreference(notification: AddonNotificationsNotificationPreferencesNotificationFormatted, state: string): void {
|
||||
const processorState: AddonNotificationsNotificationPreferencesNotificationProcessorStateFormatted =
|
||||
notification.currentProcessor[state];
|
||||
const preferenceName = notification.preferencekey + '_' + processorState.name;
|
||||
let value;
|
||||
|
||||
|
@ -211,6 +216,7 @@ export class AddonNotificationsSettingsPage implements OnDestroy {
|
|||
}
|
||||
|
||||
processorState.updating = true;
|
||||
|
||||
this.userProvider.updateUserPreference(preferenceName, value).then(() => {
|
||||
// Update the preferences since they were modified.
|
||||
this.updatePreferencesAfterDelay();
|
||||
|
@ -264,3 +270,25 @@ export class AddonNotificationsSettingsPage implements OnDestroy {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notification preferences notification with some calculated data.
|
||||
*/
|
||||
type AddonNotificationsNotificationPreferencesNotificationFormatted = AddonNotificationsNotificationPreferencesNotification & {
|
||||
currentProcessor?: AddonNotificationsNotificationPreferencesProcessorFormatted; // Calculated in the app. Current processor.
|
||||
};
|
||||
|
||||
/**
|
||||
* Notification preferences processor with some calculated data.
|
||||
*/
|
||||
type AddonNotificationsNotificationPreferencesProcessorFormatted = AddonNotificationsNotificationPreferencesProcessor & {
|
||||
supported?: boolean; // Calculated in the app. Whether the processor is supported in the app.
|
||||
};
|
||||
|
||||
/**
|
||||
* State in notification processor in notification preferences component with some calculated data.
|
||||
*/
|
||||
type AddonNotificationsNotificationPreferencesNotificationProcessorStateFormatted =
|
||||
AddonNotificationsNotificationPreferencesNotificationProcessorState & {
|
||||
updating?: boolean; // Calculated in the app. Whether the state is being updated.
|
||||
};
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { AddonNotificationsProvider } from './notifications';
|
||||
import {
|
||||
AddonNotificationsProvider, AddonNotificationsAnyNotification, AddonNotificationsGetMessagesMessage
|
||||
} from './notifications';
|
||||
|
||||
/**
|
||||
* Service that provides some helper functions for notifications.
|
||||
|
@ -37,7 +39,7 @@ export class AddonNotificationsHelperProvider {
|
|||
* @return Promise resolved with notifications and if can load more.
|
||||
*/
|
||||
getNotifications(notifications: any[], limit?: number, toDisplay: boolean = true, forceCache?: boolean, ignoreCache?: boolean,
|
||||
siteId?: string): Promise<{notifications: any[], canLoadMore: boolean}> {
|
||||
siteId?: string): Promise<{notifications: AddonNotificationsAnyNotification[], canLoadMore: boolean}> {
|
||||
|
||||
notifications = notifications || [];
|
||||
limit = limit || AddonNotificationsProvider.LIST_LIMIT;
|
||||
|
@ -80,7 +82,7 @@ export class AddonNotificationsHelperProvider {
|
|||
promise = Promise.resolve(unread);
|
||||
}
|
||||
|
||||
return promise.then((notifications) => {
|
||||
return promise.then((notifications: AddonNotificationsGetMessagesMessage[]) => {
|
||||
return {
|
||||
notifications: notifications,
|
||||
canLoadMore: notifications.length >= limit
|
||||
|
|
|
@ -20,8 +20,9 @@ import { CoreTextUtilsProvider } from '@providers/utils/text';
|
|||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
import { CoreEmulatorHelperProvider } from '@core/emulator/providers/helper';
|
||||
import { AddonMessagesProvider } from '@addon/messages/providers/messages';
|
||||
import { AddonMessagesProvider, AddonMessagesMarkMessageReadResult } from '@addon/messages/providers/messages';
|
||||
import { CoreSite } from '@classes/site';
|
||||
import { CoreWSExternalWarning } from '@providers/ws';
|
||||
|
||||
/**
|
||||
* Service to handle notifications.
|
||||
|
@ -51,14 +52,13 @@ export class AddonNotificationsProvider {
|
|||
* @param read Whether the notifications are read or unread.
|
||||
* @return Promise resolved with notifications.
|
||||
*/
|
||||
protected formatNotificationsData(notifications: any[], read?: boolean): Promise<any> {
|
||||
protected formatNotificationsData(notifications: AddonNotificationsAnyNotification[], read?: boolean): Promise<any> {
|
||||
|
||||
const promises = notifications.map((notification) => {
|
||||
|
||||
// Set message to show.
|
||||
if (notification.component && notification.component == 'mod_forum') {
|
||||
notification.mobiletext = notification.smallmessage;
|
||||
} else if (notification.component && notification.component == 'moodle' && notification.name == 'insights') {
|
||||
notification.mobiletext = notification.fullmessagehtml;
|
||||
} else {
|
||||
notification.mobiletext = notification.fullmessage;
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ export class AddonNotificationsProvider {
|
|||
* @param siteId Site ID. If not defined, use current site.
|
||||
* @return Promise resolved with the notification preferences.
|
||||
*/
|
||||
getNotificationPreferences(siteId?: string): Promise<any> {
|
||||
getNotificationPreferences(siteId?: string): Promise<AddonNotificationsNotificationPreferences> {
|
||||
this.logger.debug('Get notification preferences');
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
@ -126,7 +126,9 @@ export class AddonNotificationsProvider {
|
|||
updateFrequency: CoreSite.FREQUENCY_SOMETIMES
|
||||
};
|
||||
|
||||
return site.read('core_message_get_user_notification_preferences', {}, preSets).then((data) => {
|
||||
return site.read('core_message_get_user_notification_preferences', {}, preSets)
|
||||
.then((data: AddonNotificationsGetUserNotificationPreferencesResult) => {
|
||||
|
||||
return data.preferences;
|
||||
});
|
||||
});
|
||||
|
@ -154,7 +156,7 @@ export class AddonNotificationsProvider {
|
|||
* @return Promise resolved with notifications.
|
||||
*/
|
||||
getNotifications(read: boolean, limitFrom: number, limitNumber: number = 0, toDisplay: boolean = true,
|
||||
forceCache?: boolean, ignoreCache?: boolean, siteId?: string): Promise<any[]> {
|
||||
forceCache?: boolean, ignoreCache?: boolean, siteId?: string): Promise<AddonNotificationsGetMessagesMessage[]> {
|
||||
limitNumber = limitNumber || AddonNotificationsProvider.LIST_LIMIT;
|
||||
this.logger.debug('Get ' + (read ? 'read' : 'unread') + ' notifications from ' + limitFrom + '. Limit: ' + limitNumber);
|
||||
|
||||
|
@ -176,7 +178,7 @@ export class AddonNotificationsProvider {
|
|||
};
|
||||
|
||||
// Get unread notifications.
|
||||
return site.read('core_message_get_messages', data, preSets).then((response) => {
|
||||
return site.read('core_message_get_messages', data, preSets).then((response: AddonNotificationsGetMessagesResult) => {
|
||||
if (response.messages) {
|
||||
const notifications = response.messages;
|
||||
|
||||
|
@ -209,7 +211,7 @@ export class AddonNotificationsProvider {
|
|||
* @since 3.2
|
||||
*/
|
||||
getPopupNotifications(offset: number, limit?: number, toDisplay: boolean = true, forceCache?: boolean, ignoreCache?: boolean,
|
||||
siteId?: string): Promise<{notifications: any[], canLoadMore: boolean}> {
|
||||
siteId?: string): Promise<{notifications: AddonNotificationsPopupNotificationFormatted[], canLoadMore: boolean}> {
|
||||
|
||||
limit = limit || AddonNotificationsProvider.LIST_LIMIT;
|
||||
|
||||
|
@ -230,17 +232,17 @@ export class AddonNotificationsProvider {
|
|||
};
|
||||
|
||||
// Get notifications.
|
||||
return site.read('message_popup_get_popup_notifications', data, preSets).then((response) => {
|
||||
return site.read('message_popup_get_popup_notifications', data, preSets)
|
||||
.then((response: AddonNotificationsGetPopupNotificationsResult) => {
|
||||
|
||||
if (response.notifications) {
|
||||
const result: any = {
|
||||
canLoadMore: response.notifications.length > limit
|
||||
},
|
||||
notifications = response.notifications.slice(0, limit);
|
||||
const result = {
|
||||
canLoadMore: response.notifications.length > limit,
|
||||
notifications: response.notifications.slice(0, limit)
|
||||
};
|
||||
|
||||
result.notifications = notifications;
|
||||
|
||||
return this.formatNotificationsData(notifications).then(() => {
|
||||
const first = notifications[0];
|
||||
return this.formatNotificationsData(result.notifications).then(() => {
|
||||
const first = result.notifications[0];
|
||||
|
||||
if (this.appProvider.isDesktop() && toDisplay && offset === 0 && first && !first.read) {
|
||||
// Store the last received notification. Don't block the user for this.
|
||||
|
@ -269,7 +271,7 @@ export class AddonNotificationsProvider {
|
|||
* @return Promise resolved with notifications.
|
||||
*/
|
||||
getReadNotifications(limitFrom: number, limitNumber: number, toDisplay: boolean = true,
|
||||
forceCache?: boolean, ignoreCache?: boolean, siteId?: string): Promise<any[]> {
|
||||
forceCache?: boolean, ignoreCache?: boolean, siteId?: string): Promise<AddonNotificationsGetMessagesMessage[]> {
|
||||
return this.getNotifications(true, limitFrom, limitNumber, toDisplay, forceCache, ignoreCache, siteId);
|
||||
}
|
||||
|
||||
|
@ -285,7 +287,7 @@ export class AddonNotificationsProvider {
|
|||
* @return Promise resolved with notifications.
|
||||
*/
|
||||
getUnreadNotifications(limitFrom: number, limitNumber: number, toDisplay: boolean = true,
|
||||
forceCache?: boolean, ignoreCache?: boolean, siteId?: string): Promise<any[]> {
|
||||
forceCache?: boolean, ignoreCache?: boolean, siteId?: string): Promise<AddonNotificationsGetMessagesMessage[]> {
|
||||
return this.getNotifications(false, limitFrom, limitNumber, toDisplay, forceCache, ignoreCache, siteId);
|
||||
}
|
||||
|
||||
|
@ -349,7 +351,7 @@ export class AddonNotificationsProvider {
|
|||
* @return Resolved when done.
|
||||
* @since 3.2
|
||||
*/
|
||||
markAllNotificationsAsRead(): Promise<any> {
|
||||
markAllNotificationsAsRead(): Promise<boolean> {
|
||||
const params = {
|
||||
useridto: this.sitesProvider.getCurrentSiteUserId()
|
||||
};
|
||||
|
@ -362,10 +364,12 @@ export class AddonNotificationsProvider {
|
|||
*
|
||||
* @param notificationId ID of notification to mark as read
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Resolved when done.
|
||||
* @return Promise resolved when done.
|
||||
* @since 3.5
|
||||
*/
|
||||
markNotificationRead(notificationId: number, siteId?: string): Promise<any> {
|
||||
markNotificationRead(notificationId: number, siteId?: string)
|
||||
: Promise<AddonNotificationsMarkNotificationReadResult | AddonMessagesMarkMessageReadResult> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
||||
if (site.wsAvailable('core_message_mark_notification_read')) {
|
||||
|
@ -436,3 +440,179 @@ export class AddonNotificationsProvider {
|
|||
return this.sitesProvider.wsAvailableInCurrentSite('core_message_get_user_notification_preferences');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Preferences returned by core_message_get_user_notification_preferences.
|
||||
*/
|
||||
export type AddonNotificationsNotificationPreferences = {
|
||||
userid: number; // User id.
|
||||
disableall: number | boolean; // Whether all the preferences are disabled.
|
||||
processors: AddonNotificationsNotificationPreferencesProcessor[]; // Config form values.
|
||||
components: AddonNotificationsNotificationPreferencesComponent[]; // Available components.
|
||||
};
|
||||
|
||||
/**
|
||||
* Processor in notification preferences.
|
||||
*/
|
||||
export type AddonNotificationsNotificationPreferencesProcessor = {
|
||||
displayname: string; // Display name.
|
||||
name: string; // Processor name.
|
||||
hassettings: boolean; // Whether has settings.
|
||||
contextid: number; // Context id.
|
||||
userconfigured: number; // Whether is configured by the user.
|
||||
};
|
||||
|
||||
/**
|
||||
* Component in notification preferences.
|
||||
*/
|
||||
export type AddonNotificationsNotificationPreferencesComponent = {
|
||||
displayname: string; // Display name.
|
||||
notifications: AddonNotificationsNotificationPreferencesNotification[]; // List of notificaitons for the component.
|
||||
};
|
||||
|
||||
/**
|
||||
* Notification processor in notification preferences component.
|
||||
*/
|
||||
export type AddonNotificationsNotificationPreferencesNotification = {
|
||||
displayname: string; // Display name.
|
||||
preferencekey: string; // Preference key.
|
||||
processors: AddonNotificationsNotificationPreferencesNotificationProcessor[]; // Processors values for this notification.
|
||||
};
|
||||
|
||||
/**
|
||||
* Notification processor in notification preferences component.
|
||||
*/
|
||||
export type AddonNotificationsNotificationPreferencesNotificationProcessor = {
|
||||
displayname: string; // Display name.
|
||||
name: string; // Processor name.
|
||||
locked: boolean; // Is locked by admin?.
|
||||
lockedmessage?: string; // Text to display if locked.
|
||||
userconfigured: number; // Is configured?.
|
||||
loggedin: AddonNotificationsNotificationPreferencesNotificationProcessorState;
|
||||
loggedoff: AddonNotificationsNotificationPreferencesNotificationProcessorState;
|
||||
};
|
||||
|
||||
/**
|
||||
* State in notification processor in notification preferences component.
|
||||
*/
|
||||
export type AddonNotificationsNotificationPreferencesNotificationProcessorState = {
|
||||
name: string; // Name.
|
||||
displayname: string; // Display name.
|
||||
checked: boolean; // Is checked?.
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_message_get_messages.
|
||||
*/
|
||||
export type AddonNotificationsGetMessagesResult = {
|
||||
messages: AddonNotificationsGetMessagesMessage[];
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Message data returned by core_message_get_messages.
|
||||
*/
|
||||
export type AddonNotificationsGetMessagesMessage = {
|
||||
id: number; // Message id.
|
||||
useridfrom: number; // User from id.
|
||||
useridto: number; // User to id.
|
||||
subject: string; // The message subject.
|
||||
text: string; // The message text formated.
|
||||
fullmessage: string; // The message.
|
||||
fullmessageformat: number; // Fullmessage format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||
fullmessagehtml: string; // The message in html.
|
||||
smallmessage: string; // The shorten message.
|
||||
notification: number; // Is a notification?.
|
||||
contexturl: string; // Context URL.
|
||||
contexturlname: string; // Context URL link name.
|
||||
timecreated: number; // Time created.
|
||||
timeread: number; // Time read.
|
||||
usertofullname: string; // User to full name.
|
||||
userfromfullname: string; // User from full name.
|
||||
component?: string; // @since 3.7. The component that generated the notification.
|
||||
eventtype?: string; // @since 3.7. The type of notification.
|
||||
customdata?: any; // @since 3.7. Custom data to be passed to the message processor.
|
||||
};
|
||||
|
||||
/**
|
||||
* Message data returned by core_message_get_messages with some calculated data.
|
||||
*/
|
||||
export type AddonNotificationsGetMessagesMessageFormatted =
|
||||
AddonNotificationsGetMessagesMessage & AddonNotificationsNotificationCalculatedData;
|
||||
|
||||
/**
|
||||
* Result of WS message_popup_get_popup_notifications.
|
||||
*/
|
||||
export type AddonNotificationsGetPopupNotificationsResult = {
|
||||
notifications: AddonNotificationsPopupNotification[];
|
||||
unreadcount: number; // The number of unread message for the given user.
|
||||
};
|
||||
|
||||
/**
|
||||
* Notification returned by message_popup_get_popup_notifications.
|
||||
*/
|
||||
export type AddonNotificationsPopupNotification = {
|
||||
id: number; // Notification id (this is not guaranteed to be unique within this result set).
|
||||
useridfrom: number; // User from id.
|
||||
useridto: number; // User to id.
|
||||
subject: string; // The notification subject.
|
||||
shortenedsubject: string; // The notification subject shortened with ellipsis.
|
||||
text: string; // The message text formated.
|
||||
fullmessage: string; // The message.
|
||||
fullmessageformat: number; // Fullmessage format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||
fullmessagehtml: string; // The message in html.
|
||||
smallmessage: string; // The shorten message.
|
||||
contexturl: string; // Context URL.
|
||||
contexturlname: string; // Context URL link name.
|
||||
timecreated: number; // Time created.
|
||||
timecreatedpretty: string; // Time created in a pretty format.
|
||||
timeread: number; // Time read.
|
||||
read: boolean; // Notification read status.
|
||||
deleted: boolean; // Notification deletion status.
|
||||
iconurl: string; // URL for notification icon.
|
||||
component?: string; // The component that generated the notification.
|
||||
eventtype?: string; // The type of notification.
|
||||
customdata?: any; // @since 3.7. Custom data to be passed to the message processor.
|
||||
};
|
||||
|
||||
/**
|
||||
* Notification returned by message_popup_get_popup_notifications.
|
||||
*/
|
||||
export type AddonNotificationsPopupNotificationFormatted =
|
||||
AddonNotificationsPopupNotification & AddonNotificationsNotificationCalculatedData;
|
||||
|
||||
/**
|
||||
* Any kind of notification that can be retrieved.
|
||||
*/
|
||||
export type AddonNotificationsAnyNotification =
|
||||
AddonNotificationsPopupNotificationFormatted | AddonNotificationsGetMessagesMessageFormatted;
|
||||
|
||||
/**
|
||||
* Result of WS core_message_get_user_notification_preferences.
|
||||
*/
|
||||
export type AddonNotificationsGetUserNotificationPreferencesResult = {
|
||||
preferences: AddonNotificationsNotificationPreferences;
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of WS core_message_mark_notification_read.
|
||||
*/
|
||||
export type AddonNotificationsMarkNotificationReadResult = {
|
||||
notificationid: number; // Id of the notification.
|
||||
warnings?: CoreWSExternalWarning[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculated data for messages returned by core_message_get_messages.
|
||||
*/
|
||||
export type AddonNotificationsNotificationCalculatedData = {
|
||||
mobiletext?: string; // Calculated in the app. Text to display for the notification.
|
||||
moodlecomponent?: string; // Calculated in the app. Moodle's component.
|
||||
notif?: number; // Calculated in the app. Whether it's a notification.
|
||||
notification?: number; // Calculated in the app in some cases. Whether it's a notification.
|
||||
read?: boolean; // Calculated in the app. Whether the notifications is read.
|
||||
courseid?: number; // Calculated in the app. Course the notification belongs to.
|
||||
profileimageurlfrom?: string; // Calculated in the app. Avatar of user that sent the notification.
|
||||
userfromfullname?: string; // Calculated in the app in some cases. User from full name.
|
||||
};
|
||||
|
|
|
@ -407,3 +407,27 @@ export class CoreCommentsProvider {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data returned by comment_area_exporter.
|
||||
*/
|
||||
export type CoreCommentsArea = {
|
||||
component: string; // Component.
|
||||
commentarea: string; // Commentarea.
|
||||
itemid: number; // Itemid.
|
||||
courseid: number; // Courseid.
|
||||
contextid: number; // Contextid.
|
||||
cid: string; // Cid.
|
||||
autostart: boolean; // Autostart.
|
||||
canpost: boolean; // Canpost.
|
||||
canview: boolean; // Canview.
|
||||
count: number; // Count.
|
||||
collapsediconkey: string; // Collapsediconkey.
|
||||
displaytotalcount: boolean; // Displaytotalcount.
|
||||
displaycancel: boolean; // Displaycancel.
|
||||
fullwidth: boolean; // Fullwidth.
|
||||
linktext: string; // Linktext.
|
||||
notoggle: boolean; // Notoggle.
|
||||
template: string; // Template.
|
||||
canpostorhascomments: boolean; // Canpostorhascomments.
|
||||
};
|
||||
|
|
|
@ -1135,3 +1135,38 @@ export class CoreCourseProvider {
|
|||
}, siteId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data returned by course_summary_exporter.
|
||||
*/
|
||||
export type CoreCourseSummary = {
|
||||
id: number; // Id.
|
||||
fullname: string; // Fullname.
|
||||
shortname: string; // Shortname.
|
||||
idnumber: string; // Idnumber.
|
||||
summary: string; // Summary.
|
||||
summaryformat: number; // Summary format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
|
||||
startdate: number; // Startdate.
|
||||
enddate: number; // Enddate.
|
||||
visible: boolean; // Visible.
|
||||
fullnamedisplay: string; // Fullnamedisplay.
|
||||
viewurl: string; // Viewurl.
|
||||
courseimage: string; // Courseimage.
|
||||
progress?: number; // Progress.
|
||||
hasprogress: boolean; // Hasprogress.
|
||||
isfavourite: boolean; // Isfavourite.
|
||||
hidden: boolean; // Hidden.
|
||||
timeaccess?: number; // Timeaccess.
|
||||
showshortname: boolean; // Showshortname.
|
||||
coursecategory: string; // Coursecategory.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by course_module_summary_exporter.
|
||||
*/
|
||||
export type CoreCourseModuleSummary = {
|
||||
id: number; // Id.
|
||||
name: string; // Name.
|
||||
url?: string; // Url.
|
||||
iconurl: string; // Iconurl.
|
||||
};
|
||||
|
|
|
@ -17,74 +17,6 @@ import { TranslateService } from '@ngx-translate/core';
|
|||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Structure of a tag cloud returned by WS.
|
||||
*/
|
||||
export interface CoreTagCloud {
|
||||
tags: CoreTagCloudTag[];
|
||||
tagscount: number;
|
||||
totalcount: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Structure of a tag cloud tag returned by WS.
|
||||
*/
|
||||
export interface CoreTagCloudTag {
|
||||
name: string;
|
||||
viewurl: string;
|
||||
flag: boolean;
|
||||
isstandard: boolean;
|
||||
count: number;
|
||||
size: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Structure of a tag collection returned by WS.
|
||||
*/
|
||||
export interface CoreTagCollection {
|
||||
id: number;
|
||||
name: string;
|
||||
isdefault: boolean;
|
||||
component: string;
|
||||
sortoder: number;
|
||||
searchable: boolean;
|
||||
customurl: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Structure of a tag index returned by WS.
|
||||
*/
|
||||
export interface CoreTagIndex {
|
||||
tagid: number;
|
||||
ta: number;
|
||||
component: string;
|
||||
itemtype: string;
|
||||
nextpageurl: string;
|
||||
prevpageurl: string;
|
||||
exclusiveurl: string;
|
||||
exclusivetext: string;
|
||||
title: string;
|
||||
content: string;
|
||||
hascontent: number;
|
||||
anchor: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Structure of a tag item returned by WS.
|
||||
*/
|
||||
export interface CoreTagItem {
|
||||
id: number;
|
||||
name: string;
|
||||
rawname: string;
|
||||
isstandard: boolean;
|
||||
tagcollid: number;
|
||||
taginstanceid: number;
|
||||
taginstancecontextid: number;
|
||||
itemid: number;
|
||||
ordering: number;
|
||||
flag: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Service to handle tags.
|
||||
*/
|
||||
|
@ -343,3 +275,71 @@ export class CoreTagProvider {
|
|||
+ contextId + ':' + (recursive ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Structure of a tag cloud returned by WS.
|
||||
*/
|
||||
export type CoreTagCloud = {
|
||||
tags: CoreTagCloudTag[];
|
||||
tagscount: number;
|
||||
totalcount: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure of a tag cloud tag returned by WS.
|
||||
*/
|
||||
export type CoreTagCloudTag = {
|
||||
name: string;
|
||||
viewurl: string;
|
||||
flag: boolean;
|
||||
isstandard: boolean;
|
||||
count: number;
|
||||
size: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure of a tag collection returned by WS.
|
||||
*/
|
||||
export type CoreTagCollection = {
|
||||
id: number;
|
||||
name: string;
|
||||
isdefault: boolean;
|
||||
component: string;
|
||||
sortoder: number;
|
||||
searchable: boolean;
|
||||
customurl: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure of a tag index returned by WS.
|
||||
*/
|
||||
export type CoreTagIndex = {
|
||||
tagid: number;
|
||||
ta: number;
|
||||
component: string;
|
||||
itemtype: string;
|
||||
nextpageurl: string;
|
||||
prevpageurl: string;
|
||||
exclusiveurl: string;
|
||||
exclusivetext: string;
|
||||
title: string;
|
||||
content: string;
|
||||
hascontent: number;
|
||||
anchor: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure of a tag item returned by WS.
|
||||
*/
|
||||
export type CoreTagItem = {
|
||||
id: number;
|
||||
name: string;
|
||||
rawname: string;
|
||||
isstandard: boolean;
|
||||
tagcollid: number;
|
||||
taginstanceid: number;
|
||||
taginstancecontextid: number;
|
||||
itemid: number;
|
||||
ordering: number;
|
||||
flag: number;
|
||||
};
|
||||
|
|
|
@ -634,3 +634,21 @@ export class CoreUserProvider {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data returned by user_summary_exporter.
|
||||
*/
|
||||
export type CoreUserSummary = {
|
||||
id: number; // Id.
|
||||
email: string; // Email.
|
||||
idnumber: string; // Idnumber.
|
||||
phone1: string; // Phone1.
|
||||
phone2: string; // Phone2.
|
||||
department: string; // Department.
|
||||
institution: string; // Institution.
|
||||
fullname: string; // Fullname.
|
||||
identity: string; // Identity.
|
||||
profileurl: string; // Profileurl.
|
||||
profileimageurl: string; // Profileimageurl.
|
||||
profileimageurlsmall: string; // Profileimageurlsmall.
|
||||
};
|
||||
|
|
|
@ -81,126 +81,6 @@ export interface CoreWSAjaxPreSets {
|
|||
useGet?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Error returned by a WS call.
|
||||
*/
|
||||
export interface CoreWSError {
|
||||
/**
|
||||
* The error message.
|
||||
*/
|
||||
message: string;
|
||||
|
||||
/**
|
||||
* Name of the exception. Undefined for local errors (fake WS errors).
|
||||
*/
|
||||
exception?: string;
|
||||
|
||||
/**
|
||||
* The error code. Undefined for local errors (fake WS errors).
|
||||
*/
|
||||
errorcode?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* File upload options.
|
||||
*/
|
||||
export interface CoreWSFileUploadOptions extends FileUploadOptions {
|
||||
/**
|
||||
* The file area where to put the file. By default, 'draft'.
|
||||
*/
|
||||
fileArea?: string;
|
||||
|
||||
/**
|
||||
* Item ID of the area where to put the file. By default, 0.
|
||||
*/
|
||||
itemId?: number;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Structure of warnings returned by WS.
|
||||
*/
|
||||
export type CoreWSExternalWarning = {
|
||||
/**
|
||||
* Item.
|
||||
* @type {string}
|
||||
*/
|
||||
item?: string;
|
||||
|
||||
/**
|
||||
* Item id.
|
||||
* @type {number}
|
||||
*/
|
||||
itemid?: number;
|
||||
|
||||
/**
|
||||
* The warning code can be used by the client app to implement specific behaviour.
|
||||
* @type {string}
|
||||
*/
|
||||
warningcode: string;
|
||||
|
||||
/**
|
||||
* Untranslated english message to explain the warning.
|
||||
* @type {string}
|
||||
*/
|
||||
message: string;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure of files returned by WS.
|
||||
*/
|
||||
export type CoreWSExternalFile = {
|
||||
/**
|
||||
* File name.
|
||||
* @type {string}
|
||||
*/
|
||||
filename?: string;
|
||||
|
||||
/**
|
||||
* File path.
|
||||
* @type {string}
|
||||
*/
|
||||
filepath?: string;
|
||||
|
||||
/**
|
||||
* File size.
|
||||
* @type {number}
|
||||
*/
|
||||
filesize?: number;
|
||||
|
||||
/**
|
||||
* Downloadable file url.
|
||||
* @type {string}
|
||||
*/
|
||||
fileurl?: string;
|
||||
|
||||
/**
|
||||
* Time modified.
|
||||
* @type {number}
|
||||
*/
|
||||
timemodified?: number;
|
||||
|
||||
/**
|
||||
* File mime type.
|
||||
* @type {string}
|
||||
*/
|
||||
mimetype?: string;
|
||||
|
||||
/**
|
||||
* Whether is an external file.
|
||||
* @type {number}
|
||||
*/
|
||||
isexternalfile?: number;
|
||||
|
||||
/**
|
||||
* The repository type for external files.
|
||||
* @type {string}
|
||||
*/
|
||||
repositorytype?: string;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* This service allows performing WS calls and download/upload files.
|
||||
*/
|
||||
|
@ -948,3 +828,127 @@ export class CoreWSProvider {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error returned by a WS call.
|
||||
*/
|
||||
export interface CoreWSError {
|
||||
/**
|
||||
* The error message.
|
||||
*/
|
||||
message: string;
|
||||
|
||||
/**
|
||||
* Name of the exception. Undefined for local errors (fake WS errors).
|
||||
*/
|
||||
exception?: string;
|
||||
|
||||
/**
|
||||
* The error code. Undefined for local errors (fake WS errors).
|
||||
*/
|
||||
errorcode?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* File upload options.
|
||||
*/
|
||||
export interface CoreWSFileUploadOptions extends FileUploadOptions {
|
||||
/**
|
||||
* The file area where to put the file. By default, 'draft'.
|
||||
*/
|
||||
fileArea?: string;
|
||||
|
||||
/**
|
||||
* Item ID of the area where to put the file. By default, 0.
|
||||
*/
|
||||
itemId?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Structure of warnings returned by WS.
|
||||
*/
|
||||
export type CoreWSExternalWarning = {
|
||||
/**
|
||||
* Item.
|
||||
*/
|
||||
item?: string;
|
||||
|
||||
/**
|
||||
* Item id.
|
||||
*/
|
||||
itemid?: number;
|
||||
|
||||
/**
|
||||
* The warning code can be used by the client app to implement specific behaviour.
|
||||
*/
|
||||
warningcode: string;
|
||||
|
||||
/**
|
||||
* Untranslated english message to explain the warning.
|
||||
*/
|
||||
message: string;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure of files returned by WS.
|
||||
*/
|
||||
export type CoreWSExternalFile = {
|
||||
/**
|
||||
* File name.
|
||||
*/
|
||||
filename?: string;
|
||||
|
||||
/**
|
||||
* File path.
|
||||
*/
|
||||
filepath?: string;
|
||||
|
||||
/**
|
||||
* File size.
|
||||
*/
|
||||
filesize?: number;
|
||||
|
||||
/**
|
||||
* Downloadable file url.
|
||||
*/
|
||||
fileurl?: string;
|
||||
|
||||
/**
|
||||
* Time modified.
|
||||
*/
|
||||
timemodified?: number;
|
||||
|
||||
/**
|
||||
* File mime type.
|
||||
*/
|
||||
mimetype?: string;
|
||||
|
||||
/**
|
||||
* Whether is an external file.
|
||||
*/
|
||||
isexternalfile?: number;
|
||||
|
||||
/**
|
||||
* The repository type for external files.
|
||||
*/
|
||||
repositorytype?: string;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by date_exporter.
|
||||
*/
|
||||
export type CoreWSDate = {
|
||||
seconds: number; // Seconds.
|
||||
minutes: number; // Minutes.
|
||||
hours: number; // Hours.
|
||||
mday: number; // Mday.
|
||||
wday: number; // Wday.
|
||||
mon: number; // Mon.
|
||||
year: number; // Year.
|
||||
yday: number; // Yday.
|
||||
weekday: string; // Weekday.
|
||||
month: string; // Month.
|
||||
timestamp: number; // Timestamp.
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue