Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mobile 3947 #3864

Merged
merged 8 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,5 @@ module.exports = {
'!src/testing/**/*',
],
transformIgnorePatterns: ['node_modules/(?!@stencil|@angular|@ionic|@moodlehq|@ngx-translate|swiper)'],
moduleNameMapper: {
...pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/src/' }),
'^!raw-loader!.*': 'jest-raw-loader',
},
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/src/' }),
};
7 changes: 0 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@
"gulp-slash": "^1.1.3",
"jest": "^29.7.0",
"jest-preset-angular": "^13.1.4",
"jest-raw-loader": "^1.0.1",
"jsonc-parser": "^2.3.1",
"keytar": "^7.2.0",
"minimatch": "^5.1.0",
Expand Down
22 changes: 17 additions & 5 deletions src/addons/calendar/pages/edit-event/edit-event.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,14 @@ <h1>{{ title | translate }}</h1>
<ion-label position="stacked">
<p class="item-heading" [core-mark-required]="true">{{ 'core.date' | translate }}</p>
</ion-label>
<ion-datetime formControlName="timestart" [placeholder]="'core.date' | translate" [displayFormat]="dateFormat"
[max]="maxDate" [min]="minDate" [displayTimezone]="displayTimezone" />
<ion-datetime-button datetime="timestart" />
<ion-modal [keepContentsMounted]="true">
<ng-template>
<ion-datetime id="timestart" formControlName="timestart" presentation="date-time" [max]="maxDate" [min]="minDate">
<span slot="title">{{'core.date' | translate}}</span>
</ion-datetime>
</ng-template>
</ion-modal>
<core-input-errors [control]="form.controls.timestart" [errorMessages]="errors" />
</ion-item>

Expand Down Expand Up @@ -154,9 +160,15 @@ <h1>{{ title | translate }}</h1>
</ion-item>
<ion-item *ngIf="form.controls.duration.value === 1">
<ion-label position="stacked" />
<ion-datetime formControlName="timedurationuntil" [max]="maxDate" [min]="minDate"
[placeholder]="'addon.calendar.durationuntil' | translate" [displayFormat]="dateFormat"
[displayTimezone]="displayTimezone" />
<ion-datetime-button datetime="timedurationuntil" />
<ion-modal [keepContentsMounted]="true">
<ng-template>
<ion-datetime id="timedurationuntil" formControlName="timedurationuntil" [max]="maxDate" [min]="minDate"
presentation="date-time">
<span slot="title">{{'addon.calendar.durationuntil' | translate}}</span>
</ion-datetime>
</ng-template>
</ion-modal>
</ion-item>
<ion-item>
<ion-label>
Expand Down
8 changes: 0 additions & 8 deletions src/addons/calendar/pages/edit-event/edit-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import { CoreForms } from '@singletons/form';
import { CoreReminders, CoreRemindersService, CoreRemindersUnits } from '@features/reminders/services/reminders';
import { CoreRemindersSetReminderMenuComponent } from '@features/reminders/components/set-reminder-menu/set-reminder-menu';
import moment from 'moment-timezone';
import { CoreAppProvider } from '@services/app';

/**
* Page that displays a form to create/edit an event.
Expand All @@ -61,7 +60,6 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave {
@ViewChild('editEventForm') formElement!: ElementRef;

title = 'addon.calendar.newevent';
dateFormat: string;
component = AddonCalendarProvider.COMPONENT;
loaded = false;
hasOffline = false;
Expand All @@ -78,7 +76,6 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave {
eventId?: number;
maxDate: string;
minDate: string;
displayTimezone?: string;

// Form variables.
form: FormGroup;
Expand Down Expand Up @@ -107,11 +104,6 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave {
required: Translate.instant('core.required'),
};

// Calculate format to use. ion-datetime doesn't support escaping characters ([]), so we remove them.
this.dateFormat = CoreTimeUtils.convertPHPToMoment(Translate.instant('core.strftimedatetimeshort'))
.replace(/[[\]]/g, '');
this.displayTimezone = CoreAppProvider.getForcedTimezone();

this.form = new FormGroup({});

// Initialize form variables.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
<span *ngIf="inputMode && form" [formGroup]="form">
<span *ngIf="inputMode && form && searchFields" [formGroup]="form">
<span *ngIf="editMode" [core-mark-required]="field.required" class="core-mark-required"></span>
<ion-datetime [formControlName]="'f_'+field.id" [placeholder]="'core.date' | translate" [max]="maxDate" [min]="minDate"
[disabled]="searchMode && !searchFields!['f_'+field.id+'_z']" [displayFormat]="format" [displayTimezone]="displayTimezone" />

<ion-datetime-button datetime="datetime" />
<ion-modal [keepContentsMounted]="true">
<ng-template>
<ion-datetime id="datetime" [formControlName]="'f_'+field.id" [max]="maxDate" [min]="minDate"
[disabled]="searchMode && !searchFields['f_'+field.id+'_z']" presentation="date" />
</ng-template>
</ion-modal>
<core-input-errors *ngIf="error && editMode" [control]="form.controls['f_'+field.id]" [errorText]="error" />

<ion-item *ngIf="searchMode">
<ion-label>{{ 'addon.mod_data.usedate' | translate }}</ion-label>
<ion-checkbox slot="end" [formControlName]="'f_'+field.id+'_z'" [(ngModel)]="searchFields!['f_'+field.id+'_z']" />
<ion-checkbox slot="end" [formControlName]="'f_'+field.id+'_z'" [(ngModel)]="searchFields['f_'+field.id+'_z']" />
</ion-item>
</span>

Expand Down
19 changes: 5 additions & 14 deletions src/addons/mod/data/fields/date/component/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
// limitations under the License.

import { Component } from '@angular/core';
import { CoreAppProvider } from '@services/app';
import { CoreTimeUtils } from '@services/utils/time';
import { Translate } from '@singletons';
import moment, { Moment } from 'moment-timezone';
import { AddonModDataFieldPluginBaseComponent } from '../../../classes/base-field-plugin-component';

Expand All @@ -28,11 +26,9 @@ import { AddonModDataFieldPluginBaseComponent } from '../../../classes/base-fiel
})
export class AddonModDataFieldDateComponent extends AddonModDataFieldPluginBaseComponent {

format!: string;
displayDate?: number;
maxDate?: string;
minDate?: string;
displayTimezone?: string;

/**
* @inheritdoc
Expand All @@ -48,23 +44,18 @@ export class AddonModDataFieldDateComponent extends AddonModDataFieldPluginBaseC

let momentInstance: Moment;

// Calculate format to use.
this.format = CoreTimeUtils.fixFormatForDatetime(CoreTimeUtils.convertPHPToMoment(
Translate.instant('core.strftimedate'),
));
this.maxDate = CoreTimeUtils.getDatetimeDefaultMax();
this.minDate = CoreTimeUtils.getDatetimeDefaultMin();
this.displayTimezone = CoreAppProvider.getForcedTimezone();

if (this.searchMode) {
if (this.searchMode && this.searchFields) {
this.addControl('f_' + this.field.id + '_z');

momentInstance = this.searchFields!['f_' + this.field.id + '_y']
? moment(this.searchFields!['f_' + this.field.id + '_y'] + '-' +
this.searchFields!['f_' + this.field.id + '_m'] + '-' + this.searchFields!['f_' + this.field.id + '_d'])
momentInstance = this.searchFields['f_' + this.field.id + '_y']
? moment(this.searchFields['f_' + this.field.id + '_y'] + '-' +
this.searchFields['f_' + this.field.id + '_m'] + '-' + this.searchFields['f_' + this.field.id + '_d'])
: moment();

this.searchFields!['f_' + this.field.id] = CoreTimeUtils.toDatetimeFormat(momentInstance.unix() * 1000);
this.searchFields['f_' + this.field.id] = CoreTimeUtils.toDatetimeFormat(momentInstance.unix() * 1000);
} else {
momentInstance = this.value?.content
? moment(parseInt(this.value.content, 10) * 1000)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@
[courseId]="courseId" [wsNotFiltered]="true" />
</span>
</ion-label>
<ion-datetime [formControlName]="modelName" [placeholder]="'core.choosedots' | translate" [displayFormat]="format" [max]="max"
[min]="min" [monthNames]="monthNames" [displayTimezone]="displayTimezone" />

<ion-datetime-button datetime="datetime" />
<ion-modal [keepContentsMounted]="true">
<ng-template>
<ion-datetime id="datetime" [formControlName]="modelName" [presentation]="ionDateTimePresentation" [max]="max" [min]="min" />
</ng-template>
</ion-modal>
<core-input-errors [control]="form.controls[modelName]" />
</ion-item>
14 changes: 2 additions & 12 deletions src/addons/userprofilefield/datetime/component/datetime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ import { CoreTimeUtils } from '@services/utils/time';
import { CoreUtils } from '@services/utils/utils';
import { AuthEmailSignupProfileField } from '@features/login/services/login-helper';
import { CoreUserProfileField } from '@features/user/services/user';
import { Translate } from '@singletons';
import { CoreUserProfileFieldBaseComponent } from '@features/user/classes/base-profilefield-component';
import { CoreLang } from '@services/lang';
import { CoreAppProvider } from '@services/app';

/**
* Directive to render a datetime user profile field.
Expand All @@ -33,13 +30,11 @@ import { CoreAppProvider } from '@services/app';
})
export class AddonUserProfileFieldDatetimeComponent extends CoreUserProfileFieldBaseComponent {

format?: string;
ionDateTimePresentation = 'date';
min?: string;
max?: string;
valueNumber?: number;
displayValue?: string;
monthNames?: string[];
displayTimezone?: string;

/**
* Init the data when the field is meant to be displayed without editing.
Expand All @@ -64,16 +59,11 @@ export class AddonUserProfileFieldDatetimeComponent extends CoreUserProfileField
protected initForEdit(field: AuthEmailSignupProfileField): void {
super.initForEdit(field);

this.monthNames = CoreLang.getMonthNames();
this.displayTimezone = CoreAppProvider.getForcedTimezone();

// Check if it's only date or it has time too.
const hasTime = CoreUtils.isTrueOrOne(field.param3);

// Calculate format to use.
this.format = CoreTimeUtils.fixFormatForDatetime(CoreTimeUtils.convertPHPToMoment(
Translate.instant('core.' + (hasTime ? 'strftimedatetime' : 'strftimedate')),
));
this.ionDateTimePresentation = hasTime ? 'date-time' : 'date';

// Check min value.
if (field.param1 && Number(field.param1)) {
Expand Down
2 changes: 2 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ export function createTranslateLoader(http: HttpClient): TranslateHttpLoader {
IonicModule.forRoot(
{
navAnimation: moodleTransitionAnimation,
innerHTMLTemplatesEnabled: true,
sanitizerEnabled: true,
},
),
HttpClientModule, // HttpClient is used to make JSON requests. It fails for HEAD requests because there is no content.
Expand Down
6 changes: 2 additions & 4 deletions src/core/components/error-info/error-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
import { Component, ElementRef, Input, OnChanges, OnInit } from '@angular/core';
import { Translate } from '@singletons';
import { CoreForms } from '@singletons/form';
import ChevronUpSVG from '!raw-loader!ionicons/dist/svg/chevron-up.svg';
import ChevronDownSVG from '!raw-loader!ionicons/dist/svg/chevron-down.svg';

/**
* Component to show error details.
Expand Down Expand Up @@ -54,11 +52,11 @@ export class CoreErrorInfoComponent implements OnInit, OnChanges {
<label for="${toggleId}" class="core-error-info--toggle" aria-hidden="true">
<span class="core-error-info--hide-content">
${hideDetailsLabel}
${ChevronUpSVG}
<ion-icon name="chevron-up" />
</span>
<span class="core-error-info--show-content">
${showDetailsLabel}
${ChevronDownSVG}
<ion-icon name="chevron-down" />
</span>
</label>
</div>
Expand Down
5 changes: 3 additions & 2 deletions src/core/components/input-errors/input-errors.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
:host {
width: 100%;

display: contents;
.core-input-error-container {
width: 100%;

.core-input-error {
padding: 4px;
color: var(--danger);
Expand Down
3 changes: 2 additions & 1 deletion src/core/components/sheet-modal/sheet-modal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

:host {
--backdrop-opacity: var(--ion-backdrop-opacity, 0.4);
--border-radius: var(--modal-radius);

width: 100%;
height: 100%;
Expand All @@ -17,7 +18,7 @@
}

.sheet-modal--wrapper {
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
border-radius: var(--border-radius) var(--border-radius) 0 0;
@include padding(24px, 16px, 24px, 16px);

background-color: var(--ion-overlay-background-color, var(--ion-background-color, #fff));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
}

/**
* Detect and act upon changes that Angular can’t or won’t detect on its own (objects and arrays).
* @inheritdoc
*/
ngDoCheck(): void {
if (!this.componentInstance || this.creatingComponent) {
Expand All @@ -111,7 +111,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
}

/**
* Detect changes on input properties.
* @inheritdoc
*/
async ngOnChanges(changes: Record<string, SimpleChange>): Promise<void> {
// Only compile if text/javascript has changed or the forceCompile flag has been set to true.
Expand Down Expand Up @@ -148,7 +148,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
}

/**
* Component destroyed.
* @inheritdoc
*/
ngOnDestroy(): void {
this.componentRef?.destroy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,9 @@ ion-item.item {
&.restricted {
font-size: var(--text-size);
}
&[role=button] {
min-height: auto;
min-width: auto;
}
}
}
2 changes: 1 addition & 1 deletion src/core/features/login/pages/site/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,8 @@ export class CoreLoginSitePage implements OnInit {
});

if (errorDetails) {
// Avoid sanitizing JS.
const containerElement = alertElement.querySelector('.core-error-info-container');

if (containerElement) {
containerElement.innerHTML = CoreErrorInfoComponent.render(errorDetails, errorCode);
}
Expand Down
22 changes: 18 additions & 4 deletions src/core/services/lang.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { CorePlatform } from '@services/platform';
import { AddonFilterMultilangHandler } from '@addons/filter/multilang/services/handlers/multilang';
import { AddonFilterMultilang2Handler } from '@addons/filter/multilang2/services/handlers/multilang2';
import { firstValueFrom } from 'rxjs';
import { CoreLogger } from '@singletons/logger';

/*
* Service to handle language features, like changing the current language.
Expand All @@ -40,6 +41,11 @@ export class CoreLangProvider {
protected customStrings: CoreLanguageObject = {}; // Strings defined using the admin tool.
protected customStringsRaw?: string;
protected sitePluginsStrings: CoreLanguageObject = {}; // Strings defined by site plugins.
protected logger: CoreLogger;

constructor() {
this.logger = CoreLogger.getInstance('CoreLang');
}

async initialize(): Promise<void> {
// Set fallback language and language to use until the app determines the right language to use.
Expand Down Expand Up @@ -171,13 +177,21 @@ export class CoreLangProvider {
// Use british english when parent english is loaded.
moment.locale(language == 'en' ? 'en-gb' : language);

const previousLanguage = this.currentLanguage ?? this.getDefaultLanguage();

this.currentLanguage = language;

try {
await Promise.all([
this.reloadLanguageStrings(),
CoreConfig.set('current_language', language),
]);
await this.reloadLanguageStrings();
await CoreConfig.set('current_language', language);
} catch (error) {
if (language !== previousLanguage) {
this.logger.error(`Language ${language} not available, reverting to ${previousLanguage}`, error);

return this.changeCurrentLanguage(previousLanguage);
}

throw error;
} finally {
// Load the custom and site plugins strings for the language.
if (this.loadLangStrings(this.customStrings, language) || this.loadLangStrings(this.sitePluginsStrings, language)) {
Expand Down
Loading
Loading