Merge pull request #3362 from dpalou/MOBILE-4035

Mobile 4035
main
Pau Ferrer Ocaña 2022-09-02 14:33:08 +02:00 committed by GitHub
commit 5828560771
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 117 additions and 187 deletions

View File

@ -984,6 +984,7 @@
"addon.mod_url.modulenameplural": "url", "addon.mod_url.modulenameplural": "url",
"addon.mod_url.pointingtourl": "local_moodlemobileapp", "addon.mod_url.pointingtourl": "local_moodlemobileapp",
"addon.mod_wiki.cannoteditpage": "wiki", "addon.mod_wiki.cannoteditpage": "wiki",
"addon.mod_wiki.cannotviewpage": "wiki",
"addon.mod_wiki.createpage": "wiki", "addon.mod_wiki.createpage": "wiki",
"addon.mod_wiki.editingpage": "wiki", "addon.mod_wiki.editingpage": "wiki",
"addon.mod_wiki.errorloadingpage": "local_moodlemobileapp", "addon.mod_wiki.errorloadingpage": "local_moodlemobileapp",

View File

@ -20,18 +20,8 @@
<!-- User can view all submissions (teacher). --> <!-- User can view all submissions (teacher). -->
<ng-container *ngIf="assign && canViewAllSubmissions"> <ng-container *ngIf="assign && canViewAllSubmissions">
<ion-list class="core-list-align-detail-right"> <ion-list class="core-list-align-detail-right">
<ion-item class="ion-text-wrap core-group-selector" *ngIf="(groupInfo.separateGroups || groupInfo.visibleGroups)">
<ion-label id="addon-assign-groupslabel"> <core-group-selector [groupInfo]="groupInfo" [(selected)]="group" (selectedChange)="setGroup(group)"></core-group-selector>
<ng-container *ngIf="groupInfo.separateGroups">{{'core.groupsseparate' | translate }}</ng-container>
<ng-container *ngIf="groupInfo.visibleGroups">{{'core.groupsvisible' | translate }}</ng-container>
</ion-label>
<ion-select [(ngModel)]="group" (ionChange)="setGroup(group)" aria-labelledby="addon-assign-groupslabel"
interface="action-sheet" [interfaceOptions]="{header: 'core.group' | translate}">
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
{{groupOpt.name}}
</ion-select-option>
</ion-select>
</ion-item>
<ion-item class="ion-text-wrap"> <ion-item class="ion-text-wrap">
<ion-label> <ion-label>

View File

@ -21,18 +21,9 @@
</ion-refresher> </ion-refresher>
<core-loading [hideUntil]="submissions.loaded"> <core-loading [hideUntil]="submissions.loaded">
<ion-list> <ion-list>
<ion-item class="ion-text-wrap core-group-selector" *ngIf="(groupInfo.separateGroups || groupInfo.visibleGroups)"> <core-group-selector [groupInfo]="groupInfo" [(selected)]="groupId" (selectedChange)="reloadSubmissions()">
<ion-label id="addon-assign-groupslabel-list"> </core-group-selector>
<ng-container *ngIf="groupInfo.separateGroups">{{'core.groupsseparate' | translate }}</ng-container>
<ng-container *ngIf="groupInfo.visibleGroups">{{'core.groupsvisible' | translate }}</ng-container>
</ion-label>
<ion-select [(ngModel)]="groupId" (ionChange)="reloadSubmissions()" aria-labelledby="addon-assign-groupslabel-list"
interface="action-sheet" slot="end" [interfaceOptions]="{header: 'core.group' | translate}">
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
{{groupOpt.name}}
</ion-select-option>
</ion-select>
</ion-item>
<!-- List of submissions. --> <!-- List of submissions. -->
<ng-container *ngFor="let submission of submissions.items"> <ng-container *ngFor="let submission of submissions.items">
<ion-item class="ion-text-wrap" (click)="submissions.select(submission)" button <ion-item class="ion-text-wrap" (click)="submissions.select(submission)" button

View File

@ -13,27 +13,8 @@
[courseId]="courseId" (completionChanged)="onCompletionChange()"> [courseId]="courseId" (completionChanged)="onCompletionChange()">
</core-course-module-info> </core-course-module-info>
<ng-container *ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)"> <core-group-selector [groupInfo]="groupInfo" [(selected)]="groupId" (selectedChange)="groupChanged()"
<ion-card class="core-info-card" *ngIf="groupInfo.groups && groupInfo.groups.length > 1"> [multipleGroupsMessage]="'addon.mod_bigbluebuttonbn.view_groups_selection_warning' | translate"></core-group-selector>
<ion-item>
<ion-icon name="fas-question-circle" slot="start" aria-hidden="true"></ion-icon>
<ion-label>{{ 'addon.mod_bigbluebuttonbn.view_groups_selection_warning' | translate }}</ion-label>
</ion-item>
</ion-card>
<ion-item class="ion-text-wrap core-group-selector">
<ion-label id="addon-bigbluebuttonbn-groupslabel">
<ng-container *ngIf="groupInfo.separateGroups">{{ 'core.groupsseparate' | translate }}</ng-container>
<ng-container *ngIf="groupInfo.visibleGroups">{{ 'core.groupsvisible' | translate }}</ng-container>
</ion-label>
<ion-select [(ngModel)]="groupId" (ionChange)="groupChanged()" aria-labelledby="addon-bigbluebuttonbn-groupslabel"
interface="action-sheet" [interfaceOptions]="{header: 'core.group' | translate}">
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
{{groupOpt.name}}
</ion-select-option>
</ion-select>
</ion-item>
</ng-container>
<ng-container *ngIf="meetingInfo"> <ng-container *ngIf="meetingInfo">
<ion-item class="ion-text-wrap" *ngIf="meetingInfo.openingtime"> <ion-item class="ion-text-wrap" *ngIf="meetingInfo.openingtime">

View File

@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
import { Component, OnInit, Optional } from '@angular/core'; import { Component, OnInit, Optional } from '@angular/core';
import { CoreError } from '@classes/errors/error';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component'; import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents'; import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { IonContent } from '@ionic/angular'; import { IonContent } from '@ionic/angular';
@ -68,6 +69,10 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
this.groupId = CoreGroups.validateGroupId(this.groupId, this.groupInfo); this.groupId = CoreGroups.validateGroupId(this.groupId, this.groupInfo);
if (this.groupInfo.separateGroups && !this.groupInfo.groups.length) {
throw new CoreError(Translate.instant('addon.mod_bigbluebuttonbn.view_nojoin'));
}
await this.fetchMeetingInfo(); await this.fetchMeetingInfo();
} }

View File

@ -14,18 +14,7 @@
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content> <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
</ion-refresher> </ion-refresher>
<core-loading [hideUntil]="sessions.loaded"> <core-loading [hideUntil]="sessions.loaded">
<ion-item class="ion-text-wrap core-group-selector" *ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)"> <core-group-selector [groupInfo]="groupInfo" [(selected)]="groupId" (selectedChange)="reloadSessions()"></core-group-selector>
<ion-label id="addon-chat-groupslabel">
<ng-container *ngIf="groupInfo.separateGroups">{{'core.groupsseparate' | translate }}</ng-container>
<ng-container *ngIf="groupInfo.visibleGroups">{{'core.groupsvisible' | translate }}</ng-container>
</ion-label>
<ion-select [(ngModel)]="groupId" (ionChange)="reloadSessions()" aria-labelledby="addon-chat-groupslabel"
interface="action-sheet" [interfaceOptions]="{header: 'core.group' | translate}">
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
{{groupOpt.name}}
</ion-select-option>
</ion-select>
</ion-item>
<ion-item> <ion-item>
<ion-label>{{ 'addon.mod_chat.showincompletesessions' | translate }}</ion-label> <ion-label>{{ 'addon.mod_chat.showincompletesessions' | translate }}</ion-label>

View File

@ -25,18 +25,8 @@
[courseId]="courseId" [hasDataToSync]="hasOffline || hasOfflineRatings" (completionChanged)="onCompletionChange()"> [courseId]="courseId" [hasDataToSync]="hasOffline || hasOfflineRatings" (completionChanged)="onCompletionChange()">
</core-course-module-info> </core-course-module-info>
<ion-item class="ion-text-wrap core-group-selector" *ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)"> <core-group-selector [groupInfo]="groupInfo" [(selected)]="selectedGroup" (selectedChange)="setGroup(selectedGroup)">
<ion-label id="addon-data-groupslabel"> </core-group-selector>
<ng-container *ngIf="groupInfo.separateGroups">{{'core.groupsseparate' | translate }}</ng-container>
<ng-container *ngIf="groupInfo.visibleGroups">{{'core.groupsvisible' | translate }}</ng-container>
</ion-label>
<ion-select [(ngModel)]="selectedGroup" (ionChange)="setGroup(selectedGroup)" aria-labelledby="addon-data-groupslabel"
interface="action-sheet" [interfaceOptions]="{header: 'core.group' | translate}">
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
{{groupOpt.name}}
</ion-select-option>
</ion-select>
</ion-item>
<ion-card class="core-info-card" *ngIf="!access?.timeavailable && timeAvailableFrom"> <ion-card class="core-info-card" *ngIf="!access?.timeavailable && timeAvailableFrom">
<ion-item> <ion-item>

View File

@ -218,7 +218,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
} }
this.groupInfo = await CoreGroups.getActivityGroupInfo(this.database.coursemodule); this.groupInfo = await CoreGroups.getActivityGroupInfo(this.database.coursemodule);
if (this.groupInfo.visibleGroups && this.groupInfo.groups?.length) { if (this.groupInfo.visibleGroups && this.groupInfo.groups.length) {
// There is a bug in Moodle with All participants and visible groups (MOBILE-3597). Remove it. // There is a bug in Moodle with All participants and visible groups (MOBILE-3597). Remove it.
this.groupInfo.groups = this.groupInfo.groups.filter(group => group.id !== 0); this.groupInfo.groups = this.groupInfo.groups.filter(group => group.id !== 0);
this.groupInfo.defaultGroupId = this.groupInfo.groups[0].id; this.groupInfo.defaultGroupId = this.groupInfo.groups[0].id;

View File

@ -18,18 +18,8 @@
</ion-header> </ion-header>
<ion-content> <ion-content>
<core-loading [hideUntil]="loaded"> <core-loading [hideUntil]="loaded">
<ion-item class="ion-text-wrap core-group-selector" *ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)"> <core-group-selector [groupInfo]="groupInfo" [(selected)]="selectedGroup" (selectedChange)="setGroup(selectedGroup)">
<ion-label id="addon-data-groupslabel"> </core-group-selector>
<ng-container *ngIf="groupInfo.separateGroups">{{ 'core.groupsseparate' | translate }}</ng-container>
<ng-container *ngIf="groupInfo.visibleGroups">{{ 'core.groupsvisible' | translate }}</ng-container>
</ion-label>
<ion-select [(ngModel)]="selectedGroup" (ionChange)="setGroup(selectedGroup)" aria-labelledby="addon-data-groupslabel"
interface="action-sheet" [interfaceOptions]="{header: 'core.group' | translate}">
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
{{groupOpt.name}}
</ion-select-option>
</ion-select>
</ion-item>
<div class="addon-data-contents {{cssClass}}" *ngIf="database"> <div class="addon-data-contents {{cssClass}}" *ngIf="database">
<core-style [css]="database.csstemplate" prefix=".{{cssClass}}"></core-style> <core-style [css]="database.csstemplate" prefix=".{{cssClass}}"></core-style>

View File

@ -179,7 +179,7 @@ export class AddonModDataEditPage implements OnInit {
if (refresh) { if (refresh) {
groupInfo = await CoreGroups.getActivityGroupInfo(this.database.coursemodule); groupInfo = await CoreGroups.getActivityGroupInfo(this.database.coursemodule);
if (groupInfo.visibleGroups && groupInfo.groups?.length) { if (groupInfo.visibleGroups && groupInfo.groups.length) {
// There is a bug in Moodle with All participants and visible groups (MOBILE-3597). Remove it. // There is a bug in Moodle with All participants and visible groups (MOBILE-3597). Remove it.
groupInfo.groups = groupInfo.groups.filter(group => group.id !== 0); groupInfo.groups = groupInfo.groups.filter(group => group.id !== 0);
groupInfo.defaultGroupId = groupInfo.groups[0].id; groupInfo.defaultGroupId = groupInfo.groups[0].id;

View File

@ -25,18 +25,8 @@
</ion-item> </ion-item>
</ion-card> </ion-card>
<ion-item class="ion-text-wrap core-group-selector" *ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)"> <core-group-selector [groupInfo]="groupInfo" [(selected)]="selectedGroup" (selectedChange)="setGroup(selectedGroup)">
<ion-label id="addon-data-groupslabel"> </core-group-selector>
<ng-container *ngIf="groupInfo.separateGroups">{{ 'core.groupsvisible' | translate }}</ng-container>
<ng-container *ngIf="groupInfo.visibleGroups">{{ 'core.groupsseparate' | translate }}</ng-container>
</ion-label>
<ion-select [(ngModel)]="selectedGroup" (ionChange)="setGroup(selectedGroup)" aria-labelledby="addon-data-groupslabel"
interface="action-sheet" [interfaceOptions]="{header: 'core.group' | translate}">
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
{{groupOpt.name}}
</ion-select-option>
</ion-select>
</ion-item>
<div class="addon-data-contents addon-data-entry addon-data-entries-{{database.id}}" *ngIf="database && entry"> <div class="addon-data-contents addon-data-entry addon-data-entries-{{database.id}}" *ngIf="database && entry">
<core-style [css]="database.csstemplate" prefix=".addon-data-entries-{{database.id}}"></core-style> <core-style [css]="database.csstemplate" prefix=".addon-data-entries-{{database.id}}"></core-style>

View File

@ -174,7 +174,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy {
this.access = await AddonModData.getDatabaseAccessInformation(this.database.id, { cmId: this.moduleId }); this.access = await AddonModData.getDatabaseAccessInformation(this.database.id, { cmId: this.moduleId });
this.groupInfo = await CoreGroups.getActivityGroupInfo(this.database.coursemodule); this.groupInfo = await CoreGroups.getActivityGroupInfo(this.database.coursemodule);
if (this.groupInfo.visibleGroups && this.groupInfo.groups?.length) { if (this.groupInfo.visibleGroups && this.groupInfo.groups.length) {
// There is a bug in Moodle with All participants and visible groups (MOBILE-3597). Remove it. // There is a bug in Moodle with All participants and visible groups (MOBILE-3597). Remove it.
this.groupInfo.groups = this.groupInfo.groups.filter(group => group.id !== 0); this.groupInfo.groups = this.groupInfo.groups.filter(group => group.id !== 0);
this.groupInfo.defaultGroupId = this.groupInfo.groups[0].id; this.groupInfo.defaultGroupId = this.groupInfo.groups[0].id;

View File

@ -59,18 +59,8 @@
<ng-template #basicInfo> <ng-template #basicInfo>
<ion-list *ngIf="access && access.canviewanalysis && !access.isempty"> <ion-list *ngIf="access && access.canviewanalysis && !access.isempty">
<ion-item class="ion-text-wrap core-group-selector" *ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)"> <core-group-selector [groupInfo]="groupInfo" [(selected)]="group" (selectedChange)="setGroup(group)"></core-group-selector>
<ion-label id="addon-feedback-groupslabel">
<ng-container *ngIf="groupInfo.separateGroups">{{ 'core.groupsseparate' | translate }}</ng-container>
<ng-container *ngIf="groupInfo.visibleGroups">{{ 'core.groupsvisible' | translate }}</ng-container>
</ion-label>
<ion-select [(ngModel)]="group" (ionChange)="setGroup(group)" aria-labelledby="addon-feedback-groupslabel"
interface="action-sheet" [interfaceOptions]="{header: 'core.group' | translate}">
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
{{groupOpt.name}}
</ion-select-option>
</ion-select>
</ion-item>
<ion-item class="ion-text-wrap" (click)="openAttempts()" [detail]="access.canviewreports && completedCount > 0" <ion-item class="ion-text-wrap" (click)="openAttempts()" [detail]="access.canviewreports && completedCount > 0"
[button]="access.canviewreports && completedCount > 0"> [button]="access.canviewreports && completedCount > 0">
<ion-label> <ion-label>

View File

@ -15,19 +15,8 @@
</ion-refresher> </ion-refresher>
<core-loading [hideUntil]="attempts && attempts.loaded"> <core-loading [hideUntil]="attempts && attempts.loaded">
<ion-list class="ion-no-margin"> <ion-list class="ion-no-margin">
<ion-item class="ion-text-wrap core-group-selector" <core-group-selector [groupInfo]="groupInfo" [(selected)]="selectedGroup" (selectedChange)="reloadAttempts()">
*ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)"> </core-group-selector>
<ion-label id="addon-feedback-groupslabel">
<ng-container *ngIf="groupInfo.separateGroups">{{'core.groupsseparate' | translate }}</ng-container>
<ng-container *ngIf="groupInfo.visibleGroups">{{'core.groupsvisible' | translate }}</ng-container>
</ion-label>
<ion-select [(ngModel)]="selectedGroup" (ionChange)="reloadAttempts()" aria-labelledby="addon-feedback-groupslabel"
interface="action-sheet" [interfaceOptions]="{header: 'core.group' | translate}">
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
{{groupOpt.name}}
</ion-select-option>
</ion-select>
</ion-item>
<ng-container *ngIf="identifiableAttemptsTotal > 0"> <ng-container *ngIf="identifiableAttemptsTotal > 0">
<ion-item-divider> <ion-item-divider>

View File

@ -14,19 +14,8 @@
</ion-refresher> </ion-refresher>
<core-loading [hideUntil]="loaded"> <core-loading [hideUntil]="loaded">
<ion-list class="ion-no-margin"> <ion-list class="ion-no-margin">
<ion-item class="ion-text-wrap core-group-selector" *ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)"> <core-group-selector [groupInfo]="groupInfo" [(selected)]="selectedGroup" (selectedChange)="loadAttempts(selectedGroup)">
<ion-label id="addon-feedback-groupslabel"> </core-group-selector>
<ng-container *ngIf="groupInfo.separateGroups">{{'core.groupsseparate' | translate }}</ng-container>
<ng-container *ngIf="groupInfo.visibleGroups">{{'core.groupsvisible' | translate }}</ng-container>
</ion-label>
<ion-select [(ngModel)]="selectedGroup" (ionChange)="loadAttempts(selectedGroup)"
aria-labelledby="addon-feedback-groupslabel" interface="action-sheet"
[interfaceOptions]="{header: 'core.group' | translate}">
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
{{groupOpt.name}}
</ion-select-option>
</ion-select>
</ion-item>
<ion-item-divider> <ion-item-divider>
<ion-label> <ion-label>

View File

@ -23,19 +23,8 @@
</ion-item> </ion-item>
</core-course-module-info> </core-course-module-info>
<ion-item class="ion-text-wrap core-group-selector" lines="none" <core-group-selector *ngIf="supportsChangeGroup" [groupInfo]="groupInfo" [(selected)]="groupId" (selectedChange)="groupChanged()">
*ngIf="supportsChangeGroup && groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)"> </core-group-selector>
<ion-label id="addon-forum-groupslabel">
<ng-container *ngIf="groupInfo.separateGroups">{{'core.groupsseparate' | translate }}</ng-container>
<ng-container *ngIf="groupInfo.visibleGroups">{{'core.groupsvisible' | translate }}</ng-container>
</ion-label>
<ion-select [(ngModel)]="groupId" (ionChange)="groupChanged()" aria-labelledby="addon-forum-groupslabel"
interface="action-sheet" [interfaceOptions]="{header: 'core.group' | translate}">
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
{{groupOpt.name}}
</ion-select-option>
</ion-select>
</ion-item>
<!-- Cut-off date or due date message --> <!-- Cut-off date or due date message -->
<ion-card class="core-info-card" *ngIf="availabilityMessage"> <ion-card class="core-info-card" *ngIf="availabilityMessage">

View File

@ -158,7 +158,7 @@ export class AddonModForumPrefetchHandlerService extends CoreCourseActivityPrefe
return [0]; return [0];
} }
const allPartsGroup = groupInfo.groups?.find(group => group.id === 0); const allPartsGroup = groupInfo.groups.find(group => group.id === 0);
if (allPartsGroup) { if (allPartsGroup) {
return [0]; // Prefetch all participants. return [0]; // Prefetch all participants.
} }
@ -168,7 +168,7 @@ export class AddonModForumPrefetchHandlerService extends CoreCourseActivityPrefe
return [groupInfo.defaultGroupId]; return [groupInfo.defaultGroupId];
} }
return groupInfo.groups?.map(group => group.id) ?? [0]; return groupInfo.groups.map(group => group.id) ?? [0];
} }
/** /**

View File

@ -56,20 +56,8 @@
<core-tab *ngIf="canViewReports" [title]="'addon.mod_lesson.reports' | translate" (ionSelect)="reportsSelected()"> <core-tab *ngIf="canViewReports" [title]="'addon.mod_lesson.reports' | translate" (ionSelect)="reportsSelected()">
<ng-template> <ng-template>
<core-loading [hideUntil]="reportLoaded"> <core-loading [hideUntil]="reportLoaded">
<!-- Group selector if the activity uses groups. --> <core-group-selector [groupInfo]="groupInfo" [(selected)]="group" (selectedChange)="setGroup(group)">
<ion-item class="ion-text-wrap core-group-selector" </core-group-selector>
*ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)">
<ion-label id="addon-mod_lesson-groupslabel">
<span *ngIf="groupInfo.separateGroups">{{ 'core.groupsseparate' | translate }}</span>
<span *ngIf="groupInfo.visibleGroups">{{ 'core.groupsvisible' | translate }}</span>
</ion-label>
<ion-select [(ngModel)]="group" (ionChange)="setGroup(group)" aria-labelledby="addon-mod_lesson-groupslabel"
interface="action-sheet" [interfaceOptions]="{header: 'core.group' | translate}">
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
{{groupOpt.name}}
</ion-select-option>
</ion-select>
</ion-item>
<!-- No lesson retakes. --> <!-- No lesson retakes. -->
<core-empty-box *ngIf="!overview && selectedGroupName" icon="fas-chart-bar" <core-empty-box *ngIf="!overview && selectedGroupName" icon="fas-chart-bar"

View File

@ -431,7 +431,7 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref
): Promise<void> { ): Promise<void> {
const groupInfo = await CoreGroups.getActivityGroupInfo(moduleId, false, undefined, modOptions.siteId, true); const groupInfo = await CoreGroups.getActivityGroupInfo(moduleId, false, undefined, modOptions.siteId, true);
await Promise.all(groupInfo.groups?.map(async (group) => { await Promise.all(groupInfo.groups.map(async (group) => {
await AddonModLesson.getRetakesOverview(lessonId, { await AddonModLesson.getRetakesOverview(lessonId, {
groupId: group.id, groupId: group.id,
...modOptions, // Include all options. ...modOptions, // Include all options.

View File

@ -249,6 +249,10 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
// Get real groupmode, in case it's forced by the course. // Get real groupmode, in case it's forced by the course.
const groupInfo = await CoreGroups.getActivityGroupInfo(this.wiki.coursemodule); const groupInfo = await CoreGroups.getActivityGroupInfo(this.wiki.coursemodule);
if (groupInfo.separateGroups && !groupInfo.groups.length) {
throw new CoreError(Translate.instant('addon.mod_wiki.cannotviewpage'));
}
await this.createSubwikiList(groupInfo.groups); await this.createSubwikiList(groupInfo.groups);
} else { } else {
this.subwikiData.count = subwikiList.count; this.subwikiData.count = subwikiList.count;
@ -867,7 +871,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
* @param userGroups Groups. * @param userGroups Groups.
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
protected async createSubwikiList(userGroups?: CoreGroup[]): Promise<void> { protected async createSubwikiList(userGroups: CoreGroup[]): Promise<void> {
const subwikiList: AddonModWikiSubwikiListSubwiki[] = []; const subwikiList: AddonModWikiSubwikiListSubwiki[] = [];
let allParticipants = false; let allParticipants = false;
let showMyGroupsLabel = false; let showMyGroupsLabel = false;
@ -895,7 +899,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
allParticipants = true; allParticipants = true;
} }
} else { } else {
if (subwiki.groupid != 0 && userGroups && userGroups.length > 0) { if (subwiki.groupid != 0 && userGroups.length > 0) {
// Get groupLabel if it has groupId. // Get groupLabel if it has groupId.
const group = userGroups.find(group => group.id == subwiki.groupid); const group = userGroups.find(group => group.id == subwiki.groupid);
groupLabel = group?.name || ''; groupLabel = group?.name || '';

View File

@ -1,5 +1,6 @@
{ {
"cannoteditpage": "You can not edit this page.", "cannoteditpage": "You can not edit this page.",
"cannotviewpage": "You can not view this page.",
"createpage": "Create page", "createpage": "Create page",
"editingpage": "Editing this page '{{$a}}'", "editingpage": "Editing this page '{{$a}}'",
"errorloadingpage": "An error occurred while loading the page.", "errorloadingpage": "An error occurred while loading the page.",

View File

@ -178,20 +178,7 @@
<h2 *ngIf="workshop!.phase > PHASE_SUBMISSION">{{ 'addon.mod_workshop.gradesreport' | translate }}</h2> <h2 *ngIf="workshop!.phase > PHASE_SUBMISSION">{{ 'addon.mod_workshop.gradesreport' | translate }}</h2>
</ion-label> </ion-label>
</ion-item-divider> </ion-item-divider>
<ion-item class="ion-text-wrap core-group-selector" *ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)"> <core-group-selector [groupInfo]="groupInfo" [(selected)]="group" (selectedChange)="setGroup(group)"></core-group-selector>
<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)]="group" (ionChange)="setGroup(group)" aria-labelledby="addon-workshop-groupslabel"
interface="action-sheet" [interfaceOptions]="{header: 'core.group' | translate}">
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
{{groupOpt.name}}
</ion-select-option>
</ion-select>
</ion-item>
<ng-container *ngFor="let submission of grades"> <ng-container *ngFor="let submission of grades">
<addon-mod-workshop-submission [submission]="submission" [courseId]="workshop!.course" [module]="module" <addon-mod-workshop-submission [submission]="submission" [courseId]="workshop!.course" [module]="module"

View File

@ -62,6 +62,7 @@ import { CoreButtonWithSpinnerComponent } from './button-with-spinner/button-wit
import { CoreSwipeSlidesComponent } from './swipe-slides/swipe-slides'; import { CoreSwipeSlidesComponent } from './swipe-slides/swipe-slides';
import { CoreSwipeNavigationTourComponent } from './swipe-navigation-tour/swipe-navigation-tour'; import { CoreSwipeNavigationTourComponent } from './swipe-navigation-tour/swipe-navigation-tour';
import { CoreMessageComponent } from './message/message'; import { CoreMessageComponent } from './message/message';
import { CoreGroupSelectorComponent } from './group-selector/group-selector';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -78,6 +79,7 @@ import { CoreMessageComponent } from './message/message';
CoreEmptyBoxComponent, CoreEmptyBoxComponent,
CoreFileComponent, CoreFileComponent,
CoreFilesComponent, CoreFilesComponent,
CoreGroupSelectorComponent,
CoreIconComponent, CoreIconComponent,
CoreIframeComponent, CoreIframeComponent,
CoreInfiniteLoadingComponent, CoreInfiniteLoadingComponent,
@ -129,6 +131,7 @@ import { CoreMessageComponent } from './message/message';
CoreEmptyBoxComponent, CoreEmptyBoxComponent,
CoreFileComponent, CoreFileComponent,
CoreFilesComponent, CoreFilesComponent,
CoreGroupSelectorComponent,
CoreIconComponent, CoreIconComponent,
CoreIframeComponent, CoreIframeComponent,
CoreInfiniteLoadingComponent, CoreInfiniteLoadingComponent,

View File

@ -0,0 +1,22 @@
<ng-container *ngIf="groupInfo && groupInfo.groups.length > 0 && (groupInfo.separateGroups || groupInfo.visibleGroups)">
<ion-card class="core-info-card" *ngIf="multipleGroupsMessage && groupInfo.groups && groupInfo.groups.length > 1">
<ion-item>
<ion-icon name="fas-question-circle" slot="start" aria-hidden="true"></ion-icon>
<ion-label>{{ multipleGroupsMessage }}</ion-label>
</ion-item>
</ion-card>
<ion-item class="ion-text-wrap core-group-selector">
<ion-label id="core-groups-selector-groupslabel-{{id}}">
<ng-container *ngIf="groupInfo.separateGroups">{{'core.groupsseparate' | translate }}</ng-container>
<ng-container *ngIf="groupInfo.visibleGroups">{{'core.groupsvisible' | translate }}</ng-container>
</ion-label>
<ion-select [(ngModel)]="selected" (ionChange)="selectedChange.emit(selected)"
[attr.aria-labelledby]="'core-groups-selector-groupslabel-' + id" interface="action-sheet"
[interfaceOptions]="{header: 'core.group' | translate}">
<ion-select-option *ngFor="let groupOpt of groupInfo.groups" [value]="groupOpt.id">
{{groupOpt.name}}
</ion-select-option>
</ion-select>
</ion-item>
</ng-container>

View File

@ -0,0 +1,43 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Input, Output, EventEmitter, OnInit, ChangeDetectionStrategy } from '@angular/core';
import { CoreGroupInfo } from '@services/groups';
import { CoreUtils } from '@services/utils/utils';
/**
* Component to display a group selector.
*/
@Component({
selector: 'core-group-selector',
templateUrl: 'group-selector.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CoreGroupSelectorComponent implements OnInit {
@Input() groupInfo?: CoreGroupInfo;
@Input() multipleGroupsMessage?: string;
@Input() selected!: number;
@Output() selectedChange = new EventEmitter<number>();
id!: number;
/**
* @inheritdoc
*/
ngOnInit(): void {
this.id = CoreUtils.getUniqueId('CoreGroupSelectorComponent');
}
}

View File

@ -170,19 +170,17 @@ export class CoreGroupsProvider {
}; };
} }
if (result.groups.length <= 0) { if (!result.groups.length) {
groupInfo.separateGroups = false;
groupInfo.visibleGroups = false;
groupInfo.defaultGroupId = 0; groupInfo.defaultGroupId = 0;
} else { } else {
if (result.canaccessallgroups || groupInfo.visibleGroups) { if (result.canaccessallgroups || groupInfo.visibleGroups) {
groupInfo.groups!.push({ id: 0, name: Translate.instant('core.allparticipants') }); groupInfo.groups.push({ id: 0, name: Translate.instant('core.allparticipants') });
groupInfo.defaultGroupId = 0; groupInfo.defaultGroupId = 0;
} else { } else {
groupInfo.defaultGroupId = result.groups[0].id; groupInfo.defaultGroupId = result.groups[0].id;
} }
groupInfo.groups = groupInfo.groups!.concat(result.groups); groupInfo.groups = groupInfo.groups.concat(result.groups);
} }
return groupInfo; return groupInfo;
@ -458,7 +456,7 @@ export type CoreGroupInfo = {
/** /**
* List of groups. * List of groups.
*/ */
groups?: CoreGroup[]; groups: CoreGroup[];
/** /**
* Whether it's separate groups. * Whether it's separate groups.