MOBILE-3018 forum: Post a copy to all groups
parent
84caaaeaa9
commit
e25306b0b2
|
@ -503,6 +503,7 @@
|
|||
"addon.mod_forum.erroremptysubject": "forum",
|
||||
"addon.mod_forum.errorgetforum": "local_moodlemobileapp",
|
||||
"addon.mod_forum.errorgetgroups": "local_moodlemobileapp",
|
||||
"addon.mod_forum.errorposttoallgroups": "local_moodlemobileapp",
|
||||
"addon.mod_forum.favouriteupdated": "forum",
|
||||
"addon.mod_forum.forumnodiscussionsyet": "local_moodlemobileapp",
|
||||
"addon.mod_forum.group": "local_moodlemobileapp",
|
||||
|
@ -520,6 +521,7 @@
|
|||
"addon.mod_forum.pinupdated": "forum",
|
||||
"addon.mod_forum.postisprivatereply": "forum",
|
||||
"addon.mod_forum.posttoforum": "forum",
|
||||
"addon.mod_forum.posttomygroups": "forum",
|
||||
"addon.mod_forum.privatereply": "forum",
|
||||
"addon.mod_forum.re": "forum",
|
||||
"addon.mod_forum.refreshdiscussions": "local_moodlemobileapp",
|
||||
|
@ -1219,6 +1221,7 @@
|
|||
"core.agelocationverification": "moodle",
|
||||
"core.ago": "message",
|
||||
"core.all": "moodle",
|
||||
"core.allgroups": "moodle",
|
||||
"core.allparticipants": "moodle",
|
||||
"core.android": "local_moodlemobileapp",
|
||||
"core.answer": "moodle",
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<ion-icon name="information-circle"></ion-icon> {{ availabilityMessage }}
|
||||
</ion-card>
|
||||
|
||||
<core-empty-box *ngIf="forum && discussions.length == 0" icon="chatbubbles" [message]="'addon.mod_forum.forumnodiscussionsyet' | translate">
|
||||
<core-empty-box *ngIf="forum && discussions.length == 0 && offlineDiscussions.length == 0" icon="chatbubbles" [message]="'addon.mod_forum.forumnodiscussionsyet' | translate">
|
||||
</core-empty-box>
|
||||
|
||||
<div text-wrap *ngIf="sortingAvailable && selectedSortOrder" ion-row padding-horizontal padding-top margin-bottom>
|
||||
|
@ -41,7 +41,7 @@
|
|||
</button>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="forum && discussions.length > 0">
|
||||
<ng-container *ngIf="forum">
|
||||
<ion-card *ngFor="let discussion of offlineDiscussions" (click)="openNewDiscussion(discussion.timecreated)" [class.addon-forum-discussion-selected]="discussion.timecreated == -selectedDiscussion">
|
||||
<ion-item text-wrap>
|
||||
<ion-avatar core-user-avatar [user]="discussion" item-start [courseId]="courseId"></ion-avatar>
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
"erroremptysubject": "Post subject cannot be empty.",
|
||||
"errorgetforum": "Error getting forum data.",
|
||||
"errorgetgroups": "Error getting group settings.",
|
||||
"errorposttoallgroups": "Could not create new discussion in all groups.",
|
||||
"favouriteupdated": "Your star option has been updated.",
|
||||
"forumnodiscussionsyet": "There are no discussions yet in this forum.",
|
||||
"group": "Group",
|
||||
|
@ -41,6 +42,7 @@
|
|||
"pinupdated": "The pin option has been updated.",
|
||||
"postisprivatereply": "This post was made privately and is not visible to all users.",
|
||||
"posttoforum": "Post to forum",
|
||||
"posttomygroups": "Post a copy to all groups",
|
||||
"privatereply": "Reply privately",
|
||||
"re": "Re:",
|
||||
"refreshdiscussions": "Refresh discussions",
|
||||
|
|
|
@ -27,9 +27,13 @@
|
|||
{{ 'addon.mod_forum.advanced' | translate }}
|
||||
</ion-item-divider>
|
||||
<ng-container *ngIf="advanced">
|
||||
<ion-item *ngIf="showGroups && groupIds.length > 1 && accessInfo.cancanposttomygroups">
|
||||
<ion-label>{{ 'addon.mod_forum.posttomygroups' | translate }}</ion-label>
|
||||
<ion-toggle [(ngModel)]="newDiscussion.postToAllGroups"></ion-toggle>
|
||||
</ion-item>
|
||||
<ion-item *ngIf="showGroups">
|
||||
<ion-label id="addon-mod-forum-groupslabel">{{ 'addon.mod_forum.group' | translate }}</ion-label>
|
||||
<ion-select [(ngModel)]="newDiscussion.groupId" aria-labelledby="addon-mod-forum-groupslabel" interface="action-sheet">
|
||||
<ion-select [(ngModel)]="newDiscussion.groupId" [disabled]="newDiscussion.postToAllGroups" aria-labelledby="addon-mod-forum-groupslabel" interface="action-sheet">
|
||||
<ion-option *ngFor="let group of groups" [value]="group.id">{{ group.name }}</ion-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
|
|
@ -53,15 +53,18 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
|
|||
forum: any;
|
||||
showForm = false;
|
||||
groups = [];
|
||||
groupIds = [];
|
||||
newDiscussion = {
|
||||
subject: '',
|
||||
message: null, // Null means empty or just white space.
|
||||
postToAllGroups: false,
|
||||
groupId: 0,
|
||||
subscribe: true,
|
||||
pin: false,
|
||||
files: []
|
||||
};
|
||||
advanced = false; // Display all form fields.
|
||||
accessInfo: any = {};
|
||||
|
||||
protected courseId: number;
|
||||
protected cmId: number;
|
||||
|
@ -146,9 +149,13 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
|
|||
return promise.then((forumGroups) => {
|
||||
if (forumGroups.length > 0) {
|
||||
this.groups = forumGroups;
|
||||
this.groupIds = forumGroups.map((group) => group.id).filter((id) => id > 0);
|
||||
// Do not override group id.
|
||||
this.newDiscussion.groupId = this.newDiscussion.groupId || forumGroups[0].id;
|
||||
this.showGroups = true;
|
||||
if (this.groupIds.length <= 1) {
|
||||
this.newDiscussion.postToAllGroups = false;
|
||||
}
|
||||
} else {
|
||||
const message = mode === CoreGroupsProvider.SEPARATEGROUPS ?
|
||||
'addon.mod_forum.cannotadddiscussionall' : 'addon.mod_forum.cannotadddiscussion';
|
||||
|
@ -159,6 +166,7 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
|
|||
}));
|
||||
} else {
|
||||
this.showGroups = false;
|
||||
this.newDiscussion.postToAllGroups = false;
|
||||
|
||||
// Use the canAddDiscussion WS to check if the user can add attachments and pin discussions.
|
||||
promises.push(this.forumProvider.canAddDiscussionToAll(this.forumId).then((response) => {
|
||||
|
@ -174,10 +182,18 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
|
|||
this.forum = forum;
|
||||
}));
|
||||
|
||||
// Get access information.
|
||||
promises.push(this.forumProvider.getAccessInformation(this.forumId).then((accessInfo) => {
|
||||
this.accessInfo = accessInfo;
|
||||
}));
|
||||
|
||||
return Promise.all(promises);
|
||||
}).then(() => {
|
||||
// If editing a discussion, get offline data.
|
||||
if (this.timeCreated && !refresh) {
|
||||
this.syncId = this.forumSync.getForumSyncId(this.forumId);
|
||||
promises.push(this.forumSync.waitForSync(this.syncId).then(() => {
|
||||
|
||||
return this.forumSync.waitForSync(this.syncId).then(() => {
|
||||
// Do not block if the scope is already destroyed.
|
||||
if (!this.isDestroyed) {
|
||||
this.syncProvider.blockOperation(AddonModForumProvider.COMPONENT, this.syncId);
|
||||
|
@ -186,7 +202,13 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
|
|||
return this.forumOffline.getNewDiscussion(this.forumId, this.timeCreated).then((discussion) => {
|
||||
this.hasOffline = true;
|
||||
discussion.options = discussion.options || {};
|
||||
this.newDiscussion.groupId = discussion.groupid ? discussion.groupid : this.newDiscussion.groupId;
|
||||
if (discussion.groupid == AddonModForumProvider.ALL_GROUPS) {
|
||||
this.newDiscussion.groupId = this.groups[0].id;
|
||||
this.newDiscussion.postToAllGroups = true;
|
||||
} else {
|
||||
this.newDiscussion.groupId = discussion.groupid;
|
||||
this.newDiscussion.postToAllGroups = false;
|
||||
}
|
||||
this.newDiscussion.subject = discussion.subject;
|
||||
this.newDiscussion.message = discussion.message;
|
||||
this.newDiscussion.subscribe = discussion.options.discussionsubscribe;
|
||||
|
@ -203,15 +225,15 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
|
|||
|
||||
return Promise.resolve(promise).then(() => {
|
||||
// Show advanced fields by default if any of them has not the default value.
|
||||
if (!this.newDiscussion.subscribe || this.newDiscussion.pin || this.newDiscussion.files.length) {
|
||||
if (!this.newDiscussion.subscribe || this.newDiscussion.pin || this.newDiscussion.files.length ||
|
||||
this.groups.length > 0 && this.newDiscussion.groupId != this.groups[0].id ||
|
||||
this.newDiscussion.postToAllGroups) {
|
||||
this.advanced = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
}).then(() => {
|
||||
if (!this.originalData) {
|
||||
// Initialize original data.
|
||||
|
@ -232,9 +254,9 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
|
|||
* Validate which of the groups returned by getActivityAllowedGroups in visible groups should be shown to post to.
|
||||
*
|
||||
* @param {any[]} forumGroups Forum groups.
|
||||
* @return {Promise<any>} Promise resolved when done.
|
||||
* @return {Promise<any[]>} Promise resolved with the list of groups.
|
||||
*/
|
||||
protected validateVisibleGroups(forumGroups: any[]): Promise<any> {
|
||||
protected validateVisibleGroups(forumGroups: any[]): Promise<any[]> {
|
||||
// We first check if the user can post to all the groups.
|
||||
return this.forumProvider.canAddDiscussionToAll(this.forumId).catch(() => {
|
||||
// The call failed, let's assume he can't.
|
||||
|
@ -331,7 +353,7 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
|
|||
if (canAdd) {
|
||||
groups.unshift({
|
||||
courseid: this.courseId,
|
||||
id: -1,
|
||||
id: AddonModForumProvider.ALL_PARTICIPANTS,
|
||||
name: this.translate.instant('core.allparticipants')
|
||||
});
|
||||
}
|
||||
|
@ -362,14 +384,14 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
|
|||
/**
|
||||
* Convenience function to update or return to discussions depending on device.
|
||||
*
|
||||
* @param {number} [discussionId] Id of the new discussion.
|
||||
* @param {number} [discussionIds] Ids of the new discussions.
|
||||
* @param {number} [discTimecreated] The time created of the discussion (if offline).
|
||||
*/
|
||||
protected returnToDiscussions(discussionId?: number, discTimecreated?: number): void {
|
||||
protected returnToDiscussions(discussionIds?: number[], discTimecreated?: number): void {
|
||||
const data: any = {
|
||||
forumId: this.forumId,
|
||||
cmId: this.cmId,
|
||||
discussionId: discussionId,
|
||||
discussionIds: discussionIds,
|
||||
discTimecreated: discTimecreated
|
||||
};
|
||||
this.eventsProvider.trigger(AddonModForumProvider.NEW_DISCUSSION_EVENT, data, this.sitesProvider.getCurrentSiteId());
|
||||
|
@ -383,6 +405,7 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
|
|||
this.newDiscussion.subject = '';
|
||||
this.newDiscussion.message = null;
|
||||
this.newDiscussion.files = [];
|
||||
this.newDiscussion.postToAllGroups = false;
|
||||
this.messageEditor.clearText();
|
||||
this.originalData = this.utils.clone(this.newDiscussion);
|
||||
|
||||
|
@ -414,13 +437,11 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
|
|||
const subject = this.newDiscussion.subject;
|
||||
let message = this.newDiscussion.message;
|
||||
const pin = this.newDiscussion.pin;
|
||||
const groupId = this.newDiscussion.groupId;
|
||||
const attachments = this.newDiscussion.files;
|
||||
const discTimecreated = this.timeCreated || Date.now();
|
||||
const options: any = {
|
||||
discussionsubscribe: !!this.newDiscussion.subscribe
|
||||
};
|
||||
let saveOffline = false;
|
||||
|
||||
if (!subject) {
|
||||
this.domUtils.showErrorModal('addon.mod_forum.erroremptysubject', true);
|
||||
|
@ -434,51 +455,29 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
|
|||
}
|
||||
|
||||
const modal = this.domUtils.showModalLoading('core.sending', true);
|
||||
let promise;
|
||||
|
||||
// Add some HTML to the message if needed.
|
||||
message = this.textUtils.formatHtmlLines(message);
|
||||
|
||||
// Upload attachments first if any.
|
||||
if (attachments.length) {
|
||||
promise = this.forumHelper.uploadOrStoreNewDiscussionFiles(this.forumId, discTimecreated, attachments, false)
|
||||
.catch(() => {
|
||||
// Cannot upload them in online, save them in offline.
|
||||
saveOffline = true;
|
||||
|
||||
return this.forumHelper.uploadOrStoreNewDiscussionFiles(this.forumId, discTimecreated, attachments, true);
|
||||
});
|
||||
} else {
|
||||
promise = Promise.resolve();
|
||||
if (pin) {
|
||||
options.discussionpinned = true;
|
||||
}
|
||||
|
||||
promise.then((attach) => {
|
||||
if (attach) {
|
||||
options.attachmentsid = attach;
|
||||
}
|
||||
if (pin) {
|
||||
options.discussionpinned = true;
|
||||
}
|
||||
const groupIds = this.newDiscussion.postToAllGroups ? this.groupIds : [this.newDiscussion.groupId];
|
||||
|
||||
if (saveOffline) {
|
||||
// Save discussion in offline.
|
||||
return this.forumOffline.addNewDiscussion(this.forumId, forumName, this.courseId, subject,
|
||||
message, options, groupId, discTimecreated).then(() => {
|
||||
// Don't return anything.
|
||||
});
|
||||
} else {
|
||||
// Try to send it to server.
|
||||
// Don't allow offline if there are attachments since they were uploaded fine.
|
||||
return this.forumProvider.addNewDiscussion(this.forumId, forumName, this.courseId, subject, message, options,
|
||||
groupId, undefined, discTimecreated, !attachments.length);
|
||||
}
|
||||
}).then((discussionId) => {
|
||||
if (discussionId) {
|
||||
this.forumHelper.addNewDiscussion(this.forumId, forumName, this.courseId, subject, message, attachments, options, groupIds,
|
||||
discTimecreated).then((discussionIds) => {
|
||||
if (discussionIds) {
|
||||
// Data sent to server, delete stored files (if any).
|
||||
this.forumHelper.deleteNewDiscussionStoredFiles(this.forumId, discTimecreated);
|
||||
}
|
||||
|
||||
this.returnToDiscussions(discussionId, discTimecreated);
|
||||
if (discussionIds && discussionIds.length < groupIds.length) {
|
||||
// Some discussions could not be created.
|
||||
this.domUtils.showErrorModalDefault(null, 'addon.mod_forum.errorposttoallgroups', true);
|
||||
}
|
||||
|
||||
this.returnToDiscussions(discussionIds, discTimecreated);
|
||||
}).catch((message) => {
|
||||
this.domUtils.showErrorModalDefault(message, 'addon.mod_forum.cannotcreatediscussion', true);
|
||||
}).finally(() => {
|
||||
|
|
|
@ -46,6 +46,9 @@ export class AddonModForumProvider {
|
|||
static SORTORDER_REPLIES_DESC = 5;
|
||||
static SORTORDER_REPLIES_ASC = 6;
|
||||
|
||||
static ALL_PARTICIPANTS = -1;
|
||||
static ALL_GROUPS = -2;
|
||||
|
||||
protected ROOT_CACHE_KEY = 'mmaModForum:';
|
||||
|
||||
constructor(private appProvider: CoreAppProvider,
|
||||
|
@ -126,62 +129,6 @@ export class AddonModForumProvider {
|
|||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new discussion.
|
||||
*
|
||||
* @param {number} forumId Forum ID.
|
||||
* @param {string} name Forum name.
|
||||
* @param {number} courseId Course ID the forum belongs to.
|
||||
* @param {string} subject New discussion's subject.
|
||||
* @param {string} message New discussion's message.
|
||||
* @param {any} [options] Options (subscribe, pin, ...).
|
||||
* @param {string} [groupId] Group this discussion belongs to.
|
||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||
* @param {number} [timeCreated] The time the discussion was created. Only used when editing discussion.
|
||||
* @param {boolean} allowOffline True if it can be stored in offline, false otherwise.
|
||||
* @return {Promise<any>} Promise resolved with discussion ID if sent online, resolved with false if stored offline.
|
||||
*/
|
||||
addNewDiscussion(forumId: number, name: string, courseId: number, subject: string, message: string, options?: any,
|
||||
groupId?: number, siteId?: string, timeCreated?: number, allowOffline?: boolean): Promise<any> {
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
||||
// Convenience function to store a message to be synchronized later.
|
||||
const storeOffline = (): Promise<any> => {
|
||||
return this.forumOffline.addNewDiscussion(forumId, name, courseId, subject, message, options,
|
||||
groupId, timeCreated, siteId).then(() => {
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
// If we are editing an offline discussion, discard previous first.
|
||||
let discardPromise;
|
||||
if (timeCreated) {
|
||||
discardPromise = this.forumOffline.deleteNewDiscussion(forumId, timeCreated, siteId);
|
||||
} else {
|
||||
discardPromise = Promise.resolve();
|
||||
}
|
||||
|
||||
return discardPromise.then(() => {
|
||||
if (!this.appProvider.isOnline() && allowOffline) {
|
||||
// App is offline, store the action.
|
||||
return storeOffline();
|
||||
}
|
||||
|
||||
return this.addNewDiscussionOnline(forumId, subject, message, options, groupId, siteId).then((id) => {
|
||||
// Success, return the discussion ID.
|
||||
return id;
|
||||
}).catch((error) => {
|
||||
if (!allowOffline || this.utils.isWebServiceError(error)) {
|
||||
// The WebService has thrown an error or offline not supported, reject.
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
// Couldn't connect to server, store in offline.
|
||||
return storeOffline();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new discussion. It will fail if offline or cannot connect.
|
||||
*
|
||||
|
@ -268,7 +215,7 @@ export class AddonModForumProvider {
|
|||
* - cancreateattachment (boolean)
|
||||
*/
|
||||
canAddDiscussionToAll(forumId: number): Promise<any> {
|
||||
return this.canAddDiscussion(forumId, -1);
|
||||
return this.canAddDiscussion(forumId, AddonModForumProvider.ALL_PARTICIPANTS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -309,6 +256,7 @@ export class AddonModForumProvider {
|
|||
|
||||
return this.groupsProvider.getActivityAllowedGroups(cmId).then((forumGroups) => {
|
||||
const strAllParts = this.translate.instant('core.allparticipants');
|
||||
const strAllGroups = this.translate.instant('core.allgroups');
|
||||
|
||||
// Turn groups into an object where each group is identified by id.
|
||||
const groups = {};
|
||||
|
@ -318,8 +266,11 @@ export class AddonModForumProvider {
|
|||
|
||||
// Format discussions.
|
||||
discussions.forEach((disc) => {
|
||||
if (disc.groupid === -1) {
|
||||
if (disc.groupid == AddonModForumProvider.ALL_PARTICIPANTS) {
|
||||
disc.groupname = strAllParts;
|
||||
} else if (disc.groupid == AddonModForumProvider.ALL_GROUPS) {
|
||||
// Offline discussions only.
|
||||
disc.groupname = strAllGroups;
|
||||
} else {
|
||||
const group = groups[disc.groupid];
|
||||
if (group) {
|
||||
|
|
|
@ -14,10 +14,12 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreFileProvider } from '@providers/file';
|
||||
import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
import { AddonModForumProvider } from './forum';
|
||||
import { AddonModForumOfflineProvider } from './offline';
|
||||
|
@ -33,9 +35,123 @@ export class AddonModForumHelperProvider {
|
|||
private uploaderProvider: CoreFileUploaderProvider,
|
||||
private timeUtils: CoreTimeUtilsProvider,
|
||||
private userProvider: CoreUserProvider,
|
||||
private appProvider: CoreAppProvider,
|
||||
private utils: CoreUtilsProvider,
|
||||
private forumProvider: AddonModForumProvider,
|
||||
private forumOffline: AddonModForumOfflineProvider) {}
|
||||
|
||||
/**
|
||||
* Add a new discussion.
|
||||
*
|
||||
* @param {number} forumId Forum ID.
|
||||
* @param {string} name Forum name.
|
||||
* @param {number} courseId Course ID the forum belongs to.
|
||||
* @param {string} subject New discussion's subject.
|
||||
* @param {string} message New discussion's message.
|
||||
* @param {any[]} [attachments] New discussion's attachments.
|
||||
* @param {any} [options] Options (subscribe, pin, ...).
|
||||
* @param {number[]} [groupIds] Groups this discussion belongs to.
|
||||
* @param {number} [timeCreated] The time the discussion was created. Only used when editing discussion.
|
||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||
* @return {Promise<number[]>} Promise resolved with ids of the created discussions or null if stored offline
|
||||
*/
|
||||
addNewDiscussion(forumId: number, name: string, courseId: number, subject: string, message: string, attachments?: any[],
|
||||
options?: any, groupIds?: number[], timeCreated?: number, siteId?: string): Promise<number[]> {
|
||||
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
groupIds = groupIds && groupIds.length > 0 ? groupIds : [0];
|
||||
|
||||
let saveOffline = false;
|
||||
const attachmentsIds = [];
|
||||
let offlineAttachments: any;
|
||||
|
||||
// Convenience function to store a message to be synchronized later.
|
||||
const storeOffline = (): Promise<number[]> => {
|
||||
// Multiple groups, the discussion is being posted to all groups.
|
||||
const groupId = groupIds.length > 1 ? AddonModForumProvider.ALL_GROUPS : groupIds[0];
|
||||
|
||||
if (offlineAttachments) {
|
||||
options.attachmentsid = offlineAttachments;
|
||||
}
|
||||
|
||||
return this.forumOffline.addNewDiscussion(forumId, name, courseId, subject, message, options,
|
||||
groupId, timeCreated, siteId).then(() => {
|
||||
return null;
|
||||
});
|
||||
};
|
||||
|
||||
// First try to upload attachments, once per group.
|
||||
let promise;
|
||||
if (attachments && attachments.length > 0) {
|
||||
const promises = groupIds.map(() => {
|
||||
return this.uploadOrStoreNewDiscussionFiles(forumId, timeCreated, attachments, false).then((attach) => {
|
||||
attachmentsIds.push(attach);
|
||||
});
|
||||
});
|
||||
|
||||
promise = Promise.all(promises).catch(() => {
|
||||
// Cannot upload them in online, save them in offline.
|
||||
saveOffline = true;
|
||||
|
||||
return this.uploadOrStoreNewDiscussionFiles(forumId, timeCreated, attachments, true).then((attach) => {
|
||||
offlineAttachments = attach;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
promise = Promise.resolve();
|
||||
}
|
||||
|
||||
return promise.then(() => {
|
||||
// If we are editing an offline discussion, discard previous first.
|
||||
let discardPromise;
|
||||
if (timeCreated) {
|
||||
discardPromise = this.forumOffline.deleteNewDiscussion(forumId, timeCreated, siteId);
|
||||
} else {
|
||||
discardPromise = Promise.resolve();
|
||||
}
|
||||
|
||||
return discardPromise.then(() => {
|
||||
if (saveOffline || !this.appProvider.isOnline()) {
|
||||
return storeOffline();
|
||||
}
|
||||
|
||||
const errors = [];
|
||||
const discussionIds = [];
|
||||
|
||||
const promises = groupIds.map((groupId, index) => {
|
||||
const grouOptions = this.utils.clone(options);
|
||||
if (attachmentsIds[index]) {
|
||||
grouOptions.attachmentsid = attachmentsIds[index];
|
||||
}
|
||||
|
||||
return this.forumProvider.addNewDiscussionOnline(forumId, subject, message, grouOptions, groupId, siteId)
|
||||
.then((discussionId) => {
|
||||
discussionIds.push(discussionId);
|
||||
}).catch((error) => {
|
||||
errors.push(error);
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
if (errors.length == groupIds.length) {
|
||||
// All requests have failed.
|
||||
for (let i = 0; i < errors.length; i++) {
|
||||
if (this.utils.isWebServiceError(errors[i]) || attachments.length > 0) {
|
||||
// The WebService has thrown an error or offline not supported, reject.
|
||||
return Promise.reject(errors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't connect to server, store offline.
|
||||
return storeOffline();
|
||||
}
|
||||
|
||||
return discussionIds;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert offline reply to online format in order to be compatible with them.
|
||||
*
|
||||
|
|
|
@ -16,6 +16,7 @@ import { Injectable } from '@angular/core';
|
|||
import { CoreFileProvider } from '@providers/file';
|
||||
import { CoreSitesProvider, CoreSiteSchema } from '@providers/sites';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { AddonModForumProvider } from './forum';
|
||||
|
||||
/**
|
||||
* Service to handle offline forum.
|
||||
|
@ -248,7 +249,7 @@ export class AddonModForumOfflineProvider {
|
|||
subject: subject,
|
||||
message: message,
|
||||
options: JSON.stringify(options || {}),
|
||||
groupid: groupId || -1,
|
||||
groupid: groupId || AddonModForumProvider.ALL_PARTICIPANTS,
|
||||
userid: userId || site.getUserId(),
|
||||
timecreated: timeCreated || new Date().getTime()
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@ import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploa
|
|||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreGroupsProvider } from '@providers/groups';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreSyncProvider } from '@providers/sync';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
|
@ -46,6 +47,7 @@ export class AddonModForumSyncProvider extends CoreSyncBaseProvider {
|
|||
appProvider: CoreAppProvider,
|
||||
courseProvider: CoreCourseProvider,
|
||||
private eventsProvider: CoreEventsProvider,
|
||||
private groupsProvider: CoreGroupsProvider,
|
||||
loggerProvider: CoreLoggerProvider,
|
||||
sitesProvider: CoreSitesProvider,
|
||||
syncProvider: CoreSyncProvider,
|
||||
|
@ -222,38 +224,57 @@ export class AddonModForumSyncProvider extends CoreSyncBaseProvider {
|
|||
const promises = [];
|
||||
|
||||
discussions.forEach((data) => {
|
||||
data.options = data.options || {};
|
||||
let groupsPromise;
|
||||
if (data.groupid == AddonModForumProvider.ALL_GROUPS) {
|
||||
// Fetch all group ids.
|
||||
groupsPromise = this.forumProvider.getForumById(data.courseid, data.forumid, siteId).then((forum) => {
|
||||
return this.groupsProvider.getActivityAllowedGroups(forum.cmid).then((groups) => {
|
||||
return groups.map((group) => group.id);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
groupsPromise = Promise.resolve([data.groupid]);
|
||||
}
|
||||
|
||||
// First of all upload the attachments (if any).
|
||||
const promise = this.uploadAttachments(forumId, data, true, siteId, userId).then((itemId) => {
|
||||
// Now try to add the discussion.
|
||||
data.options.attachmentsid = itemId;
|
||||
promises.push(groupsPromise.then((groupIds) => {
|
||||
const errors = [];
|
||||
|
||||
return this.forumProvider.addNewDiscussionOnline(forumId, data.subject, data.message,
|
||||
data.options, data.groupid, siteId);
|
||||
});
|
||||
return Promise.all(groupIds.map((groupId) => {
|
||||
// First of all upload the attachments (if any).
|
||||
return this.uploadAttachments(forumId, data, true, siteId, userId).then((itemId) => {
|
||||
// Now try to add the discussion.
|
||||
const options = this.utils.clone(data.options || {});
|
||||
options.attachmentsid = itemId;
|
||||
|
||||
promises.push(promise.then(() => {
|
||||
result.updated = true;
|
||||
return this.forumProvider.addNewDiscussionOnline(forumId, data.subject, data.message, options,
|
||||
groupId, siteId);
|
||||
}).catch((error) => {
|
||||
errors.push(error);
|
||||
});
|
||||
})).then(() => {
|
||||
if (errors.length == groupIds.length) {
|
||||
// All requests have failed, reject if errors were not returned by WS.
|
||||
for (let i = 0; i < errors.length; i++) {
|
||||
if (!this.utils.isWebServiceError(errors[i])) {
|
||||
return Promise.reject(errors[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.deleteNewDiscussion(forumId, data.timecreated, siteId, userId);
|
||||
}).catch((error) => {
|
||||
if (this.utils.isWebServiceError(error)) {
|
||||
// The WebService has thrown an error, this means that responses cannot be submitted. Delete them.
|
||||
// All requests succeeded, some failed or all failed with a WS error.
|
||||
result.updated = true;
|
||||
|
||||
return this.deleteNewDiscussion(forumId, data.timecreated, siteId, userId).then(() => {
|
||||
// Responses deleted, add a warning.
|
||||
result.warnings.push(this.translate.instant('core.warningofflinedatadeleted', {
|
||||
component: this.componentTranslate,
|
||||
name: data.name,
|
||||
error: this.textUtils.getErrorMessageFromError(error)
|
||||
}));
|
||||
if (errors.length == groupIds.length) {
|
||||
// All requests failed with WS error.
|
||||
result.warnings.push(this.translate.instant('core.warningofflinedatadeleted', {
|
||||
component: this.componentTranslate,
|
||||
name: data.name,
|
||||
error: this.textUtils.getErrorMessageFromError(errors[0])
|
||||
}));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Couldn't connect to server, reject.
|
||||
return Promise.reject(error);
|
||||
}
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
|
|
|
@ -503,6 +503,7 @@
|
|||
"addon.mod_forum.erroremptysubject": "Post subject cannot be empty.",
|
||||
"addon.mod_forum.errorgetforum": "Error getting forum data.",
|
||||
"addon.mod_forum.errorgetgroups": "Error getting group settings.",
|
||||
"addon.mod_forum.errorposttoallgroups": "Could not create new discussion in all groups.",
|
||||
"addon.mod_forum.favouriteupdated": "Your star option has been updated.",
|
||||
"addon.mod_forum.forumnodiscussionsyet": "There are no discussions yet in this forum.",
|
||||
"addon.mod_forum.group": "Group",
|
||||
|
@ -520,6 +521,7 @@
|
|||
"addon.mod_forum.pinupdated": "The pin option has been updated.",
|
||||
"addon.mod_forum.postisprivatereply": "This post was made privately and is not visible to all users.",
|
||||
"addon.mod_forum.posttoforum": "Post to forum",
|
||||
"addon.mod_forum.posttomygroups": "Post a copy to all groups",
|
||||
"addon.mod_forum.privatereply": "Reply privately",
|
||||
"addon.mod_forum.re": "Re:",
|
||||
"addon.mod_forum.refreshdiscussions": "Refresh discussions",
|
||||
|
@ -1219,6 +1221,7 @@
|
|||
"core.agelocationverification": "Age and location verification",
|
||||
"core.ago": "{{$a}} ago",
|
||||
"core.all": "All",
|
||||
"core.allgroups": "All groups",
|
||||
"core.allparticipants": "All participants",
|
||||
"core.android": "Android",
|
||||
"core.answer": "Answer",
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
"agelocationverification": "Age and location verification",
|
||||
"ago": "{{$a}} ago",
|
||||
"all": "All",
|
||||
"allgroups": "All groups",
|
||||
"allparticipants": "All participants",
|
||||
"android": "Android",
|
||||
"answer": "Answer",
|
||||
|
|
Loading…
Reference in New Issue