diff --git a/scripts/langindex.json b/scripts/langindex.json
index 53faeef0b..76f5cc4a8 100644
--- a/scripts/langindex.json
+++ b/scripts/langindex.json
@@ -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",
diff --git a/src/addon/mod/forum/components/index/addon-mod-forum-index.html b/src/addon/mod/forum/components/index/addon-mod-forum-index.html
index bc35c9d06..0aecbb757 100644
--- a/src/addon/mod/forum/components/index/addon-mod-forum-index.html
+++ b/src/addon/mod/forum/components/index/addon-mod-forum-index.html
@@ -31,7 +31,7 @@
{{ availabilityMessage }}
-
+
@@ -41,7 +41,7 @@
- 0">
+
diff --git a/src/addon/mod/forum/lang/en.json b/src/addon/mod/forum/lang/en.json
index 5b2935e89..8cabc5750 100644
--- a/src/addon/mod/forum/lang/en.json
+++ b/src/addon/mod/forum/lang/en.json
@@ -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",
diff --git a/src/addon/mod/forum/pages/new-discussion/new-discussion.html b/src/addon/mod/forum/pages/new-discussion/new-discussion.html
index 236b8bcef..95bb6e5ce 100644
--- a/src/addon/mod/forum/pages/new-discussion/new-discussion.html
+++ b/src/addon/mod/forum/pages/new-discussion/new-discussion.html
@@ -27,9 +27,13 @@
{{ 'addon.mod_forum.advanced' | translate }}
+ 1 && accessInfo.cancanposttomygroups">
+ {{ 'addon.mod_forum.posttomygroups' | translate }}
+
+
{{ 'addon.mod_forum.group' | translate }}
-
+
{{ group.name }}
diff --git a/src/addon/mod/forum/pages/new-discussion/new-discussion.ts b/src/addon/mod/forum/pages/new-discussion/new-discussion.ts
index aaad29946..be2fb7383 100644
--- a/src/addon/mod/forum/pages/new-discussion/new-discussion.ts
+++ b/src/addon/mod/forum/pages/new-discussion/new-discussion.ts
@@ -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} Promise resolved when done.
+ * @return {Promise} Promise resolved with the list of groups.
*/
- protected validateVisibleGroups(forumGroups: any[]): Promise {
+ protected validateVisibleGroups(forumGroups: any[]): Promise {
// 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(() => {
diff --git a/src/addon/mod/forum/providers/forum.ts b/src/addon/mod/forum/providers/forum.ts
index 0f6683e11..8bdb7bffa 100644
--- a/src/addon/mod/forum/providers/forum.ts
+++ b/src/addon/mod/forum/providers/forum.ts
@@ -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} 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 {
- siteId = siteId || this.sitesProvider.getCurrentSiteId();
-
- // Convenience function to store a message to be synchronized later.
- const storeOffline = (): Promise => {
- 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 {
- 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) {
diff --git a/src/addon/mod/forum/providers/helper.ts b/src/addon/mod/forum/providers/helper.ts
index 5c568c911..fb46fab35 100644
--- a/src/addon/mod/forum/providers/helper.ts
+++ b/src/addon/mod/forum/providers/helper.ts
@@ -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} 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 {
+
+ 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 => {
+ // 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.
*
diff --git a/src/addon/mod/forum/providers/offline.ts b/src/addon/mod/forum/providers/offline.ts
index a5223f786..af6a08b11 100644
--- a/src/addon/mod/forum/providers/offline.ts
+++ b/src/addon/mod/forum/providers/offline.ts
@@ -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()
};
diff --git a/src/addon/mod/forum/providers/sync.ts b/src/addon/mod/forum/providers/sync.ts
index a829d2662..5ad34cbb6 100644
--- a/src/addon/mod/forum/providers/sync.ts
+++ b/src/addon/mod/forum/providers/sync.ts
@@ -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);
- }
+ });
}));
});
diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json
index 9a3acd3d6..311fb6fcc 100644
--- a/src/assets/lang/en.json
+++ b/src/assets/lang/en.json
@@ -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",
diff --git a/src/lang/en.json b/src/lang/en.json
index 5e594fcc6..bf2f305e5 100644
--- a/src/lang/en.json
+++ b/src/lang/en.json
@@ -4,6 +4,7 @@
"agelocationverification": "Age and location verification",
"ago": "{{$a}} ago",
"all": "All",
+ "allgroups": "All groups",
"allparticipants": "All participants",
"android": "Android",
"answer": "Answer",