MOBILE-2816 group: Use canaccessallgroups

main
Dani Palou 2019-07-26 09:14:19 +02:00
parent 916d408f65
commit 6c86998f7f
24 changed files with 110 additions and 127 deletions

View File

@ -204,8 +204,7 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
this.showNumbers = groupInfo.groups.length == 0 ||
this.sitesProvider.getCurrentSite().isVersionGreaterEqualThan('3.5');
return this.setGroup(this.group || (groupInfo.groups && groupInfo.groups[0] && groupInfo.groups[0].id) ||
0);
return this.setGroup(this.groupsProvider.validateGroupId(this.group, groupInfo));
});
}

View File

@ -898,8 +898,8 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
if (this.assign.teamsubmission) {
if (response.lastattempt.submissiongroup) {
// Get the name of the group.
promises.push(this.groupsProvider.getActivityAllowedGroups(this.assign.cmid).then((groups) => {
groups.forEach((group) => {
promises.push(this.groupsProvider.getActivityAllowedGroups(this.assign.cmid).then((result) => {
result.groups.forEach((group) => {
if (group.id == response.lastattempt.submissiongroup) {
this.lastAttempt.submissiongroupname = group.name;
}

View File

@ -128,7 +128,7 @@ export class AddonModAssignSubmissionListPage implements OnInit, OnDestroy {
return this.groupsProvider.getActivityGroupInfo(this.assign.cmid, false).then((groupInfo) => {
this.groupInfo = groupInfo;
return this.setGroup(this.groupId || (groupInfo.groups && groupInfo.groups[0] && groupInfo.groups[0].id) || 0);
return this.setGroup(this.groupsProvider.validateGroupId(this.groupId, groupInfo));
});
}).catch((error) => {
this.domUtils.showErrorModalDefault(error, 'Error getting assigment data.');

View File

@ -165,11 +165,11 @@ export class AddonModAssignHelperProvider {
}
// If no participants returned and all groups specified, get participants by groups.
return this.groupsProvider.getActivityAllowedGroupsIfEnabled(assign.cmid, undefined, siteId).then((userGroups) => {
return this.groupsProvider.getActivityGroupInfo(assign.cmid, false, undefined, siteId).then((info) => {
const promises = [],
participants = {};
userGroups.forEach((userGroup) => {
info.groups.forEach((userGroup) => {
promises.push(this.assignProvider.listParticipants(assign.id, userGroup.id, ignoreCache, siteId)
.then((parts) => {
// Do not get repeated users.

View File

@ -293,9 +293,9 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan
return this.assignProvider.getSubmissions(assign.id, true, siteId).then((data) => {
const promises = [];
if (data.canviewsubmissions) {
// Teacher, prefetch all submissions.
promises.push(this.groupsProvider.getActivityGroupInfo(assign.cmid, false, undefined, siteId).then((groupInfo) => {
promises.push(this.groupsProvider.getActivityGroupInfo(assign.cmid, false, undefined, siteId).then((groupInfo) => {
if (data.canviewsubmissions) {
// Teacher, prefetch all submissions.
const groupProms = [];
if (!groupInfo.groups || groupInfo.groups.length == 0) {
groupInfo.groups = [{id: 0}];
@ -354,8 +354,8 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan
});
return Promise.all(groupProms);
}));
}
}
}));
// Prefetch own submission, we need to do this for teachers too so the response with error is cached.
promises.push(
@ -370,9 +370,6 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan
})
);
promises.push(this.groupsProvider.activityHasGroups(assign.cmid, siteId, true));
promises.push(this.groupsProvider.getActivityAllowedGroups(assign.cmid, undefined, siteId, true));
return Promise.all(promises);
});
}

View File

@ -70,14 +70,7 @@ export class AddonModChatSessionsPage {
return this.groupsProvider.getActivityGroupInfo(this.cmId, false).then((groupInfo) => {
this.groupInfo = groupInfo;
if (groupInfo.groups && groupInfo.groups.length > 0) {
if (!groupInfo.groups.find((group) => group.id === this.groupId)) {
this.groupId = groupInfo.groups[0].id;
}
} else {
this.groupId = 0;
}
this.groupId = this.groupsProvider.validateGroupId(this.groupId, groupInfo);
return this.chatProvider.getSessions(this.chatId, this.groupId, this.showAll);
}).then((sessions) => {

View File

@ -226,16 +226,9 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
canSearch = true;
canAdd = accessData.canaddentry;
return this.groupsProvider.getActivityGroupInfo(this.data.coursemodule, accessData.canmanageentries)
.then((groupInfo) => {
return this.groupsProvider.getActivityGroupInfo(this.data.coursemodule).then((groupInfo) => {
this.groupInfo = groupInfo;
// Check selected group is accessible.
if (groupInfo && groupInfo.groups && groupInfo.groups.length > 0) {
if (!groupInfo.groups.some((group) => this.selectedGroup == group.id)) {
this.selectedGroup = groupInfo.groups[0].id;
}
}
this.selectedGroup = this.groupsProvider.validateGroupId(this.selectedGroup, groupInfo);
});
}).then(() => {
return this.dataProvider.getFields(this.data.id).then((fields) => {

View File

@ -131,16 +131,9 @@ export class AddonModDataEditPage {
return this.dataProvider.getDatabaseAccessInformation(data.id);
}).then((accessData) => {
if (this.entryId) {
return this.groupsProvider.getActivityGroupInfo(this.data.coursemodule, accessData.canmanageentries)
.then((groupInfo) => {
return this.groupsProvider.getActivityGroupInfo(this.data.coursemodule).then((groupInfo) => {
this.groupInfo = groupInfo;
// Check selected group is accessible.
if (groupInfo && groupInfo.groups && groupInfo.groups.length > 0) {
if (!groupInfo.groups.some((group) => this.selectedGroup == group.id)) {
this.selectedGroup = groupInfo.groups[0].id;
}
}
this.selectedGroup = this.groupsProvider.validateGroupId(this.selectedGroup, groupInfo);
});
}
}).then(() => {

View File

@ -149,16 +149,9 @@ export class AddonModDataEntryPage implements OnDestroy {
}).then((accessData) => {
this.access = accessData;
return this.groupsProvider.getActivityGroupInfo(this.data.coursemodule, accessData.canmanageentries)
.then((groupInfo) => {
return this.groupsProvider.getActivityGroupInfo(this.data.coursemodule).then((groupInfo) => {
this.groupInfo = groupInfo;
// Check selected group is accessible.
if (groupInfo && groupInfo.groups && groupInfo.groups.length > 0) {
if (!groupInfo.groups.some((group) => this.selectedGroup == group.id)) {
this.selectedGroup = groupInfo.groups[0].id;
}
}
this.selectedGroup = this.groupsProvider.validateGroupId(this.selectedGroup, groupInfo);
});
}).then(() => {
const actions = this.dataHelper.getActions(this.data, this.access, this.entry);

View File

@ -269,7 +269,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
return this.groupsProvider.getActivityGroupInfo(cmId).then((groupInfo) => {
this.groupInfo = groupInfo;
return this.setGroup(this.group);
return this.setGroup(this.groupsProvider.validateGroupId(this.group, groupInfo));
});
}

View File

@ -78,6 +78,7 @@ export class AddonModFeedbackNonRespondentsPage {
return this.groupsProvider.getActivityGroupInfo(this.moduleId).then((groupInfo) => {
this.groupInfo = groupInfo;
this.selectedGroup = this.groupsProvider.validateGroupId(this.selectedGroup, groupInfo);
return this.loadGroupUsers(this.selectedGroup);
}).catch((message) => {

View File

@ -99,6 +99,7 @@ export class AddonModFeedbackRespondentsPage {
return this.groupsProvider.getActivityGroupInfo(this.moduleId).then((groupInfo) => {
this.groupInfo = groupInfo;
this.selectedGroup = this.groupsProvider.validateGroupId(this.selectedGroup, groupInfo);
return this.loadGroupAttempts(this.selectedGroup);
}).catch((message) => {

View File

@ -136,14 +136,14 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
const promises = [];
if (mode === CoreGroupsProvider.SEPARATEGROUPS || mode === CoreGroupsProvider.VISIBLEGROUPS) {
promises.push(this.groupsProvider.getActivityAllowedGroups(this.cmId).then((forumGroups) => {
promises.push(this.groupsProvider.getActivityAllowedGroups(this.cmId).then((result) => {
let promise;
if (mode === CoreGroupsProvider.VISIBLEGROUPS) {
// We need to check which of the returned groups the user can post to.
promise = this.validateVisibleGroups(forumGroups);
promise = this.validateVisibleGroups(result.groups);
} else {
// WS already filters groups, no need to do it ourselves. Add "All participants" if needed.
promise = this.addAllParticipantsOption(forumGroups, true);
promise = this.addAllParticipantsOption(result.groups, true);
}
return promise.then((forumGroups) => {

View File

@ -254,13 +254,13 @@ export class AddonModForumProvider {
formatDiscussionsGroups(cmId: number, discussions: any[]): Promise<any[]> {
discussions = this.utils.clone(discussions);
return this.groupsProvider.getActivityAllowedGroups(cmId).then((forumGroups) => {
return this.groupsProvider.getActivityAllowedGroups(cmId).then((result) => {
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 = {};
forumGroups.forEach((fg) => {
result.groups.forEach((fg) => {
groups[fg.id] = fg;
});

View File

@ -255,7 +255,7 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand
}
// Activity uses groups, prefetch allowed groups.
return this.groupsProvider.getActivityAllowedGroups(forum.cmid).then((groups) => {
return this.groupsProvider.getActivityAllowedGroups(forum.cmid).then((result) => {
if (mode === CoreGroupsProvider.SEPARATEGROUPS) {
// Groups are already filtered by WS. Prefetch canAddDiscussionToAll to determine if user can pin/attach.
return this.forumProvider.canAddDiscussionToAll(forum.id).catch(() => {
@ -278,7 +278,7 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand
// The user can't post to all groups, let's check which groups he can post to.
const groupPromises = [];
groups.forEach((group) => {
result.groups.forEach((group) => {
groupPromises.push(this.forumProvider.canAddDiscussion(forum.id, group.id).catch(() => {
// Ignore errors.
}));

View File

@ -228,8 +228,8 @@ export class AddonModForumSyncProvider extends CoreSyncBaseProvider {
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);
return this.groupsProvider.getActivityAllowedGroups(forum.cmid).then((result) => {
return result.groups.map((group) => group.id);
});
});
} else {

View File

@ -223,7 +223,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
return this.groupsProvider.getActivityGroupInfo(this.module.id).then((groupInfo) => {
this.groupInfo = groupInfo;
return this.setGroup(this.group || 0);
return this.setGroup(this.groupsProvider.validateGroupId(this.group, groupInfo));
}).finally(() => {
this.reportLoaded = true;
});

View File

@ -366,11 +366,10 @@ export class AddonModLessonPrefetchHandler extends CoreCourseActivityPrefetchHan
if (accessInfo.canviewreports) {
// Prefetch reports data.
promises.push(this.groupsProvider.getActivityAllowedGroupsIfEnabled(module.id, undefined, siteId, true)
.then((groups) => {
promises.push(this.groupsProvider.getActivityGroupInfo(module.id, false, undefined, siteId, true).then((info) => {
const subPromises = [];
groups.forEach((group) => {
info.groups.forEach((group) => {
subPromises.push(this.lessonProvider.getRetakesOverview(lesson.id, group.id, false, true, siteId));
});

View File

@ -265,44 +265,34 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
this.componentId = this.module.id;
// Get real groupmode, in case it's forced by the course.
return this.groupsProvider.getActivityGroupMode(this.wiki.coursemodule).then((groupMode) => {
return this.groupsProvider.getActivityGroupInfo(this.wiki.coursemodule).then((groupInfo) => {
return this.fetchSubwikis(this.wiki.id).then(() => {
// Get the subwiki list data from the cache.
const subwikiList = this.wikiProvider.getSubwikiList(this.wiki.id);
if (groupMode === CoreGroupsProvider.SEPARATEGROUPS || groupMode === CoreGroupsProvider.VISIBLEGROUPS) {
// Get the groups available for the user.
promise = this.groupsProvider.getActivityAllowedGroups(this.wiki.coursemodule);
} else {
promise = Promise.resolve([]);
}
return promise.then((userGroups) => {
return this.fetchSubwikis(this.wiki.id).then(() => {
// Get the subwiki list data from the cache.
const subwikiList = this.wikiProvider.getSubwikiList(this.wiki.id);
if (!subwikiList) {
// Not found in cache, create a new one.
return this.createSubwikiList(userGroups);
}
this.subwikiData.count = subwikiList.count;
this.setSelectedWiki(this.subwikiId, this.userId, this.groupId);
// If nothing was selected using nav params, use the selected from cache.
if (!this.isAnySubwikiSelected()) {
this.setSelectedWiki(subwikiList.subwikiSelected, subwikiList.userSelected,
subwikiList.groupSelected);
}
this.subwikiData.subwikis = subwikiList.subwikis;
});
}).then(() => {
if (!this.isAnySubwikiSelected() || this.subwikiData.count <= 0) {
return Promise.reject(this.translate.instant('addon.mod_wiki.errornowikiavailable'));
if (!subwikiList) {
// Not found in cache, create a new one.
return this.createSubwikiList(groupInfo.groups);
}
}).then(() => {
return this.fetchWikiPage();
this.subwikiData.count = subwikiList.count;
this.setSelectedWiki(this.subwikiId, this.userId, this.groupId);
// If nothing was selected using nav params, use the selected from cache.
if (!this.isAnySubwikiSelected()) {
this.setSelectedWiki(subwikiList.subwikiSelected, subwikiList.userSelected,
subwikiList.groupSelected);
}
this.subwikiData.subwikis = subwikiList.subwikis;
});
}).then(() => {
if (!this.isAnySubwikiSelected() || this.subwikiData.count <= 0) {
return Promise.reject(this.translate.instant('addon.mod_wiki.errornowikiavailable'));
}
}).then(() => {
return this.fetchWikiPage();
});
});
}).then(() => {

View File

@ -192,12 +192,7 @@ export class AddonModWikiPrefetchHandler extends CoreCourseActivityPrefetchHandl
});
// Fetch group data.
promises.push(this.groupsProvider.getActivityGroupMode(module.id, siteId).then((groupMode) => {
if (groupMode === CoreGroupsProvider.SEPARATEGROUPS || groupMode === CoreGroupsProvider.VISIBLEGROUPS) {
// Get the groups available for the user.
return this.groupsProvider.getActivityAllowedGroups(module.id, userId, siteId);
}
}));
promises.push(this.groupsProvider.getActivityGroupInfo(module.id, false, userId, siteId));
// Fetch info to provide wiki links.
promises.push(this.wikiProvider.getWiki(courseId, module.id, false, siteId).then((wiki) => {

View File

@ -144,7 +144,7 @@
<ion-item text-wrap *ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)">
<ion-label id="addon-workshop-groupslabel" *ngIf="groupInfo.separateGroups">{{ 'core.groupsseparate' | translate }}</ion-label>
<ion-label id="addon-workshop-groupslabel" *ngIf="groupInfo.visibleGroups">{{ 'core.groupsvisible' | translate }}</ion-label>
<ion-select [(ngModel)]="selectedGroup" (ionChange)="setGroup(selectedGroup)" aria-labelledby="addon-workshop-groupslabel" interface="action-sheet">
<ion-select [(ngModel)]="group" (ionChange)="setGroup(group)" aria-labelledby="addon-workshop-groupslabel" interface="action-sheet">
<ion-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">{{groupOpt.name}}</ion-option>
</ion-select>
</ion-item>

View File

@ -201,19 +201,9 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
this.access = accessData;
if (accessData.canviewallsubmissions) {
return this.groupsProvider.getActivityGroupInfo(this.workshop.coursemodule,
accessData.canviewallsubmissions).then((groupInfo) => {
return this.groupsProvider.getActivityGroupInfo(this.workshop.coursemodule).then((groupInfo) => {
this.groupInfo = groupInfo;
// Check selected group is accessible.
if (groupInfo && groupInfo.groups && groupInfo.groups.length > 0) {
const found = groupInfo.groups.some((group) => {
return group.id == this.group;
});
if (!found) {
this.group = groupInfo.groups[0].id;
}
}
this.group = this.groupsProvider.validateGroupId(this.group, groupInfo);
});
}
}).then(() => {

View File

@ -39,6 +39,12 @@ export interface CoreGroupInfo {
* @type {boolean}
*/
visibleGroups?: boolean;
/**
* The group ID to use by default. If all participants is visible, 0 will be used. First group ID otherwise.
* @type {number}
*/
defaultGroupId?: number;
}
/*
@ -103,7 +109,7 @@ export class CoreGroupsProvider {
return Promise.reject(null);
}
return response.groups;
return response;
});
});
}
@ -138,7 +144,9 @@ export class CoreGroupsProvider {
return this.getActivityAllowedGroups(cmId, userId, siteId, ignoreCache);
}
return [];
return {
groups: []
};
});
}
@ -146,13 +154,13 @@ export class CoreGroupsProvider {
* Helper function to get activity group info (group mode and list of groups).
*
* @param {number} cmId Course module ID.
* @param {boolean} [addAllParts=true] Whether to add the all participants option. Always true for visible groups.
* @param {boolean} [addAllParts] Deprecated.
* @param {number} [userId] User ID. If not defined, use current user.
* @param {string} [siteId] Site ID. If not defined, current site.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @return {Promise<CoreGroupInfo>} Promise resolved with the group info.
*/
getActivityGroupInfo(cmId: number, addAllParts: boolean = true, userId?: number, siteId?: string, ignoreCache?: boolean)
getActivityGroupInfo(cmId: number, addAllParts?: boolean, userId?: number, siteId?: string, ignoreCache?: boolean)
: Promise<CoreGroupInfo> {
const groupInfo: CoreGroupInfo = {
@ -167,16 +175,25 @@ export class CoreGroupsProvider {
return this.getActivityAllowedGroups(cmId, userId, siteId, ignoreCache);
}
return [];
}).then((groups) => {
if (groups.length <= 0) {
return {
groups: [],
canaccessallgroups: false
};
}).then((result) => {
if (result.groups.length <= 0) {
groupInfo.separateGroups = false;
groupInfo.visibleGroups = false;
groupInfo.defaultGroupId = 0;
} else {
if (addAllParts || groupInfo.visibleGroups) {
// The "canaccessallgroups" field was added in 3.4. Add all participants for visible groups in previous versions.
if (result.canaccessallgroups || (typeof result.canaccessallgroups == 'undefined' && groupInfo.visibleGroups)) {
groupInfo.groups.push({ id: 0, name: this.translate.instant('core.allparticipants') });
groupInfo.defaultGroupId = 0;
} else {
groupInfo.defaultGroupId = result.groups[0].id;
}
groupInfo.groups = groupInfo.groups.concat(groups);
groupInfo.groups = groupInfo.groups.concat(result.groups);
}
return groupInfo;
@ -417,4 +434,22 @@ export class CoreGroupsProvider {
return site.invalidateWsCacheForKey(this.getUserGroupsInCourseCacheKey(courseId, userId));
});
}
/**
* Validate a group ID. If the group is not visible by the user, it will return the first group ID.
*
* @param {number} groupId Group ID to validate.
* @param {CoreGroupInfo} groupInfo Group info.
* @return {number} Group ID to use.
*/
validateGroupId(groupId: number, groupInfo: CoreGroupInfo): number {
if (groupId > 0 && groupInfo && groupInfo.groups && groupInfo.groups.length > 0) {
// Check if the group is in the list of groups.
if (groupInfo.groups.some((group) => groupId == group.id)) {
return groupId;
}
}
return groupInfo.defaultGroupId;
}
}

View File

@ -1,6 +1,10 @@
This files describes API changes in the Moodle Mobile app,
information provided here is intended especially for developers.
=== 3.7.1 ===
- CoreGroupsProvider.getActivityAllowedGroups and CoreGroupsProvider.getActivityAllowedGroupsIfEnabled now return the full response of core_group_get_activity_allowed_groups instead of just the groups.
=== 3.7.0 ===
- The pushnotifications addon has been moved to core. All imports of that addon need to be fixed to use the right path and name.