MOBILE-3947 chore: Migrate ion-datetime to Ionic 7

main
Pau Ferrer Ocaña 2023-11-09 16:48:27 +01:00
parent 2db3635882
commit 22d0d4ece1
10 changed files with 59 additions and 50 deletions

View File

@ -29,8 +29,14 @@
<ion-label position="stacked"> <ion-label position="stacked">
<p class="item-heading" [core-mark-required]="true">{{ 'core.date' | translate }}</p> <p class="item-heading" [core-mark-required]="true">{{ 'core.date' | translate }}</p>
</ion-label> </ion-label>
<ion-datetime formControlName="timestart" [placeholder]="'core.date' | translate" [displayFormat]="dateFormat" <ion-datetime-button datetime="timestart" />
[max]="maxDate" [min]="minDate" [displayTimezone]="displayTimezone" /> <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" /> <core-input-errors [control]="form.controls.timestart" [errorMessages]="errors" />
</ion-item> </ion-item>
@ -154,9 +160,15 @@
</ion-item> </ion-item>
<ion-item *ngIf="form.controls.duration.value === 1"> <ion-item *ngIf="form.controls.duration.value === 1">
<ion-label position="stacked" /> <ion-label position="stacked" />
<ion-datetime formControlName="timedurationuntil" [max]="maxDate" [min]="minDate" <ion-datetime-button datetime="timedurationuntil" />
[placeholder]="'addon.calendar.durationuntil' | translate" [displayFormat]="dateFormat" <ion-modal [keepContentsMounted]="true">
[displayTimezone]="displayTimezone" /> <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-item> <ion-item>
<ion-label> <ion-label>

View File

@ -45,7 +45,6 @@ import { CoreForms } from '@singletons/form';
import { CoreReminders, CoreRemindersService, CoreRemindersUnits } from '@features/reminders/services/reminders'; import { CoreReminders, CoreRemindersService, CoreRemindersUnits } from '@features/reminders/services/reminders';
import { CoreRemindersSetReminderMenuComponent } from '@features/reminders/components/set-reminder-menu/set-reminder-menu'; import { CoreRemindersSetReminderMenuComponent } from '@features/reminders/components/set-reminder-menu/set-reminder-menu';
import moment from 'moment-timezone'; import moment from 'moment-timezone';
import { CoreAppProvider } from '@services/app';
/** /**
* Page that displays a form to create/edit an event. * Page that displays a form to create/edit an event.
@ -61,7 +60,6 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave {
@ViewChild('editEventForm') formElement!: ElementRef; @ViewChild('editEventForm') formElement!: ElementRef;
title = 'addon.calendar.newevent'; title = 'addon.calendar.newevent';
dateFormat: string;
component = AddonCalendarProvider.COMPONENT; component = AddonCalendarProvider.COMPONENT;
loaded = false; loaded = false;
hasOffline = false; hasOffline = false;
@ -78,7 +76,6 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave {
eventId?: number; eventId?: number;
maxDate: string; maxDate: string;
minDate: string; minDate: string;
displayTimezone?: string;
// Form variables. // Form variables.
form: FormGroup; form: FormGroup;
@ -107,11 +104,6 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave {
required: Translate.instant('core.required'), 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({}); this.form = new FormGroup({});
// Initialize form variables. // Initialize form variables.

View File

@ -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> <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" /> <core-input-errors *ngIf="error && editMode" [control]="form.controls['f_'+field.id]" [errorText]="error" />
<ion-item *ngIf="searchMode"> <ion-item *ngIf="searchMode">
<ion-label>{{ 'addon.mod_data.usedate' | translate }}</ion-label> <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> </ion-item>
</span> </span>

View File

@ -13,9 +13,7 @@
// limitations under the License. // limitations under the License.
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { CoreAppProvider } from '@services/app';
import { CoreTimeUtils } from '@services/utils/time'; import { CoreTimeUtils } from '@services/utils/time';
import { Translate } from '@singletons';
import moment, { Moment } from 'moment-timezone'; import moment, { Moment } from 'moment-timezone';
import { AddonModDataFieldPluginBaseComponent } from '../../../classes/base-field-plugin-component'; import { AddonModDataFieldPluginBaseComponent } from '../../../classes/base-field-plugin-component';
@ -28,11 +26,9 @@ import { AddonModDataFieldPluginBaseComponent } from '../../../classes/base-fiel
}) })
export class AddonModDataFieldDateComponent extends AddonModDataFieldPluginBaseComponent { export class AddonModDataFieldDateComponent extends AddonModDataFieldPluginBaseComponent {
format!: string;
displayDate?: number; displayDate?: number;
maxDate?: string; maxDate?: string;
minDate?: string; minDate?: string;
displayTimezone?: string;
/** /**
* @inheritdoc * @inheritdoc
@ -48,23 +44,18 @@ export class AddonModDataFieldDateComponent extends AddonModDataFieldPluginBaseC
let momentInstance: Moment; let momentInstance: Moment;
// Calculate format to use.
this.format = CoreTimeUtils.fixFormatForDatetime(CoreTimeUtils.convertPHPToMoment(
Translate.instant('core.strftimedate'),
));
this.maxDate = CoreTimeUtils.getDatetimeDefaultMax(); this.maxDate = CoreTimeUtils.getDatetimeDefaultMax();
this.minDate = CoreTimeUtils.getDatetimeDefaultMin(); this.minDate = CoreTimeUtils.getDatetimeDefaultMin();
this.displayTimezone = CoreAppProvider.getForcedTimezone();
if (this.searchMode) { if (this.searchMode && this.searchFields) {
this.addControl('f_' + this.field.id + '_z'); this.addControl('f_' + this.field.id + '_z');
momentInstance = this.searchFields!['f_' + this.field.id + '_y'] momentInstance = this.searchFields['f_' + this.field.id + '_y']
? moment(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']) this.searchFields['f_' + this.field.id + '_m'] + '-' + this.searchFields['f_' + this.field.id + '_d'])
: moment(); : moment();
this.searchFields!['f_' + this.field.id] = CoreTimeUtils.toDatetimeFormat(momentInstance.unix() * 1000); this.searchFields['f_' + this.field.id] = CoreTimeUtils.toDatetimeFormat(momentInstance.unix() * 1000);
} else { } else {
momentInstance = this.value?.content momentInstance = this.value?.content
? moment(parseInt(this.value.content, 10) * 1000) ? moment(parseInt(this.value.content, 10) * 1000)

View File

@ -18,7 +18,12 @@
[courseId]="courseId" [wsNotFiltered]="true" /> [courseId]="courseId" [wsNotFiltered]="true" />
</span> </span>
</ion-label> </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]" /> <core-input-errors [control]="form.controls[modelName]" />
</ion-item> </ion-item>

View File

@ -19,10 +19,7 @@ import { CoreTimeUtils } from '@services/utils/time';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { AuthEmailSignupProfileField } from '@features/login/services/login-helper'; import { AuthEmailSignupProfileField } from '@features/login/services/login-helper';
import { CoreUserProfileField } from '@features/user/services/user'; import { CoreUserProfileField } from '@features/user/services/user';
import { Translate } from '@singletons';
import { CoreUserProfileFieldBaseComponent } from '@features/user/classes/base-profilefield-component'; 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. * Directive to render a datetime user profile field.
@ -33,13 +30,11 @@ import { CoreAppProvider } from '@services/app';
}) })
export class AddonUserProfileFieldDatetimeComponent extends CoreUserProfileFieldBaseComponent { export class AddonUserProfileFieldDatetimeComponent extends CoreUserProfileFieldBaseComponent {
format?: string; ionDateTimePresentation = 'date';
min?: string; min?: string;
max?: string; max?: string;
valueNumber?: number; valueNumber?: number;
displayValue?: string; displayValue?: string;
monthNames?: string[];
displayTimezone?: string;
/** /**
* Init the data when the field is meant to be displayed without editing. * Init the data when the field is meant to be displayed without editing.
@ -64,16 +59,11 @@ export class AddonUserProfileFieldDatetimeComponent extends CoreUserProfileField
protected initForEdit(field: AuthEmailSignupProfileField): void { protected initForEdit(field: AuthEmailSignupProfileField): void {
super.initForEdit(field); super.initForEdit(field);
this.monthNames = CoreLang.getMonthNames();
this.displayTimezone = CoreAppProvider.getForcedTimezone();
// Check if it's only date or it has time too. // Check if it's only date or it has time too.
const hasTime = CoreUtils.isTrueOrOne(field.param3); const hasTime = CoreUtils.isTrueOrOne(field.param3);
// Calculate format to use. // Calculate format to use.
this.format = CoreTimeUtils.fixFormatForDatetime(CoreTimeUtils.convertPHPToMoment( this.ionDateTimePresentation = hasTime ? 'date-time' : 'date';
Translate.instant('core.' + (hasTime ? 'strftimedatetime' : 'strftimedate')),
));
// Check min value. // Check min value.
if (field.param1 && Number(field.param1)) { if (field.param1 && Number(field.param1)) {

View File

@ -1,7 +1,8 @@
:host { :host {
width: 100%; display: contents;
.core-input-error-container { .core-input-error-container {
width: 100%;
.core-input-error { .core-input-error {
padding: 4px; padding: 4px;
color: var(--danger); color: var(--danger);

View File

@ -2,6 +2,7 @@
:host { :host {
--backdrop-opacity: var(--ion-backdrop-opacity, 0.4); --backdrop-opacity: var(--ion-backdrop-opacity, 0.4);
--border-radius: var(--modal-radius);
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -17,7 +18,7 @@
} }
.sheet-modal--wrapper { .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); @include padding(24px, 16px, 24px, 16px);
background-color: var(--ion-overlay-background-color, var(--ion-background-color, #fff)); background-color: var(--ion-overlay-background-color, var(--ion-background-color, #fff));

View File

@ -518,7 +518,7 @@ ion-alert .alert-button.timed-button{
} }
ion-alert { ion-alert {
--border-radius: var(--radius-xl); --border-radius: var(--modal-radius);
&.md, &.ios { &.md, &.ios {
--max-width: 80%; --max-width: 80%;
@ -545,7 +545,7 @@ ion-alert {
} }
ion-loading { ion-loading {
--border-radius: var(--radius-xl); --border-radius: var(--modal-radius);
.loading-wrapper { .loading-wrapper {
border-radius: var(--border-radius) !important; border-radius: var(--border-radius) !important;
@ -1917,6 +1917,9 @@ ion-modal {
--border-radius: var(--modal-radius); --border-radius: var(--modal-radius);
} }
} }
&.ion-datetime-button-overlay {
--border-radius: var(--modal-radius);
}
&.core-modal-lateral, &.core-modal-lateral,
&.core-modal-fullscreen { &.core-modal-fullscreen {
@ -1974,3 +1977,10 @@ ion-popover {
[hidden] { [hidden] {
display: none !important; display: none !important;
} }
// Ion Datetime
ion-item.item-label-stacked ion-datetime-button {
margin-top: 8px;
margin-bottom: 8px;
align-self: self-end;
}

View File

@ -9,6 +9,7 @@ For more information about upgrading, read the official documentation: https://m
- Renamed CoreLoginSitesComponent to CoreLoginSitesModalComponent to make it clear that it's a modal and to avoid confusing it with the new CoreSitesListComponent. - Renamed CoreLoginSitesComponent to CoreLoginSitesModalComponent to make it clear that it's a modal and to avoid confusing it with the new CoreSitesListComponent.
- Removed CoreToLocaleStringPipe deprecated since 3.6.0 - Removed CoreToLocaleStringPipe deprecated since 3.6.0
- With the upgrade to Ionic 7 ion-slides is no longer supported and now you need to use swiper-container and swiper-slide. More info here: https://ionicframework.com/docs/angular/slides - With the upgrade to Ionic 7 ion-slides is no longer supported and now you need to use swiper-container and swiper-slide. More info here: https://ionicframework.com/docs/angular/slides
- With the upgrade to Ionic7 ion-datetime has changed its usage. We recommend using ion-datetime-button. More info here: https://ionicframework.com/docs/updating/6-0#datetime
=== 4.3.0 === === 4.3.0 ===