diff --git a/package-lock.json b/package-lock.json index 59d7c43d3..841cc1fb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,7 +40,7 @@ "@awesome-cordova-plugins/sqlite": "^6.3.0", "@awesome-cordova-plugins/status-bar": "^6.3.0", "@awesome-cordova-plugins/web-intent": "^6.3.0", - "@ionic/angular": "^7.0.0", + "@ionic/angular": "^7.6.1", "@ionic/cordova-builders": "^10.0.0", "@moodlehq/cordova-plugin-advanced-http": "3.3.1-moodle.1", "@moodlehq/cordova-plugin-camera": "6.0.0-moodle.2", @@ -3449,11 +3449,11 @@ "dev": true }, "node_modules/@ionic/angular": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-7.5.6.tgz", - "integrity": "sha512-RJDQgGiVRps/04HBfx23E8tiGCvzE2d5NpWB1Mi1CDmc0ENTSc6odb2XI45YhFxmGvQsWZ8k+H1N/8emAHPraw==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-7.6.1.tgz", + "integrity": "sha512-Eh//g/bAL9se4PD6C19NqymgQbqKp4W+Ffbjo8Qnqwk02jGMs/jcMP0WVEcLNiEws2m67kIiWItrUhJjb8pplA==", "dependencies": { - "@ionic/core": "7.5.6", + "@ionic/core": "7.6.1", "ionicons": "^7.0.0", "jsonc-parser": "^3.0.0", "tslib": "^2.3.0" @@ -3967,11 +3967,11 @@ } }, "node_modules/@ionic/core": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.5.6.tgz", - "integrity": "sha512-bYQp2twwm61uA0Q31ToVIpQWsiQ9so1dRoWZPD+l+y4fVuFmOCLYeS6XTLTm73jVBq40JfEcsac7eYC4DxoemQ==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.6.1.tgz", + "integrity": "sha512-o4PSRxokfRB5H3E5DAM7xivG8XFXaXD3+U/tha0QKemiMSntqgPqy0FYX0pNEwIrV3llRzFbAGNqyvB1+BG97Q==", "dependencies": { - "@stencil/core": "^4.7.2", + "@stencil/core": "^4.8.2", "ionicons": "^7.2.1", "tslib": "^2.1.0" } @@ -5990,9 +5990,9 @@ } }, "node_modules/@stencil/core": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.7.2.tgz", - "integrity": "sha512-sPPDYrXiTbfeUF5CCyfqysXK/yfTHC4xYR1+nHzGkS2vhRSBOLp0oPuB+xkJLKA+K2ZqDJUxpOnDxy1CLWwBXA==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.8.2.tgz", + "integrity": "sha512-KdZEAtz9VnqMtXOkf51+8mphyRt0fN/LYgtj5M8gnveGspG8KzoyTDzlWt0wsstWIsJJ21RA1yd3AgMMZiu3MA==", "bin": { "stencil": "bin/stencil" }, diff --git a/package.json b/package.json index 9e0dfa518..7e739e549 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "@awesome-cordova-plugins/sqlite": "^6.3.0", "@awesome-cordova-plugins/status-bar": "^6.3.0", "@awesome-cordova-plugins/web-intent": "^6.3.0", - "@ionic/angular": "^7.0.0", + "@ionic/angular": "^7.6.1", "@ionic/cordova-builders": "^10.0.0", "@moodlehq/cordova-plugin-advanced-http": "3.3.1-moodle.1", "@moodlehq/cordova-plugin-camera": "6.0.0-moodle.2", diff --git a/src/addons/blog/pages/entries/entries.html b/src/addons/blog/pages/entries/entries.html index 9fac4dfb2..ee8584a08 100644 --- a/src/addons/blog/pages/entries/entries.html +++ b/src/addons/blog/pages/entries/entries.html @@ -17,8 +17,9 @@ - {{ 'addon.blog.showonlyyourentries' | translate }} - + + {{ 'addon.blog.showonlyyourentries' | translate }} + diff --git a/src/addons/calendar/components/filter/filter.html b/src/addons/calendar/components/filter/filter.html index 365e7e72f..5d746163a 100644 --- a/src/addons/calendar/components/filter/filter.html +++ b/src/addons/calendar/components/filter/filter.html @@ -11,17 +11,17 @@ - + - - + diff --git a/src/addons/calendar/pages/edit-event/edit-event.html b/src/addons/calendar/pages/edit-event/edit-event.html index 26592324d..fde3faec0 100644 --- a/src/addons/calendar/pages/edit-event/edit-event.html +++ b/src/addons/calendar/pages/edit-event/edit-event.html @@ -17,11 +17,11 @@
- -

{{ 'addon.calendar.eventname' | translate }}

-
- - + +
{{ 'addon.calendar.eventname' | translate }}
+
+
@@ -37,17 +37,18 @@ - + - +

{{ 'addon.calendar.eventkind' | translate }}

{{eventTypes[0].name | translate }}

+
{{ 'addon.calendar.eventkind' | translate }}
{{ type.name | translate }} @@ -56,11 +57,9 @@ - -

{{ 'core.category' | translate }}

-
+

{{ 'core.category' | translate }}

{{ category.name }} @@ -69,11 +68,9 @@ - -

{{ 'core.course' | translate }}

-
+

{{ 'core.course' | translate }}

{{ course.fullname }}
@@ -82,12 +79,10 @@ - -

{{ 'core.course' | translate }}

-
+

{{ 'core.course' | translate }}

{{ course.fullname }} @@ -101,11 +96,9 @@
- -

{{ 'core.group' | translate }}

-
+

{{ 'core.group' | translate }}

{{ group.name }}
@@ -147,16 +140,14 @@
- +

{{ 'addon.calendar.durationnone' | translate }}

-
- +
- +

{{ 'addon.calendar.durationuntil' | translate }}

-
- +
@@ -171,14 +162,12 @@ - -

{{ 'addon.calendar.durationminutes' | translate }}

-
- + +

{{ 'addon.calendar.durationminutes' | translate }}

+
- {{ 'addon.calendar.durationminutes' | translate }} - @@ -187,16 +176,13 @@ - +

{{ 'addon.calendar.repeatevent' | translate }}

-
- +
- -

{{ 'addon.calendar.repeatweeksl' | translate }}

-
- +
@@ -209,16 +195,14 @@ - +

{{ 'addon.calendar.repeateditall' | translate:{$a: otherEventsCount} }}

-
- +
- +

{{ 'addon.calendar.repeateditthis' | translate }}

-
- +
@@ -235,10 +219,8 @@ - -

{{ 'core.location' | translate }}

-
- +
diff --git a/src/addons/calendar/pages/edit-event/edit-event.ts b/src/addons/calendar/pages/edit-event/edit-event.ts index 7eb187dc4..a30321547 100644 --- a/src/addons/calendar/pages/edit-event/edit-event.ts +++ b/src/addons/calendar/pages/edit-event/edit-event.ts @@ -69,7 +69,6 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave { groups: CoreGroup[] = []; loadingGroups = false; courseGroupSet = false; - errors: Record; error = false; eventRepeatId?: number; otherEventsCount = 0; @@ -100,9 +99,6 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave { ) { this.currentSite = CoreSites.getRequiredCurrentSite(); this.remindersEnabled = CoreReminders.isEnabled(); - this.errors = { - required: Translate.instant('core.required'), - }; this.form = new FormGroup({}); diff --git a/src/addons/calendar/pages/settings/settings.html b/src/addons/calendar/pages/settings/settings.html index 7ca79cf28..7389d7f74 100644 --- a/src/addons/calendar/pages/settings/settings.html +++ b/src/addons/calendar/pages/settings/settings.html @@ -11,8 +11,9 @@ - {{ 'addon.calendar.defaultnotificationtime' | translate }} - + + {{ defaultTimeLabel }} diff --git a/src/addons/messageoutput/airnotifier/pages/devices/devices.html b/src/addons/messageoutput/airnotifier/pages/devices/devices.html index ffecacf69..f37297344 100644 --- a/src/addons/messageoutput/airnotifier/pages/devices/devices.html +++ b/src/addons/messageoutput/airnotifier/pages/devices/devices.html @@ -23,7 +23,7 @@ -

+

{{ device.name }} {{ device.model }} ({{platform.platform}} {{ device.version }})

{{ 'core.currentdevice' | translate }}

@@ -33,7 +33,8 @@

- +
diff --git a/src/addons/messages/pages/group-conversations/group-conversations.html b/src/addons/messages/pages/group-conversations/group-conversations.html index de0dd6db5..313ebb0b5 100644 --- a/src/addons/messages/pages/group-conversations/group-conversations.html +++ b/src/addons/messages/pages/group-conversations/group-conversations.html @@ -161,7 +161,8 @@

- +

diff --git a/src/addons/messages/pages/settings/settings.html b/src/addons/messages/pages/settings/settings.html index c5c8a9c40..c638b6e6b 100644 --- a/src/addons/messages/pages/settings/settings.html +++ b/src/addons/messages/pages/settings/settings.html @@ -22,21 +22,19 @@ - -

{{ 'addon.messages.useentertosend' | translate }}

-
- + + {{ 'addon.messages.useentertosend' | translate }} +
- - -

{{ 'addon.messages.blocknoncontacts' | translate }}

-
- + + + {{ 'addon.messages.blocknoncontacts' | translate }} + @@ -47,22 +45,19 @@ - -

{{ 'addon.messages.contactableprivacy_onlycontacts' | translate }}

-
- + + {{ 'addon.messages.contactableprivacy_onlycontacts' | translate }} +
- -

{{ 'addon.messages.contactableprivacy_coursemember' | translate }}

-
- + + {{ 'addon.messages.contactableprivacy_coursemember' | translate }} +
- -

{{ 'addon.messages.contactableprivacy_site' | translate }}

-
- + + {{ 'addon.messages.contactableprivacy_site' | translate }} +
diff --git a/src/addons/mod/assign/components/submission/addon-mod-assign-submission.html b/src/addons/mod/assign/components/submission/addon-mod-assign-submission.html index a0f9a4e70..0cf93f8f1 100644 --- a/src/addons/mod/assign/components/submission/addon-mod-assign-submission.html +++ b/src/addons/mod/assign/components/submission/addon-mod-assign-submission.html @@ -226,10 +226,9 @@ - + - - + @@ -277,22 +276,18 @@ - -

{{ 'addon.mod_assign.gradeoutof' | translate: {$a: gradeInfo!.grade} }}

-
-

{{ 'addon.mod_assign.gradelocked' | translate }}

+ [lang]="grade.lang" [label]="'addon.mod_assign.gradeoutof' | translate: {$a: gradeInfo!.grade}" + labelPlacement="stacked" + [helperText]="grade.disabled ? ('addon.mod_assign.gradelocked' | translate) : null" />
- -

{{ 'addon.mod_assign.grade' | translate }}

-
+

{{ 'addon.mod_assign.grade' | translate }}

{{grade.label}} @@ -301,12 +296,10 @@ - -

{{ outcome.name }}

-
+

{{ outcome.name }}

{{grade.label}} @@ -353,11 +346,10 @@ - +

{{ 'addon.mod_assign.groupsubmissionsettings' | translate }}

{{ 'addon.mod_assign.applytoteam' | translate }}

-
- +
@@ -380,18 +372,19 @@
- {{ 'addon.mod_assign.addattempt' | translate }} - + +

{{ 'addon.mod_assign.addattempt' | translate }}

+
- +

{{ 'addon.mod_assign.gradedby' | translate }}

-

{{ grader!.fullname }}

+

{{ grader.fullname }}

{{ feedback!.gradeddate * 1000 | coreFormatDate }}

diff --git a/src/addons/mod/assign/components/submission/submission.ts b/src/addons/mod/assign/components/submission/submission.ts index 4bf833519..9cd46da9f 100644 --- a/src/addons/mod/assign/components/submission/submission.ts +++ b/src/addons/mod/assign/components/submission/submission.ts @@ -1124,9 +1124,15 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can return []; } + // Receved submission statement should not be undefined. It would mean that the WS is not returning the value. const submissionStatementMissing = !!this.assign.requiresubmissionstatement && this.assign.submissionstatement === undefined; + // If received submission statement is empty, then it's not required. + if(!this.assign.submissionstatement && this.assign.submissionstatement !== undefined) { + this.assign.requiresubmissionstatement = 0; + } + this.canSubmit = !this.isSubmittedForGrading && !this.submittedOffline && (lastAttempt.cansubmit || (this.hasOffline && AddonModAssign.canSubmitOffline(this.assign, submissionStatus))); diff --git a/src/addons/mod/assign/pages/edit/edit.html b/src/addons/mod/assign/pages/edit/edit.html index a05415641..e1ed90813 100644 --- a/src/addons/mod/assign/pages/edit/edit.html +++ b/src/addons/mod/assign/pages/edit/edit.html @@ -38,10 +38,9 @@
- + - - + diff --git a/src/addons/mod/assign/pages/edit/edit.ts b/src/addons/mod/assign/pages/edit/edit.ts index b7677e451..1618d3918 100644 --- a/src/addons/mod/assign/pages/edit/edit.ts +++ b/src/addons/mod/assign/pages/edit/edit.ts @@ -205,6 +205,12 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy, CanLeave { this.introAttachments = submissionStatus.assignmentdata?.attachments?.intro ?? this.assign.introattachments; this.allowOffline = true; // If offline isn't allowed we shouldn't have reached this point. + + // If received submission statement is empty, then it's not required. + if(!this.assign.submissionstatement && this.assign.submissionstatement !== undefined) { + this.assign.requiresubmissionstatement = 0; + } + // Only show submission statement if we are editing our own submission. if (this.assign.requiresubmissionstatement && !this.assign.submissiondrafts && this.userId == currentUserId) { this.submissionStatement = this.assign.submissionstatement; diff --git a/src/addons/mod/chat/pages/sessions/sessions.html b/src/addons/mod/chat/pages/sessions/sessions.html index 8fc39d7c1..c85c3d68c 100644 --- a/src/addons/mod/chat/pages/sessions/sessions.html +++ b/src/addons/mod/chat/pages/sessions/sessions.html @@ -17,8 +17,9 @@ - {{ 'addon.mod_chat.showincompletesessions' | translate }} - + + {{ 'addon.mod_chat.showincompletesessions' | translate }} + - + - - + - + - - + @@ -147,7 +145,7 @@ -

+

{{ 'addon.mod_choice.full' | translate }} diff --git a/src/addons/mod/data/components/search/search.html b/src/addons/mod/data/components/search/search.html index 4071d5917..479fb2eb3 100644 --- a/src/addons/mod/data/components/search/search.html +++ b/src/addons/mod/data/components/search/search.html @@ -12,20 +12,20 @@ - {{ 'addon.mod_data.advancedsearch' | translate }} - + + {{ 'addon.mod_data.advancedsearch' | translate }} + - {{ 'addon.mod_data.search' | translate}} - + - {{ 'core.sortby' | translate }} - + {{field.name}} @@ -41,14 +41,16 @@ - + - {{ 'addon.mod_data.ascending' | translate }} - + + {{ 'addon.mod_data.ascending' | translate }} + - {{ 'addon.mod_data.descending' | translate }} - + + {{'addon.mod_data.descending' | translate}} + diff --git a/src/addons/mod/data/data-forms.scss b/src/addons/mod/data/data-forms.scss index 92f6ff9fa..bc50e228f 100644 --- a/src/addons/mod/data/data-forms.scss +++ b/src/addons/mod/data/data-forms.scss @@ -16,6 +16,12 @@ .addon-data-latlong { display: flex; + + .input-units { + flex-grow: 1; + white-space: nowrap; + align-self: center; + } } } diff --git a/src/addons/mod/data/fields/checkbox/component/addon-mod-data-field-checkbox.html b/src/addons/mod/data/fields/checkbox/component/addon-mod-data-field-checkbox.html index abca23146..76533f6a0 100644 --- a/src/addons/mod/data/fields/checkbox/component/addon-mod-data-field-checkbox.html +++ b/src/addons/mod/data/fields/checkbox/component/addon-mod-data-field-checkbox.html @@ -3,13 +3,17 @@ - {{option.key}} + + + - - {{ 'addon.mod_data.selectedrequired' | translate }} - + + + {{ 'addon.mod_data.selectedrequired' | translate }} + diff --git a/src/addons/mod/data/fields/date/component/addon-mod-data-field-date.html b/src/addons/mod/data/fields/date/component/addon-mod-data-field-date.html index 5e2b2c817..9e9378121 100644 --- a/src/addons/mod/data/fields/date/component/addon-mod-data-field-date.html +++ b/src/addons/mod/data/fields/date/component/addon-mod-data-field-date.html @@ -10,9 +10,10 @@ - - {{ 'addon.mod_data.usedate' | translate }} - + + + {{ 'addon.mod_data.usedate' | translate }} + diff --git a/src/addons/mod/data/fields/latlong/component/addon-mod-data-field-latlong.html b/src/addons/mod/data/fields/latlong/component/addon-mod-data-field-latlong.html index eee88521b..69cc66907 100644 --- a/src/addons/mod/data/fields/latlong/component/addon-mod-data-field-latlong.html +++ b/src/addons/mod/data/fields/latlong/component/addon-mod-data-field-latlong.html @@ -3,13 +3,13 @@ -

+
- °N +
°N
-
+
- °E +
°E
diff --git a/src/addons/mod/data/fields/menu/component/addon-mod-data-field-menu.html b/src/addons/mod/data/fields/menu/component/addon-mod-data-field-menu.html index cc2184808..76391c5e2 100644 --- a/src/addons/mod/data/fields/menu/component/addon-mod-data-field-menu.html +++ b/src/addons/mod/data/fields/menu/component/addon-mod-data-field-menu.html @@ -3,7 +3,10 @@ {{ 'addon.mod_data.menuchoose' | translate }} - {{option}} + + + diff --git a/src/addons/mod/data/fields/multimenu/component/addon-mod-data-field-multimenu.html b/src/addons/mod/data/fields/multimenu/component/addon-mod-data-field-multimenu.html index 455677ce0..d7b459a7c 100644 --- a/src/addons/mod/data/fields/multimenu/component/addon-mod-data-field-multimenu.html +++ b/src/addons/mod/data/fields/multimenu/component/addon-mod-data-field-multimenu.html @@ -3,14 +3,18 @@ - {{option.key}} + + + - - {{ 'addon.mod_data.selectedrequired' | translate }} - + + + {{ 'addon.mod_data.selectedrequired' | translate }} + diff --git a/src/addons/mod/data/fields/picture/component/addon-mod-data-field-picture.html b/src/addons/mod/data/fields/picture/component/addon-mod-data-field-picture.html index 99cfcd004..52291469f 100644 --- a/src/addons/mod/data/fields/picture/component/addon-mod-data-field-picture.html +++ b/src/addons/mod/data/fields/picture/component/addon-mod-data-field-picture.html @@ -4,8 +4,8 @@ [allowOffline]="true" acceptedTypes="image" [courseId]="database?.course" /> - {{ 'addon.mod_data.alttext' | translate }} - + diff --git a/src/addons/mod/data/fields/radiobutton/component/addon-mod-data-field-radiobutton.html b/src/addons/mod/data/fields/radiobutton/component/addon-mod-data-field-radiobutton.html index 1f51004cc..ced96a13f 100644 --- a/src/addons/mod/data/fields/radiobutton/component/addon-mod-data-field-radiobutton.html +++ b/src/addons/mod/data/fields/radiobutton/component/addon-mod-data-field-radiobutton.html @@ -4,7 +4,10 @@ [cancelText]="'core.cancel' | translate" [okText]="'core.ok' | translate" [interfaceOptions]="{header: field.name}" interface="alert"> {{ 'addon.mod_data.menuchoose' | translate }} - {{option}} + + + diff --git a/src/addons/mod/feedback/pages/form/form.html b/src/addons/mod/feedback/pages/form/form.html index 0f6671a84..e03f78b9b 100644 --- a/src/addons/mod/feedback/pages/form/form.html +++ b/src/addons/mod/feedback/pages/form/form.html @@ -26,37 +26,40 @@ - -

- {{item.itemnumber}}. - - {{item.postfix}} -

+ +

- + + + - + + + {{ 'addon.mod_feedback.numberoutofrange' | translate }} [{{item.rangefrom}} , {{item.rangeto}}] - + + + - + @@ -66,23 +69,21 @@ - - + + - - + - + - - + @@ -152,3 +153,13 @@
+ + + +

+ {{item.itemnumber}}. + + {{item.postfix}} +

+
diff --git a/src/addons/mod/feedback/services/feedback-helper.ts b/src/addons/mod/feedback/services/feedback-helper.ts index 18dddff57..8b7f6d58a 100644 --- a/src/addons/mod/feedback/services/feedback-helper.ts +++ b/src/addons/mod/feedback/services/feedback-helper.ts @@ -251,7 +251,7 @@ export class AddonModFeedbackHelperProvider { return Object.assign(item, { templateName: 'label', value: '', - hasTextInput: false, + slottedLabel: false, }); } @@ -265,7 +265,7 @@ export class AddonModFeedbackHelperProvider { const formItem: AddonModFeedbackFormBasicItem = Object.assign(item, { templateName: 'label', value: '', - hasTextInput: false, + slottedLabel: false, }); const type = parseInt(formItem.presentation, 10); @@ -304,7 +304,7 @@ export class AddonModFeedbackHelperProvider { value: item.rawValue !== undefined ? Number(item.rawValue) : '', rangefrom: typeof rangeFrom == 'number' && !isNaN(rangeFrom) ? range[0] : '', rangeto: typeof rangeTo == 'number' && !isNaN(rangeTo) ? rangeTo : '', - hasTextInput: true, + slottedLabel: true, }); formItem.postfix = this.getNumericBoundariesForDisplay(formItem.rangefrom, formItem.rangeto); @@ -322,7 +322,7 @@ export class AddonModFeedbackHelperProvider { templateName: 'textfield', length: Number(item.presentation.split(AddonModFeedbackProvider.LINE_SEP)[1]) || 255, value: item.rawValue !== undefined ? item.rawValue : '', - hasTextInput: true, + slottedLabel: true, }); } @@ -336,7 +336,7 @@ export class AddonModFeedbackHelperProvider { return Object.assign(item, { templateName: 'textarea', value: item.rawValue !== undefined ? item.rawValue : '', - hasTextInput: true, + slottedLabel: true, }); } @@ -356,7 +356,7 @@ export class AddonModFeedbackHelperProvider { subtype: subType, value: '', choices: [], - hasTextInput: false, + slottedLabel: subType === 'd', }); formItem.presentation = parts.length > 1 ? parts[1] : ''; @@ -411,7 +411,7 @@ export class AddonModFeedbackHelperProvider { const formItem: AddonModFeedbackCaptchaItem = Object.assign(item, { templateName: 'captcha', value: '', - hasTextInput: false, + slottedLabel: false, }); const data = CoreTextUtils.parseJSON(item.otherdata); @@ -549,7 +549,7 @@ export type AddonModFeedbackFormItem = export type AddonModFeedbackFormBasicItem = AddonModFeedbackItem & { templateName: string; value: AddonModFeedbackResponseValue; - hasTextInput: boolean; + slottedLabel: boolean; isEmpty?: boolean; hasError?: boolean; }; diff --git a/src/addons/mod/forum/components/post/post.html b/src/addons/mod/forum/components/post/post.html index 327984298..d20baf0a8 100644 --- a/src/addons/mod/forum/components/post/post.html +++ b/src/addons/mod/forum/components/post/post.html @@ -94,9 +94,9 @@ - - {{ 'addon.mod_forum.subject' | translate }} - + + {{ 'addon.mod_forum.message' | translate }} @@ -106,8 +106,9 @@ [draftExtraParams]="{reply: post.id}" (contentChanged)="onMessageChange($event)" /> - {{ 'addon.mod_forum.privatereply' | translate }} - + + {{ 'addon.mod_forum.privatereply' | translate }} + - {{ 'addon.mod_forum.subject' | translate }} - + +

{{ 'addon.mod_forum.subject' | translate }}

+
{{ 'addon.mod_forum.message' | translate }} @@ -38,27 +39,30 @@
- {{ 'addon.mod_forum.posttomygroups' | translate }} - + + {{ 'addon.mod_forum.posttomygroups' | translate }} + - - {{ 'addon.mod_forum.group' | translate }} + +

{{ 'addon.mod_forum.group' | translate }}

- - {{ 'addon.mod_forum.discussionsubscription' | translate }} - + + + {{ 'addon.mod_forum.discussionsubscription' | translate }} + - - {{ 'addon.mod_forum.discussionpinned' | translate }} - + + + {{ 'addon.mod_forum.discussionpinned' | translate }} +
- + - {{ 'addon.mod_workshop.gradinggradeover' | translate }} - + {{grade.label}} diff --git a/src/addons/mod/workshop/pages/edit-submission/edit-submission.html b/src/addons/mod/workshop/pages/edit-submission/edit-submission.html index c28b405f8..5c88ef4d2 100644 --- a/src/addons/mod/workshop/pages/edit-submission/edit-submission.html +++ b/src/addons/mod/workshop/pages/edit-submission/edit-submission.html @@ -17,20 +17,19 @@ - - + +
{{ 'addon.mod_workshop.submissiontitle' | translate }} - - - +
+
- +
{{ 'addon.mod_workshop.submissioncontent' | translate }} - +
- +

{{ 'addon.mod_workshop.publishsubmission' | translate }}

{{ 'addon.mod_workshop.publishsubmission_help' | translate }}

-
- +
@@ -114,9 +113,9 @@ - {{ 'addon.mod_workshop.gradeover' | translate }} - + {{grade.label}} diff --git a/src/addons/notes/components/add/add-modal.html b/src/addons/notes/components/add/add-modal.html index f806e1b4e..e247a4fb2 100644 --- a/src/addons/notes/components/add/add-modal.html +++ b/src/addons/notes/components/add/add-modal.html @@ -13,16 +13,15 @@ - {{ 'addon.notes.publishstate' | translate }} - - {{ 'addon.notes.personalnotes' | translate }} + + {{ 'addon.notes.personalnotes' | translate }} {{ 'addon.notes.coursenotes' | translate }} {{ 'addon.notes.sitenotes' | translate }} - {{ 'addon.notes.note' | translate }} - +
diff --git a/src/addons/notifications/pages/settings/settings.html b/src/addons/notifications/pages/settings/settings.html index 16d12064c..0348dcf1c 100644 --- a/src/addons/notifications/pages/settings/settings.html +++ b/src/addons/notifications/pages/settings/settings.html @@ -22,26 +22,22 @@ - +

{{ 'addon.notifications.allownotifications' | translate }}

-
- +
- +

{{ 'addon.notifications.playsound' | translate }}

-
- +
- - -

{{ 'addon.notifications.typeofnotification' | translate }}

-
+ +

{{ 'addon.notifications.typeofnotification' | translate }}

{{ processor.displayname }} diff --git a/src/addons/qbehaviour/deferredcbm/component/addon-qbehaviour-deferredcbm.html b/src/addons/qbehaviour/deferredcbm/component/addon-qbehaviour-deferredcbm.html index a41071878..36dc18ff1 100644 --- a/src/addons/qbehaviour/deferredcbm/component/addon-qbehaviour-deferredcbm.html +++ b/src/addons/qbehaviour/deferredcbm/component/addon-qbehaviour-deferredcbm.html @@ -7,8 +7,9 @@ - {{ option.text }} - + + {{ option.text }} + diff --git a/src/addons/qtype/calculated/component/addon-qtype-calculated.html b/src/addons/qtype/calculated/component/addon-qtype-calculated.html index bb5fb9136..9767e13cc 100644 --- a/src/addons/qtype/calculated/component/addon-qtype-calculated.html +++ b/src/addons/qtype/calculated/component/addon-qtype-calculated.html @@ -12,18 +12,16 @@ - {{ 'addon.mod_quiz.answercolon' | translate }} - -
+
- + [disabled]="question.input.readOnly" autocorrect="off" [label]="'addon.mod_quiz.answercolon' | translate" /> @@ -58,9 +56,10 @@ - {{ option.text }} - + + {{ option.text }} + diff --git a/src/addons/qtype/calculated/component/calculated.scss b/src/addons/qtype/calculated/component/calculated.scss new file mode 100644 index 000000000..da82b8552 --- /dev/null +++ b/src/addons/qtype/calculated/component/calculated.scss @@ -0,0 +1,3 @@ +.flex-row { + width: 100%; +} diff --git a/src/addons/qtype/calculated/component/calculated.ts b/src/addons/qtype/calculated/component/calculated.ts index 4fb301733..18c064819 100644 --- a/src/addons/qtype/calculated/component/calculated.ts +++ b/src/addons/qtype/calculated/component/calculated.ts @@ -22,6 +22,7 @@ import { AddonModQuizCalculatedQuestion, CoreQuestionBaseComponent } from '@feat @Component({ selector: 'addon-qtype-calculated', templateUrl: 'addon-qtype-calculated.html', + styleUrls: ['calculated.scss'], }) export class AddonQtypeCalculatedComponent extends CoreQuestionBaseComponent { diff --git a/src/addons/qtype/essay/component/addon-qtype-essay.html b/src/addons/qtype/essay/component/addon-qtype-essay.html index 452f716f8..b3c8b906f 100644 --- a/src/addons/qtype/essay/component/addon-qtype-essay.html +++ b/src/addons/qtype/essay/component/addon-qtype-essay.html @@ -11,19 +11,18 @@ - {{ 'core.question.answer' | translate }} - + - + diff --git a/src/addons/qtype/match/component/addon-qtype-match.html b/src/addons/qtype/match/component/addon-qtype-match.html index 28b81e9d5..cec385a0b 100644 --- a/src/addons/qtype/match/component/addon-qtype-match.html +++ b/src/addons/qtype/match/component/addon-qtype-match.html @@ -6,17 +6,17 @@ - - - - - +
+ + +
{{option.label}} diff --git a/src/addons/qtype/multichoice/component/addon-qtype-multichoice.html b/src/addons/qtype/multichoice/component/addon-qtype-multichoice.html index a6b5d868f..c5daf7e3d 100644 --- a/src/addons/qtype/multichoice/component/addon-qtype-multichoice.html +++ b/src/addons/qtype/multichoice/component/addon-qtype-multichoice.html @@ -16,21 +16,21 @@ - - -
- + +
+ +
+ +
- +
- - - - @@ -41,21 +41,21 @@ - - -
- + +
+ +
+ +
- +
- - - - - {{ 'addon.mod_quiz.answercolon' | translate }} - + diff --git a/src/addons/userprofilefield/checkbox/component/addon-user-profile-field-checkbox.html b/src/addons/userprofilefield/checkbox/component/addon-user-profile-field-checkbox.html index f4a639077..5b8775019 100644 --- a/src/addons/userprofilefield/checkbox/component/addon-user-profile-field-checkbox.html +++ b/src/addons/userprofilefield/checkbox/component/addon-user-profile-field-checkbox.html @@ -16,12 +16,11 @@ - - + + - - - + + diff --git a/src/addons/userprofilefield/menu/component/addon-user-profile-field-menu.html b/src/addons/userprofilefield/menu/component/addon-user-profile-field-menu.html index 545f8938b..d051d51cf 100644 --- a/src/addons/userprofilefield/menu/component/addon-user-profile-field-menu.html +++ b/src/addons/userprofilefield/menu/component/addon-user-profile-field-menu.html @@ -14,14 +14,12 @@ - - + +
- - - +
{{ 'core.choosedots' | translate }} {{option}}
diff --git a/src/addons/userprofilefield/social/component/addon-user-profile-field-social.html b/src/addons/userprofilefield/social/component/addon-user-profile-field-social.html index 8cffbf860..4a06329de 100644 --- a/src/addons/userprofilefield/social/component/addon-user-profile-field-social.html +++ b/src/addons/userprofilefield/social/component/addon-user-profile-field-social.html @@ -14,12 +14,11 @@ - - + +
- - - +
+
diff --git a/src/addons/userprofilefield/text/component/addon-user-profile-field-text.html b/src/addons/userprofilefield/text/component/addon-user-profile-field-text.html index 123ac8566..8c5f3e1ab 100644 --- a/src/addons/userprofilefield/text/component/addon-user-profile-field-text.html +++ b/src/addons/userprofilefield/text/component/addon-user-profile-field-text.html @@ -14,12 +14,12 @@ - - + +
- - - +
+
diff --git a/src/addons/userprofilefield/textarea/component/addon-user-profile-field-textarea.html b/src/addons/userprofilefield/textarea/component/addon-user-profile-field-textarea.html index 6077c5990..f56a7ecc9 100644 --- a/src/addons/userprofilefield/textarea/component/addon-user-profile-field-textarea.html +++ b/src/addons/userprofilefield/textarea/component/addon-user-profile-field-textarea.html @@ -19,8 +19,8 @@
-
+
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 0c3b63393..f6176bf38 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -59,7 +59,8 @@ export class AppComponent implements OnInit, AfterViewInit { ngOnInit(): void { // eslint-disable-next-line @typescript-eslint/no-explicit-any const win = window; - CoreDomUtils.toggleModeClass('ionic5', true, { includeLegacy: true }); + CoreDomUtils.toggleModeClass('ionic7', true, { includeLegacy: true }); + CoreDomUtils.toggleModeClass('development', CoreConstants.BUILD.isDevelopment); this.addVersionClass(MOODLEAPP_VERSION_PREFIX, CoreConstants.CONFIG.versionname.replace('-dev', '')); CoreEvents.on(CoreEvents.LOGOUT, async () => { diff --git a/src/core/components/combobox/combobox.ts b/src/core/components/combobox/combobox.ts index 05d0d7d25..97414ae21 100644 --- a/src/core/components/combobox/combobox.ts +++ b/src/core/components/combobox/combobox.ts @@ -51,7 +51,7 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; }) export class CoreComboboxComponent implements ControlValueAccessor { - @ViewChild(IonSelect) select!: IonSelect; + @ViewChild(IonSelect) select?: IonSelect; @Input() interface: 'popover' | 'modal' = 'popover'; @Input() label = Translate.instant('core.show'); // Aria label. @@ -118,7 +118,7 @@ export class CoreComboboxComponent implements ControlValueAccessor { async openSelect(event?: UIEvent): Promise { this.touch(); - if (this.interface == 'modal') { + if (this.interface === 'modal') { if (this.expanded || !this.modalOptions) { return; } diff --git a/src/core/components/group-selector/group-selector.html b/src/core/components/group-selector/group-selector.html index 300db0750..d3904dac2 100644 --- a/src/core/components/group-selector/group-selector.html +++ b/src/core/components/group-selector/group-selector.html @@ -7,12 +7,9 @@ - - {{'core.groupsseparate' | translate }} - {{'core.groupsvisible' | translate }} - - + diff --git a/src/core/components/input-errors/core-input-errors.html b/src/core/components/input-errors/core-input-errors.html index 9bee393c3..c4a3a8a07 100644 --- a/src/core/components/input-errors/core-input-errors.html +++ b/src/core/components/input-errors/core-input-errors.html @@ -1,16 +1,14 @@ - + +
{{ errorText }}
diff --git a/src/core/components/input-errors/input-errors.scss b/src/core/components/input-errors/input-errors.scss index 0d73958b9..aeb2e8fd2 100644 --- a/src/core/components/input-errors/input-errors.scss +++ b/src/core/components/input-errors/input-errors.scss @@ -1,17 +1,18 @@ :host { display: contents; - .core-input-error-container { + &.has-errors { + display: block; width: 100%; + } - .core-input-error { - padding: 4px; - color: var(--danger); - font-size: 12px; - display: none; + .core-input-error { + padding: 4px; + color: var(--danger); + font-size: 12px; + display: none; - &:first-child { - display: block; - } + &:first-child { + display: block; } } } diff --git a/src/core/components/input-errors/input-errors.ts b/src/core/components/input-errors/input-errors.ts index 0458c7cc7..570386555 100644 --- a/src/core/components/input-errors/input-errors.ts +++ b/src/core/components/input-errors/input-errors.ts @@ -12,9 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, Input, OnChanges, SimpleChange } from '@angular/core'; +import { Component, ElementRef, HostBinding, Input, OnChanges, OnInit, SimpleChange } from '@angular/core'; import { FormControl } from '@angular/forms'; -import { Translate } from '@singletons'; /** * Component to show errors if an input isn't valid. @@ -30,8 +29,7 @@ import { Translate } from '@singletons'; * Example usage: * * - * {{ 'core.login.username' | translate }} - * + * * * */ @@ -40,43 +38,87 @@ import { Translate } from '@singletons'; templateUrl: 'core-input-errors.html', styleUrls: ['input-errors.scss'], }) -export class CoreInputErrorsComponent implements OnChanges { +export class CoreInputErrorsComponent implements OnInit, OnChanges { - @Input() control?: FormControl; - @Input() errorMessages?: Record; - @Input() errorText?: string; // Set other non automatic errors. + @Input() control?: FormControl; // Needed to be able to check the validity of the input. + @Input() errorMessages: Record = {}; // Error messages to show. Keys must be the name of the error. + @Input() errorText = ''; // Set other non automatic errors. errorKeys: string[] = []; + protected hostElement: HTMLElement; + + @HostBinding('class.has-errors') + get hasErrors(): boolean { + return (this.control && this.control.dirty && !this.control.valid) || !!this.errorText; + } + + @HostBinding('role') role = 'alert'; + + constructor( + element: ElementRef, + ) { + this.hostElement = element.nativeElement; + } + /** * Initialize some common errors if they aren't set. */ protected initErrorMessages(): void { - this.errorMessages = this.errorMessages || {}; + this.errorMessages = { + required: this.errorMessages.required || 'core.required', + email: this.errorMessages.email || 'core.login.invalidemail', + date: this.errorMessages.date || 'core.login.invaliddate', + datetime: this.errorMessages.datetime || 'core.login.invaliddate', + datetimelocal: this.errorMessages.datetimelocal || 'core.login.invaliddate', + time: this.errorMessages.time || 'core.login.invalidtime', + url: this.errorMessages.url || 'core.login.invalidurl', + // Set empty values by default, the default error messages will be built in the template when needed. + max: this.errorMessages.max || '', + min: this.errorMessages.min || '', + }; - this.errorMessages.required = this.errorMessages.required || Translate.instant('core.required'); - this.errorMessages.email = this.errorMessages.email || Translate.instant('core.login.invalidemail'); - this.errorMessages.date = this.errorMessages.date || Translate.instant('core.login.invaliddate'); - this.errorMessages.datetime = this.errorMessages.datetime || Translate.instant('core.login.invaliddate'); - this.errorMessages.datetimelocal = this.errorMessages.datetimelocal || Translate.instant('core.login.invaliddate'); - this.errorMessages.time = this.errorMessages.time || Translate.instant('core.login.invalidtime'); - this.errorMessages.url = this.errorMessages.url || Translate.instant('core.login.invalidurl'); + this.errorMessages.requiredTrue = this.errorMessages.required; - // Set empty values by default, the default error messages will be built in the template when needed. - this.errorMessages.max = this.errorMessages.max || ''; - this.errorMessages.min = this.errorMessages.min || ''; + this.errorKeys = Object.keys(this.errorMessages); } /** - * Component being changed. + * @inheritdoc + */ + ngOnInit(): void { + const parent = this.hostElement.parentElement; + let item: HTMLElement | null = null; + + if (parent?.tagName === 'ION-ITEM') { + item = parent; + + // Get all elements on the parent and wrap them with a div. + // This is needed because otherwise the error message will be shown on the right of the input. Or overflowing the item. + const wrapper = document.createElement('div'); + + wrapper.classList.add('core-input-errors-wrapper'); + + Array.from(parent.children).forEach((child) => { + if (!child.slot) { + wrapper.appendChild(child); + } + }); + + parent.appendChild(wrapper); + } else { + item = this.hostElement.closest('ion-item'); + } + + item?.classList.add('has-core-input-errors'); + + } + + /** + * @inheritdoc */ ngOnChanges(changes: { [name: string]: SimpleChange }): void { if ((changes.control || changes.errorMessages) && this.control) { this.initErrorMessages(); - - this.errorKeys = this.errorMessages ? Object.keys(this.errorMessages) : []; - } - if (changes.errorText) { - this.errorText = changes.errorText.currentValue; } } diff --git a/src/core/components/loading/loading.scss b/src/core/components/loading/loading.scss index 923321dda..1c86d60ca 100644 --- a/src/core/components/loading/loading.scss +++ b/src/core/components/loading/loading.scss @@ -86,12 +86,3 @@ // Implicit Inline. @include inline(); } - -:host-context(.limited-width > *):not([slot]), -:host-context(.menu > *):not([slot]) { - &.core-loading-loaded { - --contents-display: flex; - flex-direction: column; - } - min-height: 100%; -} diff --git a/src/core/components/local-file/core-local-file.html b/src/core/components/local-file/core-local-file.html index 01f2dee0a..a0933b39a 100644 --- a/src/core/components/local-file/core-local-file.html +++ b/src/core/components/local-file/core-local-file.html @@ -18,7 +18,8 @@ + (click)="$event.stopPropagation()" core-auto-focus [(ngModel)]="newFileName" *ngIf="editMode" + [attr.aria-label]="'core.filename' | translate" />
{{ 'core.login.username' | translate }} + *

Username

*/ @Component({ selector: '[core-mark-required]', @@ -37,41 +37,43 @@ export class CoreMarkRequiredComponent implements OnInit, AfterViewInit { @Input('core-mark-required') coreMarkRequired: boolean | string = true; - protected element: HTMLElement; - requiredLabel?: string; + protected hostElement: HTMLElement; + requiredLabel = Translate.instant('core.required'); constructor( element: ElementRef, ) { - this.element = element.nativeElement; + this.hostElement = element.nativeElement; } /** * @inheritdoc */ ngOnInit(): void { - this.requiredLabel = Translate.instant('core.required'); this.coreMarkRequired = CoreUtils.isTrueOrOne(this.coreMarkRequired); } /** - * Called after the view is initialized. + * @inheritdoc */ ngAfterViewInit(): void { if (this.coreMarkRequired) { // Add the "required" to the aria-label. - const ariaLabel = this.element.getAttribute('aria-label') || - CoreTextUtils.cleanTags(this.element.innerHTML, { singleLine: true }); + const ariaLabel = this.hostElement.getAttribute('aria-label') || + CoreTextUtils.cleanTags(this.hostElement.innerHTML, { singleLine: true }); if (ariaLabel) { - this.element.setAttribute('aria-label', ariaLabel + ' ' + this.requiredLabel); + this.hostElement.setAttribute('aria-label', ariaLabel + '. ' + this.requiredLabel); } } else { // Remove the "required" from the aria-label. - const ariaLabel = this.element.getAttribute('aria-label'); + const ariaLabel = this.hostElement.getAttribute('aria-label'); if (ariaLabel) { - this.element.setAttribute('aria-label', ariaLabel.replace(' ' + this.requiredLabel, '')); + this.hostElement.setAttribute('aria-label', ariaLabel.replace('. ' + this.requiredLabel, '')); } } + + const input = this.hostElement.closest('ion-input, ion-textarea'); + input?.setAttribute('required', this.coreMarkRequired ? 'true' : 'false'); } } diff --git a/src/core/components/password-modal/password-modal.html b/src/core/components/password-modal/password-modal.html index 95629d7ab..d5a1c2dea 100644 --- a/src/core/components/password-modal/password-modal.html +++ b/src/core/components/password-modal/password-modal.html @@ -14,11 +14,11 @@
- {{ placeholder | translate }} - - - + + + diff --git a/src/core/components/show-password/core-show-password.html b/src/core/components/show-password/core-show-password.html index ed3fb385f..362f23d41 100644 --- a/src/core/components/show-password/core-show-password.html +++ b/src/core/components/show-password/core-show-password.html @@ -1,4 +1,4 @@ - +
+ [placeholder]="placeholder" [attr.aria-labelledby]="ariaLabelledBy" (ionChange)="onChange()" (ionFocus)="showToolbar($event)" + (ionBlur)="hideToolbar($event)" />