Merge pull request #3244 from crazyserver/MOBILE-3833

Mobile 3833
main
Dani Palou 2022-04-08 16:43:29 +02:00 committed by GitHub
commit 7a03ec48be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 194 additions and 103 deletions

View File

@ -2167,6 +2167,8 @@
"core.settings.cannotsyncloggedout": "local_moodlemobileapp",
"core.settings.cannotsyncoffline": "local_moodlemobileapp",
"core.settings.cannotsyncwithoutwifi": "local_moodlemobileapp",
"core.settings.changelanguage": "local_moodlemobileapp",
"core.settings.changelanguagealert": "local_moodlemobileapp",
"core.settings.colorscheme": "local_moodlemobileapp",
"core.settings.colorscheme-dark": "local_moodlemobileapp",
"core.settings.colorscheme-light": "local_moodlemobileapp",

View File

@ -134,6 +134,3 @@
[moduleId]="module.id">
</addon-mod-assign-submission>
</core-loading>
<core-course-module-navigation collapsible-footer [hidden]="showLoading" [courseId]="courseId" [currentModuleId]="module.id">
</core-course-module-navigation>

View File

@ -37,7 +37,7 @@
</ion-item>
<!-- Tabs: see the submission or grade it. -->
<core-tabs [selectedIndex]="selectedTab" [hideUntil]="loaded" parentScrollable="true" (ionChange)="tabSelected($event)">
<core-tabs [hideUntil]="loaded" parentScrollable="true" (ionChange)="tabSelected($event)">
<!-- View the submission tab. -->
<core-tab [title]="'addon.mod_assign.submission' | translate" id="submission">
<ng-template>
@ -139,10 +139,36 @@
[submission]="userSubmission" [plugin]="plugin">
</addon-mod-assign-submission-plugin>
<!-- Add or edit submission. -->
<ion-item class="ion-text-wrap" *ngIf="canEdit">
<!-- Team members that need to submit it too. -->
<ion-item-divider class="ion-text-wrap" *ngIf="membersToSubmit && membersToSubmit.length > 0">
<ion-label>
<div *ngIf="!unsupportedEditPlugins.length && !showErrorStatementEdit">
<h2>{{ 'addon.mod_assign.userswhoneedtosubmit' | translate: {$a: ''} }}</h2>
</ion-label>
</ion-item-divider>
<ng-container *ngIf="membersToSubmit && membersToSubmit.length > 0 && !blindMarking">
<ng-container *ngFor="let user of membersToSubmit">
<ion-item class="ion-text-wrap" core-user-link [userId]="user.id" [courseId]="courseId"
[attr.aria-label]="user.fullname">
<core-user-avatar [user]="user" slot="start" [linkProfile]="false"></core-user-avatar>
<ion-label>
<h2>{{ user.fullname }}</h2>
</ion-label>
</ion-item>
</ng-container>
</ng-container>
<ng-container *ngIf="membersToSubmit && membersToSubmit.length > 0 && blindMarking">
<ng-container *ngFor="let blindId of membersToSubmitBlind">
<ion-item class="ion-text-wrap">
<ion-label>{{ 'addon.mod_assign.hiddenuser' | translate }} {{ blindId }}</ion-label>
</ion-item>
</ng-container>
</ng-container>
<!-- Add or edit submission. -->
<div collapsible-footer *ngIf="loaded && !isSubmittedForGrading" [hidden]="selectedTab !== 'submission'" slot="fixed">
<div class="list-item-limited-width adaptable-buttons-row" *ngIf="canEdit || canSubmit">
<ng-container *ngIf="canEdit">
<ng-container *ngIf=" !unsupportedEditPlugins.length && !showErrorStatementEdit">
<!-- If has offline data, show edit. -->
<ion-button expand="block" class="ion-text-wrap" *ngIf="hasOffline" (click)="goToEdit()">
{{ 'addon.mod_assign.editsubmission' | translate }}
@ -173,17 +199,23 @@
userSubmission!.status != statusReopened" (click)="goToEdit()">
{{ 'addon.mod_assign.editsubmission' | translate }}
</ion-button>
</div>
<div *ngIf="unsupportedEditPlugins && unsupportedEditPlugins.length && !showErrorStatementEdit">
<p class="core-danger-item">{{ 'addon.mod_assign.erroreditpluginsnotsupported' | translate }}</p>
<p class="core-danger-item" *ngFor="let name of unsupportedEditPlugins">{{ name }}</p>
</div>
<div *ngIf="showErrorStatementEdit">
<p class="core-danger-item">{{ 'addon.mod_assign.cannoteditduetostatementsubmission' | translate }}</p>
</div>
</ng-container>
<ion-item class="core-danger-item ion-text-wrap" *ngIf="(unsupportedEditPlugins
&& unsupportedEditPlugins.length && !showErrorStatementEdit)|| showErrorStatementEdit">
<ion-label>
<ng-container
*ngIf="unsupportedEditPlugins && unsupportedEditPlugins.length && !showErrorStatementEdit">
<p>{{ 'addon.mod_assign.erroreditpluginsnotsupported' | translate }}</p>
<p *ngFor="let name of unsupportedEditPlugins">{{ name }}</p>
</ng-container>
<ng-container *ngIf="showErrorStatementEdit">
<p>{{ 'addon.mod_assign.cannoteditduetostatementsubmission' | translate }}</p>
</ng-container>
</ion-label>
</ion-item>
</ng-container>
<!-- Submit for grading form. -->
<ng-container *ngIf="canSubmit">
<ion-item class="ion-text-wrap" *ngIf="submissionStatement">
@ -211,31 +243,10 @@
</ion-label>
</ion-item>
</ng-container>
<!-- Team members that need to submit it too. -->
<ion-item-divider class="ion-text-wrap" *ngIf="membersToSubmit && membersToSubmit.length > 0">
<ion-label>
<h2>{{ 'addon.mod_assign.userswhoneedtosubmit' | translate: {$a: ''} }}</h2>
</ion-label>
</ion-item-divider>
<ng-container *ngIf="membersToSubmit && membersToSubmit.length > 0 && !blindMarking">
<ng-container *ngFor="let user of membersToSubmit">
<ion-item class="ion-text-wrap" core-user-link [userId]="user.id" [courseId]="courseId"
[attr.aria-label]="user.fullname">
<core-user-avatar [user]="user" slot="start" [linkProfile]="false"></core-user-avatar>
<ion-label>
<h2>{{ user.fullname }}</h2>
</ion-label>
</ion-item>
</ng-container>
</ng-container>
<ng-container *ngIf="membersToSubmit && membersToSubmit.length > 0 && blindMarking">
<ng-container *ngFor="let blindId of membersToSubmitBlind">
<ion-item class="ion-text-wrap">
<ion-label>{{ 'addon.mod_assign.hiddenuser' | translate }} {{ blindId }}</ion-label>
</ion-item>
</ng-container>
</ng-container>
</div>
<core-course-module-navigation [courseId]="courseId" [currentModuleId]="moduleId">
</core-course-module-navigation>
</div>
</ng-template>
</core-tab>

View File

@ -184,7 +184,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can
}
/**
* Component being initialized.
* @inheritdoc
*/
ngOnInit(): void {
this.isSubmittedForGrading = !!this.submitId;
@ -1195,6 +1195,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can
* @param tab The tab that was selected.
*/
tabSelected(tab: CoreTabComponent): void {
this.selectedTab = tab.id;
// Block sync when selecting grade tab, unblock when leaving it.
this.setGradeSyncBlocked(tab.id === 'grade');
}

View File

@ -482,6 +482,9 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft
*/
async selectTab(tabId: string, e?: Event): Promise<void> {
const index = this.tabs.findIndex((tab) => tabId == tab.id);
if (index < 0) {
return;
}
return this.selectByIndex(index, e);
}

View File

@ -6,11 +6,13 @@
"cannotsyncloggedout": "This site cannot be synchronised because you've logged out. Please try again when you're logged in the site again.",
"cannotsyncoffline": "Cannot synchronise offline.",
"cannotsyncwithoutwifi": "Cannot synchronise because the current settings only allow to synchronise when connected to Wi-Fi. Please connect to a Wi-Fi network.",
"colorscheme": "Color Scheme",
"changelanguage": "Change to {{$a}}",
"changelanguagealert": "Changing the language will restart the app.",
"colorscheme-dark": "Dark",
"colorscheme-light": "Light",
"colorscheme-system": "System default",
"colorscheme-system-notice": "System default mode will depend on your device support.",
"colorscheme-system": "System default",
"colorscheme": "Color Scheme",
"compilationinfo": "Compilation info",
"copyinfo": "Copy device info on the clipboard",
"cordovadevicemodel": "Cordova device model",

View File

@ -22,9 +22,10 @@ import { CorePushNotifications } from '@features/pushnotifications/services/push
import { CoreSettingsHelper, CoreColorScheme, CoreZoomLevel } from '../../services/settings-helper';
import { CoreApp } from '@services/app';
import { CoreIframeUtils } from '@services/utils/iframe';
import { Diagnostic } from '@singletons';
import { Diagnostic, Translate } from '@singletons';
import { CoreSites } from '@services/sites';
import { CoreUtils } from '@services/utils/utils';
import { AlertButton } from '@ionic/angular';
/**
* Page that displays the general settings.
@ -110,14 +111,64 @@ export class CoreSettingsGeneralPage {
/**
* Called when a new language is selected.
*/
languageChanged(): void {
CoreLang.changeCurrentLanguage(this.selectedLanguage).finally(async () => {
async languageChanged(): Promise<void> {
const previousLanguage = await CoreLang.getCurrentLanguage();
if (this.selectedLanguage === previousLanguage) {
// Prevent opening again.
return;
}
const previousLanguageCancel = Translate.instant('core.cancel');
try {
await CoreLang.changeCurrentLanguage(this.selectedLanguage);
} finally {
const langName = this.languages.find((lang) => lang.code == this.selectedLanguage)?.name;
const buttons: AlertButton[] = [
{
text: previousLanguageCancel,
role: 'cancel',
handler: (): void => {
clearTimeout(timeout);
this.selectedLanguage = previousLanguage;
CoreLang.changeCurrentLanguage(this.selectedLanguage);
},
},
{
text: Translate.instant('core.settings.changelanguage', { $a: langName }),
cssClass: 'timed-button',
handler: (): void => {
clearTimeout(timeout);
this.applyLanguageAndRestart();
},
},
];
const alert = await CoreDomUtils.showAlertWithOptions(
{
message: Translate.instant('core.settings.changelanguagealert'),
buttons,
},
);
const timeout = window.setTimeout(async () => {
await alert.dismiss();
this.applyLanguageAndRestart();
}, 10000);
}
}
/**
* Apply language changes and restart the app.
*/
protected async applyLanguageAndRestart(): Promise<void> {
// Invalidate cache for all sites to get the content in the right language.
const sites = await CoreSites.getSitesInstances();
await CoreUtils.ignoreErrors(Promise.all(sites.map((site) => site.invalidateWsCache())));
CoreEvents.trigger(CoreEvents.LANGUAGE_CHANGED, this.selectedLanguage);
});
window.location.reload();
}
/**

View File

@ -63,18 +63,18 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp
/**
* @inheritdoc
*/
getData(
async getData(
module: CoreCourseModuleData,
courseId: number,
sectionId?: number,
forCoursePage?: boolean,
): CoreCourseModuleHandlerData {
): Promise<CoreCourseModuleHandlerData> {
if (this.shouldOnlyDisplayDescription(module, forCoursePage)) {
const title = module.description;
module.description = '';
return {
icon: this.getIconSrc(),
icon: await CoreCourse.getModuleIconSrc(module.modname, this.handlerSchema.displaydata?.icon),
title: title || '',
a11yTitle: '',
class: this.handlerSchema.displaydata?.class,
@ -85,7 +85,7 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp
const showDowloadButton = this.handlerSchema.downloadbutton;
const handlerData: CoreCourseModuleHandlerData = {
title: module.name,
icon: this.getIconSrc(),
icon: await CoreCourse.getModuleIconSrc(module.modname, this.handlerSchema.displaydata?.icon),
class: this.handlerSchema.displaydata?.class,
showDownloadButton: showDowloadButton !== undefined ? showDowloadButton : hasOffline,
};
@ -198,13 +198,6 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp
}
}
/**
* @inheritdoc
*/
getIconSrc(): string | undefined {
return this.handlerSchema.displaydata?.icon;
}
/**
* @inheritdoc
*/

View File

@ -461,6 +461,34 @@ ion-alert.core-nohead {
}
}
@keyframes scaleFrom0 {
from {
/* More performant than animating `width` */
transform: scaleX(0);
}
}
ion-alert .alert-button.timed-button{
position: relative;
&::before {
content: '';
position: absolute;
width: 100%;
left: 0;
right: 0;
bottom: 0;
top: 0;
background-color: var(--primary-tint);
animation: scaleFrom0 10s forwards linear;
transform-origin: left;
@include rtl() {
transform-origin: right;
}
z-index: -1;
}
}
ion-alert {
--border-radius: var(--huge-radius);
@ -1054,8 +1082,15 @@ ion-button.chip {
ion-icon {
font-size: 16px;
min-width: 16px;
@include margin(0, 8px, 0, 0);
}
ion-label {
white-space: normal !important;
}
}
ion-button.chip {
ion-icon[slot=start] {
@include margin(0, 8px, 0, 0);
}
@ -1063,10 +1098,6 @@ ion-button.chip {
ion-icon[slot=end] {
@include margin(0, 0, 0, 8px);
}
ion-label {
white-space: normal !important;
}
}
ion-chip {