@idea-ionic/uncommon 8.11.5 → 8.11.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { output, input, viewChild, Input, ChangeDetectionStrategy, Component, inject, Injectable,
|
|
2
|
+
import { output, input, viewChild, Input, ChangeDetectionStrategy, Component, inject, Injectable, signal, model } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/forms';
|
|
4
4
|
import { FormsModule } from '@angular/forms';
|
|
5
5
|
import { IonText, IonList, IonInput, IonItem, IonAccordion, IonAccordionGroup, Platform, IonButton, IonIcon, IonLabel, IonSpinner, IonCardContent, IonCard, PopoverController, IonAvatar, IonContent, IonGrid, IonRow, IonCol, AlertController, ModalController, IonFooter, IonButtons, IonTitle, IonToolbar, IonHeader, IonCardTitle, IonCardHeader, IonImg, IonTextarea, IonListHeader, IonFab, IonFabButton, IonBadge, IonSegmentButton, IonSegment } from '@ionic/angular/standalone';
|
|
@@ -535,17 +535,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
535
535
|
*/
|
|
536
536
|
class IDEAOfflineService {
|
|
537
537
|
constructor() {
|
|
538
|
-
|
|
539
|
-
|
|
538
|
+
/**
|
|
539
|
+
* True/false if the platform is offline/online.
|
|
540
|
+
*/
|
|
541
|
+
this._isOffline = signal(typeof navigator === 'undefined' ? false : !navigator.onLine, /* @ts-ignore */
|
|
542
|
+
...(ngDevMode ? [{ debugName: "_isOffline" }] : /* istanbul ignore next */ []));
|
|
540
543
|
if (Network) {
|
|
541
544
|
// set the basic listener for changes
|
|
542
|
-
this.listenerHandler = Network.addListener('networkStatusChange', status =>
|
|
545
|
+
this.listenerHandler = Network.addListener('networkStatusChange', status => this._isOffline.set(!status.connected));
|
|
543
546
|
// create the observable to subscribe to the network changes; note: it won't run until subscribed
|
|
544
547
|
this.observable = new Observable(observer => {
|
|
545
548
|
// remove the basic listener add add one that supports a subscription
|
|
546
549
|
Network.removeAllListeners();
|
|
547
550
|
this.listenerHandler = Network.addListener('networkStatusChange', status => {
|
|
548
|
-
this._isOffline
|
|
551
|
+
this._isOffline.set(!status.connected);
|
|
549
552
|
if (observer)
|
|
550
553
|
observer.next(status.connected);
|
|
551
554
|
});
|
|
@@ -562,13 +565,13 @@ class IDEAOfflineService {
|
|
|
562
565
|
* Quickly check the connection status.
|
|
563
566
|
*/
|
|
564
567
|
isOnline() {
|
|
565
|
-
return !this._isOffline;
|
|
568
|
+
return !this._isOffline();
|
|
566
569
|
}
|
|
567
570
|
/**
|
|
568
571
|
* Quickly check the connection status.
|
|
569
572
|
*/
|
|
570
573
|
isOffline() {
|
|
571
|
-
return this._isOffline;
|
|
574
|
+
return this._isOffline();
|
|
572
575
|
}
|
|
573
576
|
/**
|
|
574
577
|
* Quickly check for online connection.
|
|
@@ -577,7 +580,7 @@ class IDEAOfflineService {
|
|
|
577
580
|
if (!Network)
|
|
578
581
|
return false;
|
|
579
582
|
const status = await Network.getStatus();
|
|
580
|
-
this._isOffline
|
|
583
|
+
this._isOffline.set(!status.connected);
|
|
581
584
|
return status.connected;
|
|
582
585
|
}
|
|
583
586
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: IDEAOfflineService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
@@ -1017,14 +1020,11 @@ class IDEAOldAttachmentsComponent {
|
|
|
1017
1020
|
this._message = inject(IDEAMessageService);
|
|
1018
1021
|
this._tc = inject(IDEATinCanService);
|
|
1019
1022
|
this._api = inject(IDEAAWSAPIService);
|
|
1020
|
-
this._cd = inject(ChangeDetectorRef);
|
|
1021
1023
|
this._offline = inject(IDEAOfflineService);
|
|
1022
1024
|
this._translate = inject(IDEATranslationsService);
|
|
1023
1025
|
/**
|
|
1024
1026
|
* The team from which we want to load the resources. Default: try to guess current team.
|
|
1025
1027
|
*/
|
|
1026
|
-
// TODO: Skipped for migration because:
|
|
1027
|
-
// Your application code writes to the input. This prevents migration.
|
|
1028
1028
|
this.team = null;
|
|
1029
1029
|
/**
|
|
1030
1030
|
* The path to the online API resource, as an array. Don't include the team. E.g. `['entities', entityId]`.
|
|
@@ -1034,12 +1034,11 @@ class IDEAOldAttachmentsComponent {
|
|
|
1034
1034
|
/**
|
|
1035
1035
|
* The array in which we want to add/remove attachments.
|
|
1036
1036
|
*/
|
|
1037
|
-
this.attachments =
|
|
1037
|
+
this.attachments = model(null, /* @ts-ignore */
|
|
1038
1038
|
...(ngDevMode ? [{ debugName: "attachments" }] : /* istanbul ignore next */ []));
|
|
1039
1039
|
/**
|
|
1040
1040
|
* Regulate the mode (view/edit).
|
|
1041
1041
|
*/
|
|
1042
|
-
// TODO: Skipped for migration because: This input is used in a control flow expression (e.g. `@if` or `*ngIf`) and migrating would break narrowing currently.
|
|
1043
1042
|
this.editMode = false;
|
|
1044
1043
|
/**
|
|
1045
1044
|
* Show errors as reported from the parent component.
|
|
@@ -1054,7 +1053,8 @@ class IDEAOldAttachmentsComponent {
|
|
|
1054
1053
|
/**
|
|
1055
1054
|
* Stack of errors from the last upload.
|
|
1056
1055
|
*/
|
|
1057
|
-
this.uploadErrors = []
|
|
1056
|
+
this.uploadErrors = signal([], /* @ts-ignore */
|
|
1057
|
+
...(ngDevMode ? [{ debugName: "uploadErrors" }] : /* istanbul ignore next */ []));
|
|
1058
1058
|
}
|
|
1059
1059
|
ngOnInit() {
|
|
1060
1060
|
// if the team isn't specified, try to guess it in the usual IDEA's paths
|
|
@@ -1074,7 +1074,7 @@ class IDEAOldAttachmentsComponent {
|
|
|
1074
1074
|
document.getElementById('attachmentPicker').click();
|
|
1075
1075
|
}
|
|
1076
1076
|
addAttachmentFromFile(ev) {
|
|
1077
|
-
this.uploadErrors
|
|
1077
|
+
this.uploadErrors.set(new Array());
|
|
1078
1078
|
const files = ev.target ? ev.target.files : {};
|
|
1079
1079
|
for (let i = 0; i < files.length; i++) {
|
|
1080
1080
|
const file = files.item(i);
|
|
@@ -1112,27 +1112,27 @@ class IDEAOldAttachmentsComponent {
|
|
|
1112
1112
|
content = await heic2any({ blob: content, toType: 'image/jpeg' });
|
|
1113
1113
|
}
|
|
1114
1114
|
const attachment = new Attachment({ name, format });
|
|
1115
|
-
this.attachments()
|
|
1115
|
+
this.attachments.update(list => [...(list ?? []), attachment]);
|
|
1116
1116
|
try {
|
|
1117
1117
|
const signedURL = await this._api.patchResource(this.requestURL, {
|
|
1118
1118
|
body: { action: 'ATTACHMENTS_PUT', attachmentId: attachment.attachmentId }
|
|
1119
1119
|
});
|
|
1120
1120
|
await this._api.rawRequest().put(signedURL.url, content).toPromise();
|
|
1121
1121
|
attachment.attachmentId = signedURL.id;
|
|
1122
|
+
// set a fresh array reference so the upload result (attachmentId) re-renders
|
|
1123
|
+
this.attachments.update(list => (list ? [...list] : list));
|
|
1122
1124
|
}
|
|
1123
1125
|
catch (error) {
|
|
1124
|
-
this.uploadErrors.
|
|
1126
|
+
this.uploadErrors.update(errors => [...errors, name]);
|
|
1125
1127
|
this.removeAttachment(attachment);
|
|
1126
1128
|
this._message.error('IDEA_TEAMS.ATTACHMENTS.ERROR_UPLOADING_ATTACHMENT');
|
|
1127
1129
|
}
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1130
|
+
}
|
|
1131
|
+
hideUploadError(err) {
|
|
1132
|
+
this.uploadErrors.update(errors => errors.filter(e => e !== err));
|
|
1131
1133
|
}
|
|
1132
1134
|
removeAttachment(attachment) {
|
|
1133
|
-
|
|
1134
|
-
if (index !== -1)
|
|
1135
|
-
this.attachments().splice(index, 1);
|
|
1135
|
+
this.attachments.update(list => (list ? list.filter(att => att !== attachment) : list));
|
|
1136
1136
|
}
|
|
1137
1137
|
async openAttachment(attachment) {
|
|
1138
1138
|
try {
|
|
@@ -1162,7 +1162,7 @@ class IDEAOldAttachmentsComponent {
|
|
|
1162
1162
|
}
|
|
1163
1163
|
}
|
|
1164
1164
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: IDEAOldAttachmentsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1165
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: IDEAOldAttachmentsComponent, isStandalone: true, selector: "idea-old-attachments", inputs: { team: { classPropertyName: "team", publicName: "team", isSignal: false, isRequired: false, transformFunction: null }, pathResource: { classPropertyName: "pathResource", publicName: "pathResource", isSignal: true, isRequired: false, transformFunction: null }, attachments: { classPropertyName: "attachments", publicName: "attachments", isSignal: true, isRequired: false, transformFunction: null }, editMode: { classPropertyName: "editMode", publicName: "editMode", isSignal: false, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, lines: { classPropertyName: "lines", publicName: "lines", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
1165
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: IDEAOldAttachmentsComponent, isStandalone: true, selector: "idea-old-attachments", inputs: { team: { classPropertyName: "team", publicName: "team", isSignal: false, isRequired: false, transformFunction: null }, pathResource: { classPropertyName: "pathResource", publicName: "pathResource", isSignal: true, isRequired: false, transformFunction: null }, attachments: { classPropertyName: "attachments", publicName: "attachments", isSignal: true, isRequired: false, transformFunction: null }, editMode: { classPropertyName: "editMode", publicName: "editMode", isSignal: false, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, lines: { classPropertyName: "lines", publicName: "lines", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { attachments: "attachmentsChange" }, ngImport: i0, template: `
|
|
1166
1166
|
@for (att of attachments(); track att; let index = $index; let odd = $odd) {
|
|
1167
1167
|
<ion-item
|
|
1168
1168
|
class="attachments"
|
|
@@ -1219,7 +1219,7 @@ class IDEAOldAttachmentsComponent {
|
|
|
1219
1219
|
<!----->
|
|
1220
1220
|
@if (editMode) {
|
|
1221
1221
|
<div>
|
|
1222
|
-
@for (err of uploadErrors; track err) {
|
|
1222
|
+
@for (err of uploadErrors(); track err) {
|
|
1223
1223
|
<ion-item class="attachments" [lines]="lines()">
|
|
1224
1224
|
<ion-icon name="alert-circle" slot="start" color="danger" />
|
|
1225
1225
|
<ion-label color="danger">
|
|
@@ -1231,7 +1231,7 @@ class IDEAOldAttachmentsComponent {
|
|
|
1231
1231
|
color="danger"
|
|
1232
1232
|
fill="clear"
|
|
1233
1233
|
[title]="'IDEA_TEAMS.ATTACHMENTS.HIDE_ERROR' | translate"
|
|
1234
|
-
(click)="
|
|
1234
|
+
(click)="hideUploadError(err)"
|
|
1235
1235
|
>
|
|
1236
1236
|
<ion-icon name="close" slot="icon-only" />
|
|
1237
1237
|
</ion-button>
|
|
@@ -1321,7 +1321,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
1321
1321
|
<!----->
|
|
1322
1322
|
@if (editMode) {
|
|
1323
1323
|
<div>
|
|
1324
|
-
@for (err of uploadErrors; track err) {
|
|
1324
|
+
@for (err of uploadErrors(); track err) {
|
|
1325
1325
|
<ion-item class="attachments" [lines]="lines()">
|
|
1326
1326
|
<ion-icon name="alert-circle" slot="start" color="danger" />
|
|
1327
1327
|
<ion-label color="danger">
|
|
@@ -1333,7 +1333,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
1333
1333
|
color="danger"
|
|
1334
1334
|
fill="clear"
|
|
1335
1335
|
[title]="'IDEA_TEAMS.ATTACHMENTS.HIDE_ERROR' | translate"
|
|
1336
|
-
(click)="
|
|
1336
|
+
(click)="hideUploadError(err)"
|
|
1337
1337
|
>
|
|
1338
1338
|
<ion-icon name="close" slot="icon-only" />
|
|
1339
1339
|
</ion-button>
|
|
@@ -1365,7 +1365,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
1365
1365
|
`, styles: [".attachments ion-button[slot=start],.attachments ion-icon[slot=start]{margin-right:10px}.attachments .loadingWarning{font-style:italic;font-size:.8em;color:var(--ion-color-medium)}.noAttachments{font-style:italic}.selectIcon{margin:0;padding-left:4px;font-size:.8em;color:var(--ion-color-medium)}.selectable{cursor:pointer}\n"] }]
|
|
1366
1366
|
}], propDecorators: { team: [{
|
|
1367
1367
|
type: Input
|
|
1368
|
-
}], pathResource: [{ type: i0.Input, args: [{ isSignal: true, alias: "pathResource", required: false }] }], attachments: [{ type: i0.Input, args: [{ isSignal: true, alias: "attachments", required: false }] }], editMode: [{
|
|
1368
|
+
}], pathResource: [{ type: i0.Input, args: [{ isSignal: true, alias: "pathResource", required: false }] }], attachments: [{ type: i0.Input, args: [{ isSignal: true, alias: "attachments", required: false }] }, { type: i0.Output, args: ["attachmentsChange"] }], editMode: [{
|
|
1369
1369
|
type: Input
|
|
1370
1370
|
}], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], lines: [{ type: i0.Input, args: [{ isSignal: true, alias: "lines", required: false }] }] } });
|
|
1371
1371
|
/**
|
|
@@ -1388,9 +1388,14 @@ class IDEAAnnouncementComponent {
|
|
|
1388
1388
|
this._env = inject(IDEAEnvironment);
|
|
1389
1389
|
this._tc = inject(IDEATinCanService);
|
|
1390
1390
|
this._storage = inject(IDEAStorageService);
|
|
1391
|
-
|
|
1391
|
+
/**
|
|
1392
|
+
* The color for the announcement card.
|
|
1393
|
+
*/
|
|
1394
|
+
this.color = model('dark', /* @ts-ignore */
|
|
1395
|
+
...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
1396
|
+
this.htmlContent = signal(null, /* @ts-ignore */
|
|
1397
|
+
...(ngDevMode ? [{ debugName: "htmlContent" }] : /* istanbul ignore next */ []));
|
|
1392
1398
|
this.storageKey = (this._env.idea.project || 'app').concat('_LAST_ANNOUNCEMENT');
|
|
1393
|
-
this.color = 'dark';
|
|
1394
1399
|
}
|
|
1395
1400
|
async ngOnInit() {
|
|
1396
1401
|
// standard IDEA: the announcement is read in the Init Guard
|
|
@@ -1398,21 +1403,19 @@ class IDEAAnnouncementComponent {
|
|
|
1398
1403
|
if (this.announcement && this.announcement.content) {
|
|
1399
1404
|
const lastRead = await this._storage.get(this.storageKey);
|
|
1400
1405
|
if (!lastRead || this.announcement.content !== lastRead)
|
|
1401
|
-
this.htmlContent
|
|
1402
|
-
this._cdr.markForCheck();
|
|
1406
|
+
this.htmlContent.set(mdToHtml(this.announcement.content));
|
|
1403
1407
|
}
|
|
1404
1408
|
}
|
|
1405
1409
|
async markAsRead() {
|
|
1406
1410
|
await this._storage.set(this.storageKey, this.announcement.content);
|
|
1407
|
-
this.htmlContent
|
|
1408
|
-
this._cdr.markForCheck();
|
|
1411
|
+
this.htmlContent.set(null);
|
|
1409
1412
|
}
|
|
1410
1413
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: IDEAAnnouncementComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1411
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: IDEAAnnouncementComponent, isStandalone: true, selector: "idea-announcement", inputs: { color: "color" }, ngImport: i0, template: `
|
|
1412
|
-
@if (htmlContent) {
|
|
1413
|
-
<ion-card class="announcementCard" [color]="color">
|
|
1414
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: IDEAAnnouncementComponent, isStandalone: true, selector: "idea-announcement", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { color: "colorChange" }, ngImport: i0, template: `
|
|
1415
|
+
@if (htmlContent()) {
|
|
1416
|
+
<ion-card class="announcementCard" [color]="color()">
|
|
1414
1417
|
<ion-card-content>
|
|
1415
|
-
<p class="htmlContent" [innerHTML]="htmlContent"></p>
|
|
1418
|
+
<p class="htmlContent" [innerHTML]="htmlContent()"></p>
|
|
1416
1419
|
<p class="ion-text-right">
|
|
1417
1420
|
<ion-button color="primary" (click)="markAsRead()">
|
|
1418
1421
|
{{ 'COMMON.GOT_IT' | translate }}
|
|
@@ -1430,10 +1433,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
1430
1433
|
imports: [IDEATranslatePipe, IonButton, IonCardContent, IonCard],
|
|
1431
1434
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1432
1435
|
template: `
|
|
1433
|
-
@if (htmlContent) {
|
|
1434
|
-
<ion-card class="announcementCard" [color]="color">
|
|
1436
|
+
@if (htmlContent()) {
|
|
1437
|
+
<ion-card class="announcementCard" [color]="color()">
|
|
1435
1438
|
<ion-card-content>
|
|
1436
|
-
<p class="htmlContent" [innerHTML]="htmlContent"></p>
|
|
1439
|
+
<p class="htmlContent" [innerHTML]="htmlContent()"></p>
|
|
1437
1440
|
<p class="ion-text-right">
|
|
1438
1441
|
<ion-button color="primary" (click)="markAsRead()">
|
|
1439
1442
|
{{ 'COMMON.GOT_IT' | translate }}
|
|
@@ -1444,9 +1447,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
1444
1447
|
}
|
|
1445
1448
|
`
|
|
1446
1449
|
}]
|
|
1447
|
-
}], ctorParameters: () => [], propDecorators: { color: [{
|
|
1448
|
-
type: Input
|
|
1449
|
-
}] } });
|
|
1450
|
+
}], ctorParameters: () => [], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }, { type: i0.Output, args: ["colorChange"] }] } });
|
|
1450
1451
|
|
|
1451
1452
|
/**
|
|
1452
1453
|
* Pick a color from a defined set.
|
|
@@ -1853,12 +1854,16 @@ class IDEACalendarPickerComponent {
|
|
|
1853
1854
|
this.timePicker = false;
|
|
1854
1855
|
this.manualTimePicker = false;
|
|
1855
1856
|
this.hideClearButton = false;
|
|
1857
|
+
this.refDate = signal(undefined, /* @ts-ignore */
|
|
1858
|
+
...(ngDevMode ? [{ debugName: "refDate" }] : /* istanbul ignore next */ []));
|
|
1859
|
+
this.calendarGrid = signal(undefined, /* @ts-ignore */
|
|
1860
|
+
...(ngDevMode ? [{ debugName: "calendarGrid" }] : /* istanbul ignore next */ []));
|
|
1856
1861
|
}
|
|
1857
1862
|
ngOnInit() {
|
|
1858
1863
|
this.today = new Date();
|
|
1859
1864
|
const inputDate = this.inputDate;
|
|
1860
|
-
this.refDate
|
|
1861
|
-
this.selectedDate = new Date(this.refDate);
|
|
1865
|
+
this.refDate.set(inputDate ? new Date(inputDate) : new Date(this.today));
|
|
1866
|
+
this.selectedDate = new Date(this.refDate());
|
|
1862
1867
|
this.hour = 12; // to endure timezones
|
|
1863
1868
|
this.minute = 0;
|
|
1864
1869
|
const manualTimePicker = this.manualTimePicker;
|
|
@@ -1872,7 +1877,7 @@ class IDEACalendarPickerComponent {
|
|
|
1872
1877
|
this.selectedDate.setMinutes(this.minute);
|
|
1873
1878
|
}
|
|
1874
1879
|
}
|
|
1875
|
-
this.buildCalendarGrid(this.refDate);
|
|
1880
|
+
this.buildCalendarGrid(this.refDate());
|
|
1876
1881
|
this.hours = Array.from(Array(24).keys()).map(i => '0'.concat(i.toString()).slice(-2));
|
|
1877
1882
|
this.minutes = Array.from(Array(12).keys()).map(i => '0'.concat((i * 5).toString()).slice(-2));
|
|
1878
1883
|
// build the weekdays based on the current locale
|
|
@@ -1907,21 +1912,21 @@ class IDEACalendarPickerComponent {
|
|
|
1907
1912
|
let haventFoundFirstDay = true;
|
|
1908
1913
|
// index used to build the dates of the month, starting from the first one
|
|
1909
1914
|
let index = 1;
|
|
1910
|
-
|
|
1915
|
+
const calendarGrid = new Array();
|
|
1911
1916
|
for (let i = 0; i < 6; i++) {
|
|
1912
|
-
|
|
1917
|
+
calendarGrid[i] = new Array();
|
|
1913
1918
|
for (let j = 0; j < 7; j++) {
|
|
1914
1919
|
if (haventFoundFirstDay) {
|
|
1915
1920
|
if (this.getLocalisedDay(firstDateOfMonth) === j) {
|
|
1916
1921
|
// note: considers Sunday
|
|
1917
1922
|
haventFoundFirstDay = false;
|
|
1918
|
-
|
|
1923
|
+
calendarGrid[i][j] = new Date(firstDateOfMonth);
|
|
1919
1924
|
// now the I've found the first date of the month I can fill the calendar
|
|
1920
1925
|
// the dates fromt the previous month, until there's space in the grid
|
|
1921
1926
|
for (let y = this.getLocalisedDay(firstDateOfMonth); y >= 0; y--) {
|
|
1922
1927
|
const d = new Date(firstDateOfMonth);
|
|
1923
1928
|
d.setDate(firstDateOfMonth.getDate() - y);
|
|
1924
|
-
|
|
1929
|
+
calendarGrid[i][this.getLocalisedDay(firstDateOfMonth) - y] = d;
|
|
1925
1930
|
}
|
|
1926
1931
|
}
|
|
1927
1932
|
}
|
|
@@ -1929,24 +1934,37 @@ class IDEACalendarPickerComponent {
|
|
|
1929
1934
|
// fill the following dates until there's space in the grid
|
|
1930
1935
|
const d = new Date(firstDateOfMonth);
|
|
1931
1936
|
d.setDate(firstDateOfMonth.getDate() + index++);
|
|
1932
|
-
|
|
1937
|
+
calendarGrid[i][j] = d;
|
|
1933
1938
|
}
|
|
1934
1939
|
}
|
|
1935
1940
|
}
|
|
1941
|
+
this.calendarGrid.set(calendarGrid);
|
|
1936
1942
|
}
|
|
1937
1943
|
addYears(offset) {
|
|
1938
|
-
this.refDate.
|
|
1939
|
-
|
|
1944
|
+
this.refDate.update(d => {
|
|
1945
|
+
const refDate = new Date(d);
|
|
1946
|
+
refDate.setFullYear(refDate.getFullYear() + offset);
|
|
1947
|
+
return refDate;
|
|
1948
|
+
});
|
|
1949
|
+
this.buildCalendarGrid(this.refDate());
|
|
1940
1950
|
}
|
|
1941
1951
|
setYear(year) {
|
|
1942
1952
|
if (!year)
|
|
1943
1953
|
return;
|
|
1944
|
-
this.refDate.
|
|
1945
|
-
|
|
1954
|
+
this.refDate.update(d => {
|
|
1955
|
+
const refDate = new Date(d);
|
|
1956
|
+
refDate.setFullYear(Number(year));
|
|
1957
|
+
return refDate;
|
|
1958
|
+
});
|
|
1959
|
+
this.buildCalendarGrid(this.refDate());
|
|
1946
1960
|
}
|
|
1947
1961
|
addMonths(offset) {
|
|
1948
|
-
this.refDate.
|
|
1949
|
-
|
|
1962
|
+
this.refDate.update(d => {
|
|
1963
|
+
const refDate = new Date(d);
|
|
1964
|
+
refDate.setMonth(refDate.getMonth() + offset);
|
|
1965
|
+
return refDate;
|
|
1966
|
+
});
|
|
1967
|
+
this.buildCalendarGrid(this.refDate());
|
|
1950
1968
|
}
|
|
1951
1969
|
async showMonths() {
|
|
1952
1970
|
const buttons = [];
|
|
@@ -1957,7 +1975,7 @@ class IDEACalendarPickerComponent {
|
|
|
1957
1975
|
type: 'radio',
|
|
1958
1976
|
label: month.toLocaleDateString(this._translate.getCurrentLang(), { month: 'long' }),
|
|
1959
1977
|
value: i.toString(),
|
|
1960
|
-
checked: i === this.refDate.getMonth() + 1
|
|
1978
|
+
checked: i === this.refDate().getMonth() + 1
|
|
1961
1979
|
});
|
|
1962
1980
|
month.setMonth(month.getMonth() + 1);
|
|
1963
1981
|
}
|
|
@@ -1965,8 +1983,12 @@ class IDEACalendarPickerComponent {
|
|
|
1965
1983
|
buttons.push({
|
|
1966
1984
|
text: this._translate._('COMMON.SELECT'),
|
|
1967
1985
|
handler: (m) => {
|
|
1968
|
-
this.refDate.
|
|
1969
|
-
|
|
1986
|
+
this.refDate.update(d => {
|
|
1987
|
+
const refDate = new Date(d);
|
|
1988
|
+
refDate.setMonth(parseInt(m, 10) - 1);
|
|
1989
|
+
return refDate;
|
|
1990
|
+
});
|
|
1991
|
+
this.buildCalendarGrid(this.refDate());
|
|
1970
1992
|
}
|
|
1971
1993
|
});
|
|
1972
1994
|
const alert = await this._alert.create({
|
|
@@ -2013,7 +2035,7 @@ class IDEACalendarPickerComponent {
|
|
|
2013
2035
|
this._modal.dismiss();
|
|
2014
2036
|
}
|
|
2015
2037
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: IDEACalendarPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2016
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: IDEACalendarPickerComponent, isStandalone: true, selector: "idea-calendar-picker", inputs: { inputDate: "inputDate", timePicker: "timePicker", manualTimePicker: "manualTimePicker", title: "title", hideClearButton: "hideClearButton", min: "min", max: "max" }, ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"ideaToolbar\">\n <ion-title>{{ title }}</ion-title>\n <ion-buttons slot=\"end\">\n @if (!hideClearButton) {\n <ion-button [title]=\"'IDEA_UNCOMMON.CALENDAR.RESET' | translate\" (click)=\"save(true)\">\n <ion-icon slot=\"icon-only\" name=\"arrow-undo\" />\n </ion-button>\n }\n <ion-button [title]=\"'IDEA_UNCOMMON.CALENDAR.CLOSE_WITHOUT_SAVING' | translate\" (click)=\"close()\">\n <ion-icon slot=\"icon-only\" name=\"close\" />\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n <ion-grid fixed class=\"ion-no-padding\">\n <ion-row>\n <h1 class=\"headerLabel\">{{ 'IDEA_UNCOMMON.CALENDAR.SET_DATE' | translate }}</h1>\n </ion-row>\n <ion-row style=\"margin-bottom: 8px\">\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"5\">\n <ion-row class=\"ion-align-items-center ion-justify-content-center\">\n <ion-col class=\"ion-text-right ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addYears(-1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-back\" />\n </ion-button>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding tappable\" [size]=\"6\">\n <ion-input\n type=\"text\"\n [placeholder]=\"'IDEA_UNCOMMON.CALENDAR.YEAR' | translate\"\n [value]=\"refDate.getFullYear()\"\n (ionFocus)=\"$event.target.value = ''\"\n (ionChange)=\"setYear($event?.target?.value)\"\n >\n </ion-input>\n </ion-col>\n <ion-col class=\"ion-text-left ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addYears(+1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-forward\" />\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"7\">\n <ion-row class=\"ion-align-items-center\">\n <ion-col class=\"ion-text-right ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addMonths(-1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-back\" />\n </ion-button>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding tappable\" [size]=\"6\" (click)=\"showMonths()\">\n {{ refDate | dateLocale: 'MMMM' }}\n </ion-col>\n <ion-col class=\"ion-text-left ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addMonths(+1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-forward\" />\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-col>\n </ion-row>\n <ion-row style=\"margin-bottom: 8px\" class=\"headerLabel\">\n @for (ddd of weekDays; track ddd) {\n <ion-col class=\"ion-text-center ion-no-padding\">\n {{ ddd }}\n </ion-col>\n }\n </ion-row>\n @for (row of calendarGrid; track row; let i = $index) {\n <ion-row class=\"ion-align-items-center\">\n @for (col of row; track col; let j = $index) {\n <ion-col class=\"ion-text-center ion-no-padding\">\n <ion-button\n size=\"small\"\n shape=\"round\"\n [color]=\"\n isSameDay(calendarGrid[i][j], today) || isSameDay(calendarGrid[i][j], selectedDate)\n ? 'primary'\n : isSameMonth(calendarGrid[i][j], refDate)\n ? 'dark'\n : 'medium'\n \"\n [fill]=\"\n isSameDay(calendarGrid[i][j], selectedDate)\n ? 'solid'\n : isSameDay(calendarGrid[i][j], today)\n ? 'outline'\n : 'clear'\n \"\n [disabled]=\"!isDateSelectable(calendarGrid[i][j])\"\n (click)=\"selectDate(calendarGrid[i][j])\"\n >\n {{ calendarGrid[i][j] | date: 'd' }}\n </ion-button>\n </ion-col>\n }\n </ion-row>\n }\n @if (timePicker || manualTimePicker) {\n <ion-row>\n <h1 class=\"headerLabel\">\n {{ 'IDEA_UNCOMMON.CALENDAR.SET_TIME' | translate }}\n </h1>\n </ion-row>\n }\n @if (timePicker) {\n <ion-row class=\"ion-align-items-center\">\n <ion-col class=\"ion-no-padding\" [size]=\"7\">\n <ion-row>\n @for (hour of hours; track hour) {\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"2\">\n <ion-button\n size=\"small\"\n shape=\"round\"\n [color]=\"isSameHour(hour) ? 'primary' : 'dark'\"\n [fill]=\"isSameHour(hour) ? 'solid' : 'clear'\"\n (click)=\"selectHour(hour)\"\n >\n {{ hour }}\n </ion-button>\n </ion-col>\n }\n </ion-row>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"1\"> : </ion-col>\n <ion-col class=\"ion-no-padding\" [size]=\"4\">\n <ion-row>\n @for (minute of minutes; track minute) {\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"4\">\n <ion-button\n size=\"small\"\n shape=\"round\"\n [color]=\"isSameMinute(minute) ? 'primary' : 'dark'\"\n [fill]=\"isSameMinute(minute) ? 'solid' : 'clear'\"\n (click)=\"selectMinute(minute)\"\n >\n {{ minute }}\n </ion-button>\n </ion-col>\n }\n </ion-row>\n </ion-col>\n </ion-row>\n }\n @if (manualTimePicker) {\n <ion-row class=\"ion-align-items-center manualTimePicker\">\n <ion-col class=\"ion-text-center\" [size]=\"12\">\n <input type=\"number\" min=\"0\" max=\"23\" [value]=\"hour\" (change)=\"selectHour($event.target.value)\" />\n <span>:</span>\n <input type=\"number\" min=\"0\" max=\"59\" [value]=\"minute\" (change)=\"selectMinute($event.target.value)\" />\n </ion-col>\n </ion-row>\n }\n </ion-grid>\n</ion-content>\n<ion-footer>\n <ion-toolbar color=\"ideaToolbar\" class=\"tappable\" (click)=\"save()\">\n <ion-title class=\"ion-text-center\">\n <ion-icon name=\"checkmark\" />\n </ion-title>\n </ion-toolbar>\n</ion-footer>\n", styles: ["ion-content{--background: var(--ion-color-white)}h1{margin:10px}.headerLabel{font-size:.7em;font-weight:700;text-transform:uppercase}ion-col,ion-button{font-size:.95em}ion-button{margin:3px 0}ion-footer ion-toolbar{--min-height: 40px}.tappable{cursor:pointer}.manualTimePicker{padding:20px}.manualTimePicker input[type=number],.manualTimePicker span{font-size:2.5em}.manualTimePicker input[type=number]{border:none;border-bottom:2px solid var(--ion-color-dark);text-align:center}.manualTimePicker span{padding-left:4px;padding-right:4px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: IonRow, selector: "ion-row" }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "pipe", type: i1$1.DatePipe, name: "date" }, { kind: "pipe", type: IDEATranslatePipe, name: "translate" }, { kind: "pipe", type: IDEALocalizedDatePipe, name: "dateLocale" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2038
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: IDEACalendarPickerComponent, isStandalone: true, selector: "idea-calendar-picker", inputs: { inputDate: "inputDate", timePicker: "timePicker", manualTimePicker: "manualTimePicker", title: "title", hideClearButton: "hideClearButton", min: "min", max: "max" }, ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"ideaToolbar\">\n <ion-title>{{ title }}</ion-title>\n <ion-buttons slot=\"end\">\n @if (!hideClearButton) {\n <ion-button [title]=\"'IDEA_UNCOMMON.CALENDAR.RESET' | translate\" (click)=\"save(true)\">\n <ion-icon slot=\"icon-only\" name=\"arrow-undo\" />\n </ion-button>\n }\n <ion-button [title]=\"'IDEA_UNCOMMON.CALENDAR.CLOSE_WITHOUT_SAVING' | translate\" (click)=\"close()\">\n <ion-icon slot=\"icon-only\" name=\"close\" />\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n <ion-grid fixed class=\"ion-no-padding\">\n <ion-row>\n <h1 class=\"headerLabel\">{{ 'IDEA_UNCOMMON.CALENDAR.SET_DATE' | translate }}</h1>\n </ion-row>\n <ion-row style=\"margin-bottom: 8px\">\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"5\">\n <ion-row class=\"ion-align-items-center ion-justify-content-center\">\n <ion-col class=\"ion-text-right ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addYears(-1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-back\" />\n </ion-button>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding tappable\" [size]=\"6\">\n <ion-input\n type=\"text\"\n [placeholder]=\"'IDEA_UNCOMMON.CALENDAR.YEAR' | translate\"\n [value]=\"refDate().getFullYear()\"\n (ionFocus)=\"$event.target.value = ''\"\n (ionChange)=\"setYear($event?.target?.value)\"\n >\n </ion-input>\n </ion-col>\n <ion-col class=\"ion-text-left ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addYears(+1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-forward\" />\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"7\">\n <ion-row class=\"ion-align-items-center\">\n <ion-col class=\"ion-text-right ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addMonths(-1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-back\" />\n </ion-button>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding tappable\" [size]=\"6\" (click)=\"showMonths()\">\n {{ refDate() | dateLocale: 'MMMM' }}\n </ion-col>\n <ion-col class=\"ion-text-left ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addMonths(+1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-forward\" />\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-col>\n </ion-row>\n <ion-row style=\"margin-bottom: 8px\" class=\"headerLabel\">\n @for (ddd of weekDays; track ddd) {\n <ion-col class=\"ion-text-center ion-no-padding\">\n {{ ddd }}\n </ion-col>\n }\n </ion-row>\n @for (row of calendarGrid(); track row; let i = $index) {\n <ion-row class=\"ion-align-items-center\">\n @for (col of row; track col; let j = $index) {\n <ion-col class=\"ion-text-center ion-no-padding\">\n <ion-button\n size=\"small\"\n shape=\"round\"\n [color]=\"\n isSameDay(calendarGrid()[i][j], today) || isSameDay(calendarGrid()[i][j], selectedDate)\n ? 'primary'\n : isSameMonth(calendarGrid()[i][j], refDate())\n ? 'dark'\n : 'medium'\n \"\n [fill]=\"\n isSameDay(calendarGrid()[i][j], selectedDate)\n ? 'solid'\n : isSameDay(calendarGrid()[i][j], today)\n ? 'outline'\n : 'clear'\n \"\n [disabled]=\"!isDateSelectable(calendarGrid()[i][j])\"\n (click)=\"selectDate(calendarGrid()[i][j])\"\n >\n {{ calendarGrid()[i][j] | date: 'd' }}\n </ion-button>\n </ion-col>\n }\n </ion-row>\n }\n @if (timePicker || manualTimePicker) {\n <ion-row>\n <h1 class=\"headerLabel\">\n {{ 'IDEA_UNCOMMON.CALENDAR.SET_TIME' | translate }}\n </h1>\n </ion-row>\n }\n @if (timePicker) {\n <ion-row class=\"ion-align-items-center\">\n <ion-col class=\"ion-no-padding\" [size]=\"7\">\n <ion-row>\n @for (hour of hours; track hour) {\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"2\">\n <ion-button\n size=\"small\"\n shape=\"round\"\n [color]=\"isSameHour(hour) ? 'primary' : 'dark'\"\n [fill]=\"isSameHour(hour) ? 'solid' : 'clear'\"\n (click)=\"selectHour(hour)\"\n >\n {{ hour }}\n </ion-button>\n </ion-col>\n }\n </ion-row>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"1\"> : </ion-col>\n <ion-col class=\"ion-no-padding\" [size]=\"4\">\n <ion-row>\n @for (minute of minutes; track minute) {\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"4\">\n <ion-button\n size=\"small\"\n shape=\"round\"\n [color]=\"isSameMinute(minute) ? 'primary' : 'dark'\"\n [fill]=\"isSameMinute(minute) ? 'solid' : 'clear'\"\n (click)=\"selectMinute(minute)\"\n >\n {{ minute }}\n </ion-button>\n </ion-col>\n }\n </ion-row>\n </ion-col>\n </ion-row>\n }\n @if (manualTimePicker) {\n <ion-row class=\"ion-align-items-center manualTimePicker\">\n <ion-col class=\"ion-text-center\" [size]=\"12\">\n <input type=\"number\" min=\"0\" max=\"23\" [value]=\"hour\" (change)=\"selectHour($event.target.value)\" />\n <span>:</span>\n <input type=\"number\" min=\"0\" max=\"59\" [value]=\"minute\" (change)=\"selectMinute($event.target.value)\" />\n </ion-col>\n </ion-row>\n }\n </ion-grid>\n</ion-content>\n<ion-footer>\n <ion-toolbar color=\"ideaToolbar\" class=\"tappable\" (click)=\"save()\">\n <ion-title class=\"ion-text-center\">\n <ion-icon name=\"checkmark\" />\n </ion-title>\n </ion-toolbar>\n</ion-footer>\n", styles: ["ion-content{--background: var(--ion-color-white)}h1{margin:10px}.headerLabel{font-size:.7em;font-weight:700;text-transform:uppercase}ion-col,ion-button{font-size:.95em}ion-button{margin:3px 0}ion-footer ion-toolbar{--min-height: 40px}.tappable{cursor:pointer}.manualTimePicker{padding:20px}.manualTimePicker input[type=number],.manualTimePicker span{font-size:2.5em}.manualTimePicker input[type=number]{border:none;border-bottom:2px solid var(--ion-color-dark);text-align:center}.manualTimePicker span{padding-left:4px;padding-right:4px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: IonRow, selector: "ion-row" }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "pipe", type: i1$1.DatePipe, name: "date" }, { kind: "pipe", type: IDEATranslatePipe, name: "translate" }, { kind: "pipe", type: IDEALocalizedDatePipe, name: "dateLocale" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2017
2039
|
}
|
|
2018
2040
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: IDEACalendarPickerComponent, decorators: [{
|
|
2019
2041
|
type: Component,
|
|
@@ -2034,7 +2056,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
2034
2056
|
IonTitle,
|
|
2035
2057
|
IonToolbar,
|
|
2036
2058
|
IonHeader
|
|
2037
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-header>\n <ion-toolbar color=\"ideaToolbar\">\n <ion-title>{{ title }}</ion-title>\n <ion-buttons slot=\"end\">\n @if (!hideClearButton) {\n <ion-button [title]=\"'IDEA_UNCOMMON.CALENDAR.RESET' | translate\" (click)=\"save(true)\">\n <ion-icon slot=\"icon-only\" name=\"arrow-undo\" />\n </ion-button>\n }\n <ion-button [title]=\"'IDEA_UNCOMMON.CALENDAR.CLOSE_WITHOUT_SAVING' | translate\" (click)=\"close()\">\n <ion-icon slot=\"icon-only\" name=\"close\" />\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n <ion-grid fixed class=\"ion-no-padding\">\n <ion-row>\n <h1 class=\"headerLabel\">{{ 'IDEA_UNCOMMON.CALENDAR.SET_DATE' | translate }}</h1>\n </ion-row>\n <ion-row style=\"margin-bottom: 8px\">\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"5\">\n <ion-row class=\"ion-align-items-center ion-justify-content-center\">\n <ion-col class=\"ion-text-right ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addYears(-1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-back\" />\n </ion-button>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding tappable\" [size]=\"6\">\n <ion-input\n type=\"text\"\n [placeholder]=\"'IDEA_UNCOMMON.CALENDAR.YEAR' | translate\"\n [value]=\"refDate.getFullYear()\"\n (ionFocus)=\"$event.target.value = ''\"\n (ionChange)=\"setYear($event?.target?.value)\"\n >\n </ion-input>\n </ion-col>\n <ion-col class=\"ion-text-left ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addYears(+1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-forward\" />\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"7\">\n <ion-row class=\"ion-align-items-center\">\n <ion-col class=\"ion-text-right ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addMonths(-1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-back\" />\n </ion-button>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding tappable\" [size]=\"6\" (click)=\"showMonths()\">\n {{ refDate | dateLocale: 'MMMM' }}\n </ion-col>\n <ion-col class=\"ion-text-left ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addMonths(+1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-forward\" />\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-col>\n </ion-row>\n <ion-row style=\"margin-bottom: 8px\" class=\"headerLabel\">\n @for (ddd of weekDays; track ddd) {\n <ion-col class=\"ion-text-center ion-no-padding\">\n {{ ddd }}\n </ion-col>\n }\n </ion-row>\n @for (row of calendarGrid; track row; let i = $index) {\n <ion-row class=\"ion-align-items-center\">\n @for (col of row; track col; let j = $index) {\n <ion-col class=\"ion-text-center ion-no-padding\">\n <ion-button\n size=\"small\"\n shape=\"round\"\n [color]=\"\n isSameDay(calendarGrid[i][j], today) || isSameDay(calendarGrid[i][j], selectedDate)\n ? 'primary'\n : isSameMonth(calendarGrid[i][j], refDate)\n ? 'dark'\n : 'medium'\n \"\n [fill]=\"\n isSameDay(calendarGrid[i][j], selectedDate)\n ? 'solid'\n : isSameDay(calendarGrid[i][j], today)\n ? 'outline'\n : 'clear'\n \"\n [disabled]=\"!isDateSelectable(calendarGrid[i][j])\"\n (click)=\"selectDate(calendarGrid[i][j])\"\n >\n {{ calendarGrid[i][j] | date: 'd' }}\n </ion-button>\n </ion-col>\n }\n </ion-row>\n }\n @if (timePicker || manualTimePicker) {\n <ion-row>\n <h1 class=\"headerLabel\">\n {{ 'IDEA_UNCOMMON.CALENDAR.SET_TIME' | translate }}\n </h1>\n </ion-row>\n }\n @if (timePicker) {\n <ion-row class=\"ion-align-items-center\">\n <ion-col class=\"ion-no-padding\" [size]=\"7\">\n <ion-row>\n @for (hour of hours; track hour) {\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"2\">\n <ion-button\n size=\"small\"\n shape=\"round\"\n [color]=\"isSameHour(hour) ? 'primary' : 'dark'\"\n [fill]=\"isSameHour(hour) ? 'solid' : 'clear'\"\n (click)=\"selectHour(hour)\"\n >\n {{ hour }}\n </ion-button>\n </ion-col>\n }\n </ion-row>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"1\"> : </ion-col>\n <ion-col class=\"ion-no-padding\" [size]=\"4\">\n <ion-row>\n @for (minute of minutes; track minute) {\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"4\">\n <ion-button\n size=\"small\"\n shape=\"round\"\n [color]=\"isSameMinute(minute) ? 'primary' : 'dark'\"\n [fill]=\"isSameMinute(minute) ? 'solid' : 'clear'\"\n (click)=\"selectMinute(minute)\"\n >\n {{ minute }}\n </ion-button>\n </ion-col>\n }\n </ion-row>\n </ion-col>\n </ion-row>\n }\n @if (manualTimePicker) {\n <ion-row class=\"ion-align-items-center manualTimePicker\">\n <ion-col class=\"ion-text-center\" [size]=\"12\">\n <input type=\"number\" min=\"0\" max=\"23\" [value]=\"hour\" (change)=\"selectHour($event.target.value)\" />\n <span>:</span>\n <input type=\"number\" min=\"0\" max=\"59\" [value]=\"minute\" (change)=\"selectMinute($event.target.value)\" />\n </ion-col>\n </ion-row>\n }\n </ion-grid>\n</ion-content>\n<ion-footer>\n <ion-toolbar color=\"ideaToolbar\" class=\"tappable\" (click)=\"save()\">\n <ion-title class=\"ion-text-center\">\n <ion-icon name=\"checkmark\" />\n </ion-title>\n </ion-toolbar>\n</ion-footer>\n", styles: ["ion-content{--background: var(--ion-color-white)}h1{margin:10px}.headerLabel{font-size:.7em;font-weight:700;text-transform:uppercase}ion-col,ion-button{font-size:.95em}ion-button{margin:3px 0}ion-footer ion-toolbar{--min-height: 40px}.tappable{cursor:pointer}.manualTimePicker{padding:20px}.manualTimePicker input[type=number],.manualTimePicker span{font-size:2.5em}.manualTimePicker input[type=number]{border:none;border-bottom:2px solid var(--ion-color-dark);text-align:center}.manualTimePicker span{padding-left:4px;padding-right:4px}\n"] }]
|
|
2059
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-header>\n <ion-toolbar color=\"ideaToolbar\">\n <ion-title>{{ title }}</ion-title>\n <ion-buttons slot=\"end\">\n @if (!hideClearButton) {\n <ion-button [title]=\"'IDEA_UNCOMMON.CALENDAR.RESET' | translate\" (click)=\"save(true)\">\n <ion-icon slot=\"icon-only\" name=\"arrow-undo\" />\n </ion-button>\n }\n <ion-button [title]=\"'IDEA_UNCOMMON.CALENDAR.CLOSE_WITHOUT_SAVING' | translate\" (click)=\"close()\">\n <ion-icon slot=\"icon-only\" name=\"close\" />\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n <ion-grid fixed class=\"ion-no-padding\">\n <ion-row>\n <h1 class=\"headerLabel\">{{ 'IDEA_UNCOMMON.CALENDAR.SET_DATE' | translate }}</h1>\n </ion-row>\n <ion-row style=\"margin-bottom: 8px\">\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"5\">\n <ion-row class=\"ion-align-items-center ion-justify-content-center\">\n <ion-col class=\"ion-text-right ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addYears(-1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-back\" />\n </ion-button>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding tappable\" [size]=\"6\">\n <ion-input\n type=\"text\"\n [placeholder]=\"'IDEA_UNCOMMON.CALENDAR.YEAR' | translate\"\n [value]=\"refDate().getFullYear()\"\n (ionFocus)=\"$event.target.value = ''\"\n (ionChange)=\"setYear($event?.target?.value)\"\n >\n </ion-input>\n </ion-col>\n <ion-col class=\"ion-text-left ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addYears(+1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-forward\" />\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"7\">\n <ion-row class=\"ion-align-items-center\">\n <ion-col class=\"ion-text-right ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addMonths(-1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-back\" />\n </ion-button>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding tappable\" [size]=\"6\" (click)=\"showMonths()\">\n {{ refDate() | dateLocale: 'MMMM' }}\n </ion-col>\n <ion-col class=\"ion-text-left ion-no-padding\" [size]=\"3\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"addMonths(+1)\">\n <ion-icon slot=\"icon-only\" name=\"chevron-forward\" />\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-col>\n </ion-row>\n <ion-row style=\"margin-bottom: 8px\" class=\"headerLabel\">\n @for (ddd of weekDays; track ddd) {\n <ion-col class=\"ion-text-center ion-no-padding\">\n {{ ddd }}\n </ion-col>\n }\n </ion-row>\n @for (row of calendarGrid(); track row; let i = $index) {\n <ion-row class=\"ion-align-items-center\">\n @for (col of row; track col; let j = $index) {\n <ion-col class=\"ion-text-center ion-no-padding\">\n <ion-button\n size=\"small\"\n shape=\"round\"\n [color]=\"\n isSameDay(calendarGrid()[i][j], today) || isSameDay(calendarGrid()[i][j], selectedDate)\n ? 'primary'\n : isSameMonth(calendarGrid()[i][j], refDate())\n ? 'dark'\n : 'medium'\n \"\n [fill]=\"\n isSameDay(calendarGrid()[i][j], selectedDate)\n ? 'solid'\n : isSameDay(calendarGrid()[i][j], today)\n ? 'outline'\n : 'clear'\n \"\n [disabled]=\"!isDateSelectable(calendarGrid()[i][j])\"\n (click)=\"selectDate(calendarGrid()[i][j])\"\n >\n {{ calendarGrid()[i][j] | date: 'd' }}\n </ion-button>\n </ion-col>\n }\n </ion-row>\n }\n @if (timePicker || manualTimePicker) {\n <ion-row>\n <h1 class=\"headerLabel\">\n {{ 'IDEA_UNCOMMON.CALENDAR.SET_TIME' | translate }}\n </h1>\n </ion-row>\n }\n @if (timePicker) {\n <ion-row class=\"ion-align-items-center\">\n <ion-col class=\"ion-no-padding\" [size]=\"7\">\n <ion-row>\n @for (hour of hours; track hour) {\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"2\">\n <ion-button\n size=\"small\"\n shape=\"round\"\n [color]=\"isSameHour(hour) ? 'primary' : 'dark'\"\n [fill]=\"isSameHour(hour) ? 'solid' : 'clear'\"\n (click)=\"selectHour(hour)\"\n >\n {{ hour }}\n </ion-button>\n </ion-col>\n }\n </ion-row>\n </ion-col>\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"1\"> : </ion-col>\n <ion-col class=\"ion-no-padding\" [size]=\"4\">\n <ion-row>\n @for (minute of minutes; track minute) {\n <ion-col class=\"ion-text-center ion-no-padding\" [size]=\"4\">\n <ion-button\n size=\"small\"\n shape=\"round\"\n [color]=\"isSameMinute(minute) ? 'primary' : 'dark'\"\n [fill]=\"isSameMinute(minute) ? 'solid' : 'clear'\"\n (click)=\"selectMinute(minute)\"\n >\n {{ minute }}\n </ion-button>\n </ion-col>\n }\n </ion-row>\n </ion-col>\n </ion-row>\n }\n @if (manualTimePicker) {\n <ion-row class=\"ion-align-items-center manualTimePicker\">\n <ion-col class=\"ion-text-center\" [size]=\"12\">\n <input type=\"number\" min=\"0\" max=\"23\" [value]=\"hour\" (change)=\"selectHour($event.target.value)\" />\n <span>:</span>\n <input type=\"number\" min=\"0\" max=\"59\" [value]=\"minute\" (change)=\"selectMinute($event.target.value)\" />\n </ion-col>\n </ion-row>\n }\n </ion-grid>\n</ion-content>\n<ion-footer>\n <ion-toolbar color=\"ideaToolbar\" class=\"tappable\" (click)=\"save()\">\n <ion-title class=\"ion-text-center\">\n <ion-icon name=\"checkmark\" />\n </ion-title>\n </ion-toolbar>\n</ion-footer>\n", styles: ["ion-content{--background: var(--ion-color-white)}h1{margin:10px}.headerLabel{font-size:.7em;font-weight:700;text-transform:uppercase}ion-col,ion-button{font-size:.95em}ion-button{margin:3px 0}ion-footer ion-toolbar{--min-height: 40px}.tappable{cursor:pointer}.manualTimePicker{padding:20px}.manualTimePicker input[type=number],.manualTimePicker span{font-size:2.5em}.manualTimePicker input[type=number]{border:none;border-bottom:2px solid var(--ion-color-dark);text-align:center}.manualTimePicker span{padding-left:4px;padding-right:4px}\n"] }]
|
|
2038
2060
|
}], propDecorators: { inputDate: [{
|
|
2039
2061
|
type: Input
|
|
2040
2062
|
}], timePicker: [{
|
|
@@ -2055,7 +2077,6 @@ class IDEADateTimeComponent {
|
|
|
2055
2077
|
constructor() {
|
|
2056
2078
|
this._modal = inject(ModalController);
|
|
2057
2079
|
this._translate = inject(IDEATranslationsService);
|
|
2058
|
-
this._cdr = inject(ChangeDetectorRef);
|
|
2059
2080
|
/**
|
|
2060
2081
|
* The date to show/pick.
|
|
2061
2082
|
*/
|
|
@@ -2133,12 +2154,14 @@ class IDEADateTimeComponent {
|
|
|
2133
2154
|
...(ngDevMode ? [undefined, { debugName: "max" }] : /* istanbul ignore next */ []));
|
|
2134
2155
|
this.dateChange = output();
|
|
2135
2156
|
this.iconSelect = output();
|
|
2136
|
-
this.
|
|
2157
|
+
this.valueToDisplay = signal('', /* @ts-ignore */
|
|
2158
|
+
...(ngDevMode ? [{ debugName: "valueToDisplay" }] : /* istanbul ignore next */ []));
|
|
2159
|
+
this.isOpening = signal(false, /* @ts-ignore */
|
|
2160
|
+
...(ngDevMode ? [{ debugName: "isOpening" }] : /* istanbul ignore next */ []));
|
|
2137
2161
|
}
|
|
2138
2162
|
ngOnInit() {
|
|
2139
2163
|
this.langChangeSubscription = this._translate.onLangChange.subscribe(() => {
|
|
2140
|
-
this.valueToDisplay
|
|
2141
|
-
this._cdr.markForCheck();
|
|
2164
|
+
this.valueToDisplay.set(this.getValueToDisplay(this.date()));
|
|
2142
2165
|
});
|
|
2143
2166
|
}
|
|
2144
2167
|
ngOnDestroy() {
|
|
@@ -2147,12 +2170,12 @@ class IDEADateTimeComponent {
|
|
|
2147
2170
|
}
|
|
2148
2171
|
ngOnChanges(changes) {
|
|
2149
2172
|
if (changes.date || changes.timePicker)
|
|
2150
|
-
this.valueToDisplay
|
|
2173
|
+
this.valueToDisplay.set(this.getValueToDisplay(this.date()));
|
|
2151
2174
|
}
|
|
2152
2175
|
async openCalendarPicker() {
|
|
2153
|
-
if (this.disabled() || this.isOpening)
|
|
2176
|
+
if (this.disabled() || this.isOpening())
|
|
2154
2177
|
return;
|
|
2155
|
-
this.isOpening
|
|
2178
|
+
this.isOpening.set(true);
|
|
2156
2179
|
const modal = await this._modal.create({
|
|
2157
2180
|
component: IDEACalendarPickerComponent,
|
|
2158
2181
|
componentProps: {
|
|
@@ -2174,7 +2197,7 @@ class IDEADateTimeComponent {
|
|
|
2174
2197
|
}
|
|
2175
2198
|
});
|
|
2176
2199
|
modal.present();
|
|
2177
|
-
this.isOpening
|
|
2200
|
+
this.isOpening.set(false);
|
|
2178
2201
|
}
|
|
2179
2202
|
getValueToDisplay(date) {
|
|
2180
2203
|
return !date
|
|
@@ -2197,7 +2220,7 @@ class IDEADateTimeComponent {
|
|
|
2197
2220
|
[lines]="lines()"
|
|
2198
2221
|
[title]="placeholder() || label() || ''"
|
|
2199
2222
|
[button]="!disabled()"
|
|
2200
|
-
[disabled]="isOpening"
|
|
2223
|
+
[disabled]="isOpening()"
|
|
2201
2224
|
[class.withLabel]="label()"
|
|
2202
2225
|
(click)="openCalendarPicker()"
|
|
2203
2226
|
>
|
|
@@ -2221,12 +2244,12 @@ class IDEADateTimeComponent {
|
|
|
2221
2244
|
</ion-label>
|
|
2222
2245
|
}
|
|
2223
2246
|
<ion-label class="value" [class.selectable]="!disabled()">
|
|
2224
|
-
@if (!valueToDisplay && !disabled()) {
|
|
2247
|
+
@if (!valueToDisplay() && !disabled()) {
|
|
2225
2248
|
<ion-text class="placeholder" [class.selectable]="!disabled()">
|
|
2226
2249
|
{{ placeholder() }}
|
|
2227
2250
|
</ion-text>
|
|
2228
2251
|
}
|
|
2229
|
-
{{ valueToDisplay }}
|
|
2252
|
+
{{ valueToDisplay() }}
|
|
2230
2253
|
</ion-label>
|
|
2231
2254
|
@if (!disabled()) {
|
|
2232
2255
|
<ion-icon slot="end" icon="caret-down" class="selectIcon" [class.selectable]="!disabled()" />
|
|
@@ -2243,7 +2266,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
2243
2266
|
[lines]="lines()"
|
|
2244
2267
|
[title]="placeholder() || label() || ''"
|
|
2245
2268
|
[button]="!disabled()"
|
|
2246
|
-
[disabled]="isOpening"
|
|
2269
|
+
[disabled]="isOpening()"
|
|
2247
2270
|
[class.withLabel]="label()"
|
|
2248
2271
|
(click)="openCalendarPicker()"
|
|
2249
2272
|
>
|
|
@@ -2267,12 +2290,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
2267
2290
|
</ion-label>
|
|
2268
2291
|
}
|
|
2269
2292
|
<ion-label class="value" [class.selectable]="!disabled()">
|
|
2270
|
-
@if (!valueToDisplay && !disabled()) {
|
|
2293
|
+
@if (!valueToDisplay() && !disabled()) {
|
|
2271
2294
|
<ion-text class="placeholder" [class.selectable]="!disabled()">
|
|
2272
2295
|
{{ placeholder() }}
|
|
2273
2296
|
</ion-text>
|
|
2274
2297
|
}
|
|
2275
|
-
{{ valueToDisplay }}
|
|
2298
|
+
{{ valueToDisplay() }}
|
|
2276
2299
|
</ion-label>
|
|
2277
2300
|
@if (!disabled()) {
|
|
2278
2301
|
<ion-icon slot="end" icon="caret-down" class="selectIcon" [class.selectable]="!disabled()" />
|
|
@@ -2500,6 +2523,12 @@ class IDEAEchoPage {
|
|
|
2500
2523
|
this._loading = inject(IDEALoadingService);
|
|
2501
2524
|
this._API = inject(IDEAAWSAPIService);
|
|
2502
2525
|
this._translate = inject(IDEATranslationsService);
|
|
2526
|
+
this.content = signal(undefined, /* @ts-ignore */
|
|
2527
|
+
...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
|
|
2528
|
+
this.htmlContent = signal(undefined, /* @ts-ignore */
|
|
2529
|
+
...(ngDevMode ? [{ debugName: "htmlContent" }] : /* istanbul ignore next */ []));
|
|
2530
|
+
this.success = signal(undefined, /* @ts-ignore */
|
|
2531
|
+
...(ngDevMode ? [{ debugName: "success" }] : /* istanbul ignore next */ []));
|
|
2503
2532
|
}
|
|
2504
2533
|
ngOnInit() {
|
|
2505
2534
|
const request = this._route.snapshot.paramMap.get('request') || this._route.snapshot.queryParams.request;
|
|
@@ -2532,15 +2561,15 @@ class IDEAEchoPage {
|
|
|
2532
2561
|
this.endExternalCalendarsIntegrationFlow(ExternalCalendarSources.GOOGLE, code, state);
|
|
2533
2562
|
break;
|
|
2534
2563
|
default:
|
|
2535
|
-
this.success
|
|
2536
|
-
this.content
|
|
2564
|
+
this.success.set(false);
|
|
2565
|
+
this.content.set(this._translate._('IDEA_UNCOMMON.ECHO.INVALID_ACTION'));
|
|
2537
2566
|
break;
|
|
2538
2567
|
}
|
|
2539
2568
|
}
|
|
2540
2569
|
maintenanceMode() {
|
|
2541
2570
|
const announcement = this._tc.get('idea-announcement');
|
|
2542
2571
|
if (announcement && announcement.content)
|
|
2543
|
-
this.htmlContent
|
|
2572
|
+
this.htmlContent.set(mdToHtml(announcement.content));
|
|
2544
2573
|
}
|
|
2545
2574
|
async followRegistrationLink(code, user) {
|
|
2546
2575
|
try {
|
|
@@ -2554,12 +2583,12 @@ class IDEAEchoPage {
|
|
|
2554
2583
|
cognitoUserPoolClientId: this._env.aws.cognito.userPoolClientId
|
|
2555
2584
|
}
|
|
2556
2585
|
});
|
|
2557
|
-
this.success
|
|
2558
|
-
this.content
|
|
2586
|
+
this.success.set(true);
|
|
2587
|
+
this.content.set(this._translate._('IDEA_UNCOMMON.ECHO.ACCOUNT_CONFIRMED'));
|
|
2559
2588
|
}
|
|
2560
2589
|
catch (error) {
|
|
2561
|
-
this.success
|
|
2562
|
-
this.content
|
|
2590
|
+
this.success.set(false);
|
|
2591
|
+
this.content.set(this._translate._('IDEA_UNCOMMON.ECHO.REQUEST_FAILED'));
|
|
2563
2592
|
}
|
|
2564
2593
|
finally {
|
|
2565
2594
|
this._loading.hide();
|
|
@@ -2569,12 +2598,12 @@ class IDEAEchoPage {
|
|
|
2569
2598
|
try {
|
|
2570
2599
|
await this._loading.show();
|
|
2571
2600
|
await this._API.getResource('invitations', { idea: true, resourceId: code });
|
|
2572
|
-
this.success
|
|
2573
|
-
this.content
|
|
2601
|
+
this.success.set(true);
|
|
2602
|
+
this.content.set(this._translate._('IDEA_UNCOMMON.ECHO.TEAM_JOINED'));
|
|
2574
2603
|
}
|
|
2575
2604
|
catch (error) {
|
|
2576
|
-
this.success
|
|
2577
|
-
this.content
|
|
2605
|
+
this.success.set(false);
|
|
2606
|
+
this.content.set(this._translate._('IDEA_UNCOMMON.ECHO.REQUEST_FAILED'));
|
|
2578
2607
|
}
|
|
2579
2608
|
finally {
|
|
2580
2609
|
this._loading.hide();
|
|
@@ -2588,28 +2617,28 @@ class IDEAEchoPage {
|
|
|
2588
2617
|
resourceId: code,
|
|
2589
2618
|
params: { project: this._env.idea.project }
|
|
2590
2619
|
});
|
|
2591
|
-
this.success
|
|
2592
|
-
this.content
|
|
2620
|
+
this.success.set(true);
|
|
2621
|
+
this.content.set(this._translate._('IDEA_UNCOMMON.ECHO.EMAIL_CHANGED'));
|
|
2593
2622
|
}
|
|
2594
2623
|
catch (error) {
|
|
2595
|
-
this.success
|
|
2596
|
-
this.content
|
|
2624
|
+
this.success.set(false);
|
|
2625
|
+
this.content.set(this._translate._('IDEA_UNCOMMON.ECHO.REQUEST_FAILED'));
|
|
2597
2626
|
}
|
|
2598
2627
|
finally {
|
|
2599
2628
|
this._loading.hide();
|
|
2600
2629
|
}
|
|
2601
2630
|
}
|
|
2602
2631
|
endGitHubIntegrationFlow(success) {
|
|
2603
|
-
this.success
|
|
2604
|
-
this.content
|
|
2632
|
+
this.success.set(success);
|
|
2633
|
+
this.content.set(success
|
|
2605
2634
|
? this._translate._('IDEA_UNCOMMON.ECHO.GITHUB_SOURCE_INTEGRATION_SUCCESS')
|
|
2606
|
-
: this._translate._('IDEA_UNCOMMON.ECHO.GITHUB_SOURCE_INTEGRATION_ERROR');
|
|
2635
|
+
: this._translate._('IDEA_UNCOMMON.ECHO.GITHUB_SOURCE_INTEGRATION_ERROR'));
|
|
2607
2636
|
}
|
|
2608
2637
|
endTrelloIntegrationFlow(token) {
|
|
2609
|
-
this.success
|
|
2610
|
-
this.content
|
|
2638
|
+
this.success.set(Boolean(token));
|
|
2639
|
+
this.content.set(token
|
|
2611
2640
|
? this._translate._('IDEA_UNCOMMON.ECHO.TRELLO_SOURCE_INTEGRATION_SUCCESS', { token })
|
|
2612
|
-
: this._translate._('IDEA_UNCOMMON.ECHO.TRELLO_SOURCE_INTEGRATION_ERROR');
|
|
2641
|
+
: this._translate._('IDEA_UNCOMMON.ECHO.TRELLO_SOURCE_INTEGRATION_ERROR'));
|
|
2613
2642
|
}
|
|
2614
2643
|
async endExternalCalendarsIntegrationFlow(service, code, calendarId) {
|
|
2615
2644
|
try {
|
|
@@ -2618,12 +2647,12 @@ class IDEAEchoPage {
|
|
|
2618
2647
|
idea: true,
|
|
2619
2648
|
body: { action: 'SET_EXTERNAL_INTEGRATION', service, code, calendarId, project: this._env.idea.project }
|
|
2620
2649
|
});
|
|
2621
|
-
this.success
|
|
2622
|
-
this.content
|
|
2650
|
+
this.success.set(true);
|
|
2651
|
+
this.content.set(this._translate._('IDEA_UNCOMMON.ECHO.EXTERNAL_CALENDARS_SOURCE_INTEGRATION_SUCCESS'));
|
|
2623
2652
|
}
|
|
2624
2653
|
catch (error) {
|
|
2625
|
-
this.success
|
|
2626
|
-
this.content
|
|
2654
|
+
this.success.set(false);
|
|
2655
|
+
this.content.set(this._translate._('IDEA_UNCOMMON.ECHO.EXTERNAL_CALENDARS_SOURCE_INTEGRATION_ERROR'));
|
|
2627
2656
|
}
|
|
2628
2657
|
finally {
|
|
2629
2658
|
this._loading.hide();
|
|
@@ -2637,20 +2666,20 @@ class IDEAEchoPage {
|
|
|
2637
2666
|
<ion-img [src]="'assets/icons/icon-auth.svg'" />
|
|
2638
2667
|
<ion-card-header>
|
|
2639
2668
|
<ion-card-title>
|
|
2640
|
-
@if (success === true) {
|
|
2669
|
+
@if (success() === true) {
|
|
2641
2670
|
<ion-icon testId="echoSuccess" color="success" name="checkmark" />
|
|
2642
2671
|
}
|
|
2643
|
-
@if (success === false) {
|
|
2672
|
+
@if (success() === false) {
|
|
2644
2673
|
<ion-icon testId="echoFailure" color="danger" name="close" />
|
|
2645
2674
|
}
|
|
2646
2675
|
</ion-card-title>
|
|
2647
2676
|
</ion-card-header>
|
|
2648
2677
|
<ion-card-content class="selectable">
|
|
2649
|
-
{{ content }}
|
|
2650
|
-
@if (htmlContent) {
|
|
2651
|
-
<div class="htmlContent" [innerHTML]="htmlContent"></div>
|
|
2678
|
+
{{ content() }}
|
|
2679
|
+
@if (htmlContent()) {
|
|
2680
|
+
<div class="htmlContent" [innerHTML]="htmlContent()"></div>
|
|
2652
2681
|
}
|
|
2653
|
-
@if (success === false || success === true) {
|
|
2682
|
+
@if (success() === false || success() === true) {
|
|
2654
2683
|
<p class="youCanCloseMe">
|
|
2655
2684
|
<i>{{ 'IDEA_UNCOMMON.ECHO.YOU_CAN_CLOSE_THE_PAGE' | translate }}</i>
|
|
2656
2685
|
</p>
|
|
@@ -2670,20 +2699,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
2670
2699
|
<ion-img [src]="'assets/icons/icon-auth.svg'" />
|
|
2671
2700
|
<ion-card-header>
|
|
2672
2701
|
<ion-card-title>
|
|
2673
|
-
@if (success === true) {
|
|
2702
|
+
@if (success() === true) {
|
|
2674
2703
|
<ion-icon testId="echoSuccess" color="success" name="checkmark" />
|
|
2675
2704
|
}
|
|
2676
|
-
@if (success === false) {
|
|
2705
|
+
@if (success() === false) {
|
|
2677
2706
|
<ion-icon testId="echoFailure" color="danger" name="close" />
|
|
2678
2707
|
}
|
|
2679
2708
|
</ion-card-title>
|
|
2680
2709
|
</ion-card-header>
|
|
2681
2710
|
<ion-card-content class="selectable">
|
|
2682
|
-
{{ content }}
|
|
2683
|
-
@if (htmlContent) {
|
|
2684
|
-
<div class="htmlContent" [innerHTML]="htmlContent"></div>
|
|
2711
|
+
{{ content() }}
|
|
2712
|
+
@if (htmlContent()) {
|
|
2713
|
+
<div class="htmlContent" [innerHTML]="htmlContent()"></div>
|
|
2685
2714
|
}
|
|
2686
|
-
@if (success === false || success === true) {
|
|
2715
|
+
@if (success() === false || success() === true) {
|
|
2687
2716
|
<p class="youCanCloseMe">
|
|
2688
2717
|
<i>{{ 'IDEA_UNCOMMON.ECHO.YOU_CAN_CLOSE_THE_PAGE' | translate }}</i>
|
|
2689
2718
|
</p>
|
|
@@ -2938,6 +2967,26 @@ class IDEAOfflineDataService {
|
|
|
2938
2967
|
this._translate = inject(IDEATranslationsService);
|
|
2939
2968
|
this._offline = inject(IDEAOfflineService);
|
|
2940
2969
|
this._API = inject(IDEAAWSAPIService);
|
|
2970
|
+
/**
|
|
2971
|
+
* True when running a synchronization.
|
|
2972
|
+
*/
|
|
2973
|
+
this.synchronizing = signal(undefined, /* @ts-ignore */
|
|
2974
|
+
...(ngDevMode ? [{ debugName: "synchronizing" }] : /* istanbul ignore next */ []));
|
|
2975
|
+
/**
|
|
2976
|
+
* The timestamp of the last synchronization.
|
|
2977
|
+
*/
|
|
2978
|
+
this.lastSyncAt = signal(undefined, /* @ts-ignore */
|
|
2979
|
+
...(ngDevMode ? [{ debugName: "lastSyncAt" }] : /* istanbul ignore next */ []));
|
|
2980
|
+
/**
|
|
2981
|
+
* True if an error happened in the last synchronization.
|
|
2982
|
+
*/
|
|
2983
|
+
this.errorInLastSync = signal(undefined, /* @ts-ignore */
|
|
2984
|
+
...(ngDevMode ? [{ debugName: "errorInLastSync" }] : /* istanbul ignore next */ []));
|
|
2985
|
+
/**
|
|
2986
|
+
* True if the synchronisation is too vast and so require a manual action of the user.
|
|
2987
|
+
*/
|
|
2988
|
+
this.requiresManualConfirmation = signal(undefined, /* @ts-ignore */
|
|
2989
|
+
...(ngDevMode ? [{ debugName: "requiresManualConfirmation" }] : /* istanbul ignore next */ []));
|
|
2941
2990
|
this.queueAPIRequests = new Array();
|
|
2942
2991
|
this.resources = new Array();
|
|
2943
2992
|
this.cacheableResources = {};
|
|
@@ -2945,7 +2994,7 @@ class IDEAOfflineDataService {
|
|
|
2945
2994
|
this._offline.subscribe(isOnline => {
|
|
2946
2995
|
if (isOnline) {
|
|
2947
2996
|
// try a synchronization if needed or if the last one failed
|
|
2948
|
-
if (this.errorInLastSync)
|
|
2997
|
+
if (this.errorInLastSync())
|
|
2949
2998
|
this.synchronize();
|
|
2950
2999
|
else
|
|
2951
3000
|
this.synchronizeIfNeeded();
|
|
@@ -3013,8 +3062,8 @@ class IDEAOfflineDataService {
|
|
|
3013
3062
|
loadLastSyncAt() {
|
|
3014
3063
|
return new Promise(resolve => {
|
|
3015
3064
|
this._storage.get(this.lastSyncKey).then((lastSyncAt) => {
|
|
3016
|
-
this.lastSyncAt
|
|
3017
|
-
resolve(this.lastSyncAt);
|
|
3065
|
+
this.lastSyncAt.set(lastSyncAt ? Number(lastSyncAt) : null);
|
|
3066
|
+
resolve(this.lastSyncAt());
|
|
3018
3067
|
});
|
|
3019
3068
|
});
|
|
3020
3069
|
}
|
|
@@ -3022,7 +3071,7 @@ class IDEAOfflineDataService {
|
|
|
3022
3071
|
* Update last sync at info in the local storage.
|
|
3023
3072
|
*/
|
|
3024
3073
|
saveLastSyncAt(lastSyncAt) {
|
|
3025
|
-
this.lastSyncAt
|
|
3074
|
+
this.lastSyncAt.set(lastSyncAt);
|
|
3026
3075
|
return this._storage.set(this.lastSyncKey, lastSyncAt);
|
|
3027
3076
|
}
|
|
3028
3077
|
/**
|
|
@@ -3155,22 +3204,22 @@ class IDEAOfflineDataService {
|
|
|
3155
3204
|
cr.synchronizing = true;
|
|
3156
3205
|
const success = await this.syncResourceDeltaRecords(resource, delta.records[resource]);
|
|
3157
3206
|
if (!success)
|
|
3158
|
-
this.errorInLastSync
|
|
3207
|
+
this.errorInLastSync.set(true);
|
|
3159
3208
|
}
|
|
3160
3209
|
}));
|
|
3161
3210
|
// if there were error of if there is nothing left to sync, we are done
|
|
3162
|
-
if (this.errorInLastSync || !delta.next)
|
|
3211
|
+
if (this.errorInLastSync() || !delta.next)
|
|
3163
3212
|
return done();
|
|
3164
3213
|
// otherwise, get the next page of the delta and go recursive until we are done
|
|
3165
3214
|
const params = { next: delta.next, limit: NUM_ELEMENTS_WITH_MANUAL_SYNC };
|
|
3166
|
-
if (this.lastSyncAt)
|
|
3167
|
-
params.since = this.lastSyncAt;
|
|
3215
|
+
if (this.lastSyncAt())
|
|
3216
|
+
params.since = this.lastSyncAt();
|
|
3168
3217
|
const newDelta = await this._API.getResource(this.teamId ? `teams/${this.teamId}/delta` : 'delta', { params });
|
|
3169
3218
|
this.syncDeltaRecords(newDelta, done);
|
|
3170
3219
|
}
|
|
3171
3220
|
catch (err) {
|
|
3172
3221
|
// if something went wrong, stops the operation, since we need to make sure the entire flow is consistent
|
|
3173
|
-
this.errorInLastSync
|
|
3222
|
+
this.errorInLastSync.set(true);
|
|
3174
3223
|
return done();
|
|
3175
3224
|
}
|
|
3176
3225
|
}
|
|
@@ -3246,7 +3295,7 @@ class IDEAOfflineDataService {
|
|
|
3246
3295
|
return;
|
|
3247
3296
|
this.loadLastSyncAt().then(() => this.loadQueueAPIRequest()
|
|
3248
3297
|
.then(() => {
|
|
3249
|
-
if (this.queueAPIRequests.length || Date.now() > this.lastSyncAt + SYNC_EXPIRATION_INTERVAL)
|
|
3298
|
+
if (this.queueAPIRequests.length || Date.now() > this.lastSyncAt() + SYNC_EXPIRATION_INTERVAL)
|
|
3250
3299
|
this.synchronize();
|
|
3251
3300
|
resolve();
|
|
3252
3301
|
})
|
|
@@ -3259,11 +3308,11 @@ class IDEAOfflineDataService {
|
|
|
3259
3308
|
*/
|
|
3260
3309
|
synchronize(manualConfirmation) {
|
|
3261
3310
|
return new Promise((resolve, reject) => {
|
|
3262
|
-
if (!this.isAllowed() || this.synchronizing)
|
|
3311
|
+
if (!this.isAllowed() || this.synchronizing())
|
|
3263
3312
|
return resolve();
|
|
3264
|
-
this.synchronizing
|
|
3265
|
-
this.errorInLastSync
|
|
3266
|
-
this.requiresManualConfirmation
|
|
3313
|
+
this.synchronizing.set(true);
|
|
3314
|
+
this.errorInLastSync.set(false);
|
|
3315
|
+
this.requiresManualConfirmation.set(false);
|
|
3267
3316
|
// load the lastSyncAt information
|
|
3268
3317
|
this.loadLastSyncAt().then(() =>
|
|
3269
3318
|
// try to run all the pending API requests in the queue, i.e. uploading the offline resources changed
|
|
@@ -3273,21 +3322,21 @@ class IDEAOfflineDataService {
|
|
|
3273
3322
|
const now = Date.now();
|
|
3274
3323
|
// prepare a first "short" Delta request, to see if there is a lot of data to process
|
|
3275
3324
|
const params = { limit: NUM_ELEMENTS_WITHOUT_MANUAL_SYNC };
|
|
3276
|
-
if (this.lastSyncAt)
|
|
3277
|
-
params.since = this.lastSyncAt;
|
|
3325
|
+
if (this.lastSyncAt())
|
|
3326
|
+
params.since = this.lastSyncAt();
|
|
3278
3327
|
this._API
|
|
3279
3328
|
.getResource(this.teamId ? `teams/${this.teamId}/delta` : 'delta', { params })
|
|
3280
3329
|
.then((delta) => {
|
|
3281
3330
|
// decide if to proceed with the sync: in case there is another page, it requires a manual confirmation
|
|
3282
3331
|
if (delta.next && !manualConfirmation) {
|
|
3283
|
-
this.requiresManualConfirmation
|
|
3284
|
-
this.synchronizing
|
|
3332
|
+
this.requiresManualConfirmation.set(true);
|
|
3333
|
+
this.synchronizing.set(false);
|
|
3285
3334
|
return resolve();
|
|
3286
3335
|
}
|
|
3287
3336
|
// save the records in the delta and request possible new pages
|
|
3288
3337
|
this.syncDeltaRecords(delta, () => {
|
|
3289
|
-
if (this.errorInLastSync) {
|
|
3290
|
-
this.synchronizing
|
|
3338
|
+
if (this.errorInLastSync()) {
|
|
3339
|
+
this.synchronizing.set(false);
|
|
3291
3340
|
resolve();
|
|
3292
3341
|
}
|
|
3293
3342
|
else {
|
|
@@ -3296,13 +3345,13 @@ class IDEAOfflineDataService {
|
|
|
3296
3345
|
// update the timestamp of last sync
|
|
3297
3346
|
this.saveLastSyncAt(now)
|
|
3298
3347
|
.then(() => {
|
|
3299
|
-
this.synchronizing
|
|
3348
|
+
this.synchronizing.set(false);
|
|
3300
3349
|
resolve();
|
|
3301
3350
|
})
|
|
3302
3351
|
.catch(() => {
|
|
3303
3352
|
// we couldn't save the last sync info
|
|
3304
|
-
this.errorInLastSync
|
|
3305
|
-
this.synchronizing
|
|
3353
|
+
this.errorInLastSync.set(true);
|
|
3354
|
+
this.synchronizing.set(false);
|
|
3306
3355
|
reject();
|
|
3307
3356
|
});
|
|
3308
3357
|
}
|
|
@@ -3310,15 +3359,15 @@ class IDEAOfflineDataService {
|
|
|
3310
3359
|
})
|
|
3311
3360
|
.catch(() => {
|
|
3312
3361
|
// we couldn't acquire new information (Delta)
|
|
3313
|
-
this.errorInLastSync
|
|
3314
|
-
this.synchronizing
|
|
3362
|
+
this.errorInLastSync.set(true);
|
|
3363
|
+
this.synchronizing.set(false);
|
|
3315
3364
|
reject();
|
|
3316
3365
|
});
|
|
3317
3366
|
})
|
|
3318
3367
|
.catch(() => {
|
|
3319
3368
|
// we stop, since we don't want backend data to override local info not yet uploaded
|
|
3320
|
-
this.errorInLastSync
|
|
3321
|
-
this.synchronizing
|
|
3369
|
+
this.errorInLastSync.set(true);
|
|
3370
|
+
this.synchronizing.set(false);
|
|
3322
3371
|
reject();
|
|
3323
3372
|
}));
|
|
3324
3373
|
});
|
|
@@ -3366,13 +3415,13 @@ class IDEACacheableResourceComponent {
|
|
|
3366
3415
|
@if (resource().error) {
|
|
3367
3416
|
<ion-icon slot="end" name="alert-circle" color="danger" />
|
|
3368
3417
|
}
|
|
3369
|
-
@if (!resource().error && _offline.synchronizing && resource().synchronizing) {
|
|
3418
|
+
@if (!resource().error && _offline.synchronizing() && resource().synchronizing) {
|
|
3370
3419
|
<ion-spinner slot="end" name="dots" />
|
|
3371
3420
|
}
|
|
3372
|
-
@if (!resource().error && !resource().synchronizing && !_offline.requiresManualConfirmation) {
|
|
3421
|
+
@if (!resource().error && !resource().synchronizing && !_offline.requiresManualConfirmation()) {
|
|
3373
3422
|
<ion-icon slot="end" name="checkmark" color="success" />
|
|
3374
3423
|
}
|
|
3375
|
-
@if (!resource().error && !resource().synchronizing && _offline.requiresManualConfirmation) {
|
|
3424
|
+
@if (!resource().error && !resource().synchronizing && _offline.requiresManualConfirmation()) {
|
|
3376
3425
|
<ion-icon slot="end" name="pause" color="dark" />
|
|
3377
3426
|
}
|
|
3378
3427
|
</ion-item>
|
|
@@ -3390,13 +3439,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3390
3439
|
@if (resource().error) {
|
|
3391
3440
|
<ion-icon slot="end" name="alert-circle" color="danger" />
|
|
3392
3441
|
}
|
|
3393
|
-
@if (!resource().error && _offline.synchronizing && resource().synchronizing) {
|
|
3442
|
+
@if (!resource().error && _offline.synchronizing() && resource().synchronizing) {
|
|
3394
3443
|
<ion-spinner slot="end" name="dots" />
|
|
3395
3444
|
}
|
|
3396
|
-
@if (!resource().error && !resource().synchronizing && !_offline.requiresManualConfirmation) {
|
|
3445
|
+
@if (!resource().error && !resource().synchronizing && !_offline.requiresManualConfirmation()) {
|
|
3397
3446
|
<ion-icon slot="end" name="checkmark" color="success" />
|
|
3398
3447
|
}
|
|
3399
|
-
@if (!resource().error && !resource().synchronizing && _offline.requiresManualConfirmation) {
|
|
3448
|
+
@if (!resource().error && !resource().synchronizing && _offline.requiresManualConfirmation()) {
|
|
3400
3449
|
<ion-icon slot="end" name="pause" color="dark" />
|
|
3401
3450
|
}
|
|
3402
3451
|
</ion-item>
|
|
@@ -3472,7 +3521,7 @@ class IDEAOfflineManagerComponent {
|
|
|
3472
3521
|
this._modal.dismiss();
|
|
3473
3522
|
}
|
|
3474
3523
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: IDEAOfflineManagerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3475
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: IDEAOfflineManagerComponent, isStandalone: true, selector: "idea-offline-manager", ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"ideaToolbar\">\n <ion-buttons slot=\"start\">\n <ion-button (click)=\"close()\">\n <ion-icon name=\"close\" slot=\"icon-only\" />\n </ion-button>\n </ion-buttons>\n <ion-title>\n {{ 'IDEA_UNCOMMON.OFFLINE.OFFLINE_MANAGER' | translate }}\n </ion-title>\n <ion-buttons slot=\"end\">\n <ion-button [title]=\"'IDEA_UNCOMMON.OFFLINE.ADVANCED_ACTIONS' | translate\" (click)=\"actions()\">\n <ion-icon slot=\"icon-only\" name=\"ellipsis-vertical\" />\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n <ion-list class=\"aList\">\n @if (!_offline.synchronizing && _offline.requiresManualConfirmation) {\n <ion-list-header>\n <ion-label>\n <h2>{{ 'IDEA_UNCOMMON.OFFLINE.HUGE_SYNC_NEED_MANUAL_CONFIRMATION' | translate }}</h2>\n </ion-label>\n </ion-list-header>\n }\n @if (!_offline.synchronizing) {\n <ion-list-header>\n <ion-label class=\"ion-text-wrap\">\n <h3 class=\"lastSyncAt\">\n {{ 'IDEA_UNCOMMON.OFFLINE.LAST_SYNC' | translate }}:\n <ion-text>\n {{\n _offline.lastSyncAt\n ? (_offline.lastSyncAt | dateLocale: 'medium')\n : ('IDEA_UNCOMMON.OFFLINE.NEVER' | translate)\n }}\n </ion-text>\n </h3>\n @if (_offline.errorInLastSync) {\n <p>\n <ion-text color=\"danger\">\n <b>{{ 'IDEA_UNCOMMON.OFFLINE.ERROR_DURING_LAST_SYNC' | translate }}</b>\n </ion-text>\n </p>\n }\n </ion-label>\n <ion-button\n size=\"small\"\n fill=\"solid\"\n [color]=\"_offline.errorInLastSync ? 'danger' : 'dark'\"\n [disabled]=\"_offline.isOffline()\"\n (click)=\"sync()\"\n >\n <ion-icon slot=\"start\" name=\"sync\" /> {{ 'IDEA_UNCOMMON.OFFLINE.SYNC_NOW' | translate }}\n </ion-button>\n </ion-list-header>\n }\n </ion-list>\n @if (_offline.synchronizing) {\n <ion-list class=\"aList\">\n <ion-item>\n <ion-label class=\"ion-text-center\">\n <ion-spinner name=\"crescent\" color=\"primary\" />\n </ion-label>\n </ion-item>\n </ion-list>\n }\n @if (_offline.useQueueAPIRequests) {\n <ion-list class=\"aList\">\n <ion-list-header>\n <ion-label>\n <h2>{{ 'IDEA_UNCOMMON.OFFLINE.UPLOAD' | translate }}</h2>\n <p>{{ 'IDEA_UNCOMMON.OFFLINE.UPLOAD_QUEUE_REQUESTS_EXPLANATION' | translate }}</p>\n </ion-label>\n </ion-list-header>\n @if (!_offline.queueAPIRequests.length) {\n <ion-item>\n <i>{{ 'IDEA_UNCOMMON.OFFLINE.NO_ELEMENTS_TO_UPLOAD' | translate }}</i>\n <ion-icon slot=\"end\" size=\"small\" name=\"checkmark\" color=\"success\" />\n </ion-item>\n }\n @for (r of _offline.queueAPIRequests; track r; let odd = $odd) {\n <ion-item [class.oddItem]=\"odd\">\n <ion-label class=\"ion-text-wrap\">\n {{ r.description }}\n @if (r.error) {\n <p>\n <ion-text color=\"danger\">\n <b>{{ 'IDEA_UNCOMMON.OFFLINE.ERROR_CODE' | translate }}: {{ r.error }}</b>\n </ion-text>\n <br />\n {{ 'IDEA_UNCOMMON.OFFLINE.REQUEST_FAILED_EXPLANATION_I' | translate }}<br />\n {{ 'IDEA_UNCOMMON.OFFLINE.REQUEST_FAILED_EXPLANATION_II' | translate }}<br />\n {{ 'IDEA_UNCOMMON.OFFLINE.REQUEST_FAILED_EXPLANATION_III' | translate }}\n </p>\n }\n </ion-label>\n @if (r.error) {\n <ion-button\n fill=\"clear\"\n slot=\"end\"\n color=\"danger\"\n [title]=\"'IDEA_UNCOMMON.OFFLINE.CANCEL_REQUEST' | translate\"\n (click)=\"deleteRequest(r)\"\n >\n <ion-icon slot=\"icon-only\" name=\"trash\" />\n </ion-button>\n }\n @if (r.error) {\n <ion-button\n fill=\"clear\"\n slot=\"end\"\n color=\"medium\"\n [title]=\"'IDEA_UNCOMMON.OFFLINE.DOWNLOAD_LOG' | translate\"\n (click)=\"downloadRequestLog(r)\"\n >\n <ion-icon slot=\"icon-only\" name=\"download\" />\n </ion-button>\n }\n @if (_offline.synchronizing) {\n <ion-spinner slot=\"end\" name=\"dots\" />\n }\n </ion-item>\n }\n </ion-list>\n }\n @if (_offline.getResources().length) {\n <ion-list class=\"aList\">\n <ion-list-header>\n <ion-label>\n <h2>{{ 'IDEA_UNCOMMON.OFFLINE.DOWNLOAD' | translate }}</h2>\n <p>{{ 'IDEA_UNCOMMON.OFFLINE.DOWNLOAD_RESOURCES_EXPLANATION' | translate }}</p>\n </ion-label>\n </ion-list-header>\n @for (r of _offline.getResources(); track r) {\n <idea-cacheable-resource [resource]=\"_offline.getCacheableResource(r)\" />\n }\n </ion-list>\n }\n</ion-content>\n", styles: [".aList{max-width:500px;margin:0 auto}.aList ion-list-header{padding-right:10px}.aList ion-list-header h3.lastSyncAt{margin-top:6px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IDEACacheableResourceComponent, selector: "idea-cacheable-resource", inputs: ["resource"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonListHeader, selector: "ion-list-header", inputs: ["color", "lines", "mode"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "pipe", type: IDEATranslatePipe, name: "translate" }, { kind: "pipe", type: IDEALocalizedDatePipe, name: "dateLocale" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3524
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: IDEAOfflineManagerComponent, isStandalone: true, selector: "idea-offline-manager", ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"ideaToolbar\">\n <ion-buttons slot=\"start\">\n <ion-button (click)=\"close()\">\n <ion-icon name=\"close\" slot=\"icon-only\" />\n </ion-button>\n </ion-buttons>\n <ion-title>\n {{ 'IDEA_UNCOMMON.OFFLINE.OFFLINE_MANAGER' | translate }}\n </ion-title>\n <ion-buttons slot=\"end\">\n <ion-button [title]=\"'IDEA_UNCOMMON.OFFLINE.ADVANCED_ACTIONS' | translate\" (click)=\"actions()\">\n <ion-icon slot=\"icon-only\" name=\"ellipsis-vertical\" />\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n <ion-list class=\"aList\">\n @if (!_offline.synchronizing() && _offline.requiresManualConfirmation()) {\n <ion-list-header>\n <ion-label>\n <h2>{{ 'IDEA_UNCOMMON.OFFLINE.HUGE_SYNC_NEED_MANUAL_CONFIRMATION' | translate }}</h2>\n </ion-label>\n </ion-list-header>\n }\n @if (!_offline.synchronizing()) {\n <ion-list-header>\n <ion-label class=\"ion-text-wrap\">\n <h3 class=\"lastSyncAt\">\n {{ 'IDEA_UNCOMMON.OFFLINE.LAST_SYNC' | translate }}:\n <ion-text>\n {{\n _offline.lastSyncAt()\n ? (_offline.lastSyncAt() | dateLocale: 'medium')\n : ('IDEA_UNCOMMON.OFFLINE.NEVER' | translate)\n }}\n </ion-text>\n </h3>\n @if (_offline.errorInLastSync()) {\n <p>\n <ion-text color=\"danger\">\n <b>{{ 'IDEA_UNCOMMON.OFFLINE.ERROR_DURING_LAST_SYNC' | translate }}</b>\n </ion-text>\n </p>\n }\n </ion-label>\n <ion-button\n size=\"small\"\n fill=\"solid\"\n [color]=\"_offline.errorInLastSync() ? 'danger' : 'dark'\"\n [disabled]=\"_offline.isOffline()\"\n (click)=\"sync()\"\n >\n <ion-icon slot=\"start\" name=\"sync\" /> {{ 'IDEA_UNCOMMON.OFFLINE.SYNC_NOW' | translate }}\n </ion-button>\n </ion-list-header>\n }\n </ion-list>\n @if (_offline.synchronizing()) {\n <ion-list class=\"aList\">\n <ion-item>\n <ion-label class=\"ion-text-center\">\n <ion-spinner name=\"crescent\" color=\"primary\" />\n </ion-label>\n </ion-item>\n </ion-list>\n }\n @if (_offline.useQueueAPIRequests) {\n <ion-list class=\"aList\">\n <ion-list-header>\n <ion-label>\n <h2>{{ 'IDEA_UNCOMMON.OFFLINE.UPLOAD' | translate }}</h2>\n <p>{{ 'IDEA_UNCOMMON.OFFLINE.UPLOAD_QUEUE_REQUESTS_EXPLANATION' | translate }}</p>\n </ion-label>\n </ion-list-header>\n @if (!_offline.queueAPIRequests.length) {\n <ion-item>\n <i>{{ 'IDEA_UNCOMMON.OFFLINE.NO_ELEMENTS_TO_UPLOAD' | translate }}</i>\n <ion-icon slot=\"end\" size=\"small\" name=\"checkmark\" color=\"success\" />\n </ion-item>\n }\n @for (r of _offline.queueAPIRequests; track r; let odd = $odd) {\n <ion-item [class.oddItem]=\"odd\">\n <ion-label class=\"ion-text-wrap\">\n {{ r.description }}\n @if (r.error) {\n <p>\n <ion-text color=\"danger\">\n <b>{{ 'IDEA_UNCOMMON.OFFLINE.ERROR_CODE' | translate }}: {{ r.error }}</b>\n </ion-text>\n <br />\n {{ 'IDEA_UNCOMMON.OFFLINE.REQUEST_FAILED_EXPLANATION_I' | translate }}<br />\n {{ 'IDEA_UNCOMMON.OFFLINE.REQUEST_FAILED_EXPLANATION_II' | translate }}<br />\n {{ 'IDEA_UNCOMMON.OFFLINE.REQUEST_FAILED_EXPLANATION_III' | translate }}\n </p>\n }\n </ion-label>\n @if (r.error) {\n <ion-button\n fill=\"clear\"\n slot=\"end\"\n color=\"danger\"\n [title]=\"'IDEA_UNCOMMON.OFFLINE.CANCEL_REQUEST' | translate\"\n (click)=\"deleteRequest(r)\"\n >\n <ion-icon slot=\"icon-only\" name=\"trash\" />\n </ion-button>\n }\n @if (r.error) {\n <ion-button\n fill=\"clear\"\n slot=\"end\"\n color=\"medium\"\n [title]=\"'IDEA_UNCOMMON.OFFLINE.DOWNLOAD_LOG' | translate\"\n (click)=\"downloadRequestLog(r)\"\n >\n <ion-icon slot=\"icon-only\" name=\"download\" />\n </ion-button>\n }\n @if (_offline.synchronizing()) {\n <ion-spinner slot=\"end\" name=\"dots\" />\n }\n </ion-item>\n }\n </ion-list>\n }\n @if (_offline.getResources().length) {\n <ion-list class=\"aList\">\n <ion-list-header>\n <ion-label>\n <h2>{{ 'IDEA_UNCOMMON.OFFLINE.DOWNLOAD' | translate }}</h2>\n <p>{{ 'IDEA_UNCOMMON.OFFLINE.DOWNLOAD_RESOURCES_EXPLANATION' | translate }}</p>\n </ion-label>\n </ion-list-header>\n @for (r of _offline.getResources(); track r) {\n <idea-cacheable-resource [resource]=\"_offline.getCacheableResource(r)\" />\n }\n </ion-list>\n }\n</ion-content>\n", styles: [".aList{max-width:500px;margin:0 auto}.aList ion-list-header{padding-right:10px}.aList ion-list-header h3.lastSyncAt{margin-top:6px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IDEACacheableResourceComponent, selector: "idea-cacheable-resource", inputs: ["resource"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonListHeader, selector: "ion-list-header", inputs: ["color", "lines", "mode"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "pipe", type: IDEATranslatePipe, name: "translate" }, { kind: "pipe", type: IDEALocalizedDatePipe, name: "dateLocale" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3476
3525
|
}
|
|
3477
3526
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: IDEAOfflineManagerComponent, decorators: [{
|
|
3478
3527
|
type: Component,
|
|
@@ -3494,7 +3543,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3494
3543
|
IonButton,
|
|
3495
3544
|
IonToolbar,
|
|
3496
3545
|
IonHeader
|
|
3497
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-header>\n <ion-toolbar color=\"ideaToolbar\">\n <ion-buttons slot=\"start\">\n <ion-button (click)=\"close()\">\n <ion-icon name=\"close\" slot=\"icon-only\" />\n </ion-button>\n </ion-buttons>\n <ion-title>\n {{ 'IDEA_UNCOMMON.OFFLINE.OFFLINE_MANAGER' | translate }}\n </ion-title>\n <ion-buttons slot=\"end\">\n <ion-button [title]=\"'IDEA_UNCOMMON.OFFLINE.ADVANCED_ACTIONS' | translate\" (click)=\"actions()\">\n <ion-icon slot=\"icon-only\" name=\"ellipsis-vertical\" />\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n <ion-list class=\"aList\">\n @if (!_offline.synchronizing && _offline.requiresManualConfirmation) {\n <ion-list-header>\n <ion-label>\n <h2>{{ 'IDEA_UNCOMMON.OFFLINE.HUGE_SYNC_NEED_MANUAL_CONFIRMATION' | translate }}</h2>\n </ion-label>\n </ion-list-header>\n }\n @if (!_offline.synchronizing) {\n <ion-list-header>\n <ion-label class=\"ion-text-wrap\">\n <h3 class=\"lastSyncAt\">\n {{ 'IDEA_UNCOMMON.OFFLINE.LAST_SYNC' | translate }}:\n <ion-text>\n {{\n _offline.lastSyncAt\n ? (_offline.lastSyncAt | dateLocale: 'medium')\n : ('IDEA_UNCOMMON.OFFLINE.NEVER' | translate)\n }}\n </ion-text>\n </h3>\n @if (_offline.errorInLastSync) {\n <p>\n <ion-text color=\"danger\">\n <b>{{ 'IDEA_UNCOMMON.OFFLINE.ERROR_DURING_LAST_SYNC' | translate }}</b>\n </ion-text>\n </p>\n }\n </ion-label>\n <ion-button\n size=\"small\"\n fill=\"solid\"\n [color]=\"_offline.errorInLastSync ? 'danger' : 'dark'\"\n [disabled]=\"_offline.isOffline()\"\n (click)=\"sync()\"\n >\n <ion-icon slot=\"start\" name=\"sync\" /> {{ 'IDEA_UNCOMMON.OFFLINE.SYNC_NOW' | translate }}\n </ion-button>\n </ion-list-header>\n }\n </ion-list>\n @if (_offline.synchronizing) {\n <ion-list class=\"aList\">\n <ion-item>\n <ion-label class=\"ion-text-center\">\n <ion-spinner name=\"crescent\" color=\"primary\" />\n </ion-label>\n </ion-item>\n </ion-list>\n }\n @if (_offline.useQueueAPIRequests) {\n <ion-list class=\"aList\">\n <ion-list-header>\n <ion-label>\n <h2>{{ 'IDEA_UNCOMMON.OFFLINE.UPLOAD' | translate }}</h2>\n <p>{{ 'IDEA_UNCOMMON.OFFLINE.UPLOAD_QUEUE_REQUESTS_EXPLANATION' | translate }}</p>\n </ion-label>\n </ion-list-header>\n @if (!_offline.queueAPIRequests.length) {\n <ion-item>\n <i>{{ 'IDEA_UNCOMMON.OFFLINE.NO_ELEMENTS_TO_UPLOAD' | translate }}</i>\n <ion-icon slot=\"end\" size=\"small\" name=\"checkmark\" color=\"success\" />\n </ion-item>\n }\n @for (r of _offline.queueAPIRequests; track r; let odd = $odd) {\n <ion-item [class.oddItem]=\"odd\">\n <ion-label class=\"ion-text-wrap\">\n {{ r.description }}\n @if (r.error) {\n <p>\n <ion-text color=\"danger\">\n <b>{{ 'IDEA_UNCOMMON.OFFLINE.ERROR_CODE' | translate }}: {{ r.error }}</b>\n </ion-text>\n <br />\n {{ 'IDEA_UNCOMMON.OFFLINE.REQUEST_FAILED_EXPLANATION_I' | translate }}<br />\n {{ 'IDEA_UNCOMMON.OFFLINE.REQUEST_FAILED_EXPLANATION_II' | translate }}<br />\n {{ 'IDEA_UNCOMMON.OFFLINE.REQUEST_FAILED_EXPLANATION_III' | translate }}\n </p>\n }\n </ion-label>\n @if (r.error) {\n <ion-button\n fill=\"clear\"\n slot=\"end\"\n color=\"danger\"\n [title]=\"'IDEA_UNCOMMON.OFFLINE.CANCEL_REQUEST' | translate\"\n (click)=\"deleteRequest(r)\"\n >\n <ion-icon slot=\"icon-only\" name=\"trash\" />\n </ion-button>\n }\n @if (r.error) {\n <ion-button\n fill=\"clear\"\n slot=\"end\"\n color=\"medium\"\n [title]=\"'IDEA_UNCOMMON.OFFLINE.DOWNLOAD_LOG' | translate\"\n (click)=\"downloadRequestLog(r)\"\n >\n <ion-icon slot=\"icon-only\" name=\"download\" />\n </ion-button>\n }\n @if (_offline.synchronizing) {\n <ion-spinner slot=\"end\" name=\"dots\" />\n }\n </ion-item>\n }\n </ion-list>\n }\n @if (_offline.getResources().length) {\n <ion-list class=\"aList\">\n <ion-list-header>\n <ion-label>\n <h2>{{ 'IDEA_UNCOMMON.OFFLINE.DOWNLOAD' | translate }}</h2>\n <p>{{ 'IDEA_UNCOMMON.OFFLINE.DOWNLOAD_RESOURCES_EXPLANATION' | translate }}</p>\n </ion-label>\n </ion-list-header>\n @for (r of _offline.getResources(); track r) {\n <idea-cacheable-resource [resource]=\"_offline.getCacheableResource(r)\" />\n }\n </ion-list>\n }\n</ion-content>\n", styles: [".aList{max-width:500px;margin:0 auto}.aList ion-list-header{padding-right:10px}.aList ion-list-header h3.lastSyncAt{margin-top:6px}\n"] }]
|
|
3546
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-header>\n <ion-toolbar color=\"ideaToolbar\">\n <ion-buttons slot=\"start\">\n <ion-button (click)=\"close()\">\n <ion-icon name=\"close\" slot=\"icon-only\" />\n </ion-button>\n </ion-buttons>\n <ion-title>\n {{ 'IDEA_UNCOMMON.OFFLINE.OFFLINE_MANAGER' | translate }}\n </ion-title>\n <ion-buttons slot=\"end\">\n <ion-button [title]=\"'IDEA_UNCOMMON.OFFLINE.ADVANCED_ACTIONS' | translate\" (click)=\"actions()\">\n <ion-icon slot=\"icon-only\" name=\"ellipsis-vertical\" />\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n <ion-list class=\"aList\">\n @if (!_offline.synchronizing() && _offline.requiresManualConfirmation()) {\n <ion-list-header>\n <ion-label>\n <h2>{{ 'IDEA_UNCOMMON.OFFLINE.HUGE_SYNC_NEED_MANUAL_CONFIRMATION' | translate }}</h2>\n </ion-label>\n </ion-list-header>\n }\n @if (!_offline.synchronizing()) {\n <ion-list-header>\n <ion-label class=\"ion-text-wrap\">\n <h3 class=\"lastSyncAt\">\n {{ 'IDEA_UNCOMMON.OFFLINE.LAST_SYNC' | translate }}:\n <ion-text>\n {{\n _offline.lastSyncAt()\n ? (_offline.lastSyncAt() | dateLocale: 'medium')\n : ('IDEA_UNCOMMON.OFFLINE.NEVER' | translate)\n }}\n </ion-text>\n </h3>\n @if (_offline.errorInLastSync()) {\n <p>\n <ion-text color=\"danger\">\n <b>{{ 'IDEA_UNCOMMON.OFFLINE.ERROR_DURING_LAST_SYNC' | translate }}</b>\n </ion-text>\n </p>\n }\n </ion-label>\n <ion-button\n size=\"small\"\n fill=\"solid\"\n [color]=\"_offline.errorInLastSync() ? 'danger' : 'dark'\"\n [disabled]=\"_offline.isOffline()\"\n (click)=\"sync()\"\n >\n <ion-icon slot=\"start\" name=\"sync\" /> {{ 'IDEA_UNCOMMON.OFFLINE.SYNC_NOW' | translate }}\n </ion-button>\n </ion-list-header>\n }\n </ion-list>\n @if (_offline.synchronizing()) {\n <ion-list class=\"aList\">\n <ion-item>\n <ion-label class=\"ion-text-center\">\n <ion-spinner name=\"crescent\" color=\"primary\" />\n </ion-label>\n </ion-item>\n </ion-list>\n }\n @if (_offline.useQueueAPIRequests) {\n <ion-list class=\"aList\">\n <ion-list-header>\n <ion-label>\n <h2>{{ 'IDEA_UNCOMMON.OFFLINE.UPLOAD' | translate }}</h2>\n <p>{{ 'IDEA_UNCOMMON.OFFLINE.UPLOAD_QUEUE_REQUESTS_EXPLANATION' | translate }}</p>\n </ion-label>\n </ion-list-header>\n @if (!_offline.queueAPIRequests.length) {\n <ion-item>\n <i>{{ 'IDEA_UNCOMMON.OFFLINE.NO_ELEMENTS_TO_UPLOAD' | translate }}</i>\n <ion-icon slot=\"end\" size=\"small\" name=\"checkmark\" color=\"success\" />\n </ion-item>\n }\n @for (r of _offline.queueAPIRequests; track r; let odd = $odd) {\n <ion-item [class.oddItem]=\"odd\">\n <ion-label class=\"ion-text-wrap\">\n {{ r.description }}\n @if (r.error) {\n <p>\n <ion-text color=\"danger\">\n <b>{{ 'IDEA_UNCOMMON.OFFLINE.ERROR_CODE' | translate }}: {{ r.error }}</b>\n </ion-text>\n <br />\n {{ 'IDEA_UNCOMMON.OFFLINE.REQUEST_FAILED_EXPLANATION_I' | translate }}<br />\n {{ 'IDEA_UNCOMMON.OFFLINE.REQUEST_FAILED_EXPLANATION_II' | translate }}<br />\n {{ 'IDEA_UNCOMMON.OFFLINE.REQUEST_FAILED_EXPLANATION_III' | translate }}\n </p>\n }\n </ion-label>\n @if (r.error) {\n <ion-button\n fill=\"clear\"\n slot=\"end\"\n color=\"danger\"\n [title]=\"'IDEA_UNCOMMON.OFFLINE.CANCEL_REQUEST' | translate\"\n (click)=\"deleteRequest(r)\"\n >\n <ion-icon slot=\"icon-only\" name=\"trash\" />\n </ion-button>\n }\n @if (r.error) {\n <ion-button\n fill=\"clear\"\n slot=\"end\"\n color=\"medium\"\n [title]=\"'IDEA_UNCOMMON.OFFLINE.DOWNLOAD_LOG' | translate\"\n (click)=\"downloadRequestLog(r)\"\n >\n <ion-icon slot=\"icon-only\" name=\"download\" />\n </ion-button>\n }\n @if (_offline.synchronizing()) {\n <ion-spinner slot=\"end\" name=\"dots\" />\n }\n </ion-item>\n }\n </ion-list>\n }\n @if (_offline.getResources().length) {\n <ion-list class=\"aList\">\n <ion-list-header>\n <ion-label>\n <h2>{{ 'IDEA_UNCOMMON.OFFLINE.DOWNLOAD' | translate }}</h2>\n <p>{{ 'IDEA_UNCOMMON.OFFLINE.DOWNLOAD_RESOURCES_EXPLANATION' | translate }}</p>\n </ion-label>\n </ion-list-header>\n @for (r of _offline.getResources(); track r) {\n <idea-cacheable-resource [resource]=\"_offline.getCacheableResource(r)\" />\n }\n </ion-list>\n }\n</ion-content>\n", styles: [".aList{max-width:500px;margin:0 auto}.aList ion-list-header{padding-right:10px}.aList ion-list-header h3.lastSyncAt{margin-top:6px}\n"] }]
|
|
3498
3547
|
}] });
|
|
3499
3548
|
|
|
3500
3549
|
class IDEAOfflineIndicatorComponent {
|
|
@@ -3540,7 +3589,8 @@ class IDEAOfflineIndicatorComponent {
|
|
|
3540
3589
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: IDEAOfflineIndicatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3541
3590
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: IDEAOfflineIndicatorComponent, isStandalone: true, selector: "idea-offline-indicator", inputs: { vertical: { classPropertyName: "vertical", publicName: "vertical", isSignal: true, isRequired: false, transformFunction: null }, horizontal: { classPropertyName: "horizontal", publicName: "horizontal", isSignal: true, isRequired: false, transformFunction: null }, edge: { classPropertyName: "edge", publicName: "edge", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
3542
3591
|
@if (
|
|
3543
|
-
_platform.is('mobile') &&
|
|
3592
|
+
_platform.is('mobile') &&
|
|
3593
|
+
(_offline.isOffline() || _offline.synchronizing() || _offline.requiresManualConfirmation())
|
|
3544
3594
|
) {
|
|
3545
3595
|
<ion-fab [vertical]="vertical()" [horizontal]="horizontal()" [edge]="edge()">
|
|
3546
3596
|
<ion-fab-button color="dark" size="small" (click)="showStatus()">
|
|
@@ -3549,11 +3599,11 @@ class IDEAOfflineIndicatorComponent {
|
|
|
3549
3599
|
<ion-icon name="airplane" />
|
|
3550
3600
|
}
|
|
3551
3601
|
<!-- SYNCHRONISING -->
|
|
3552
|
-
@if (_offline.isOnline() && _offline.synchronizing) {
|
|
3602
|
+
@if (_offline.isOnline() && _offline.synchronizing()) {
|
|
3553
3603
|
<ion-icon name="sync" />
|
|
3554
3604
|
}
|
|
3555
3605
|
<!-- NEED MANAL SYNCHRONISATION -->
|
|
3556
|
-
@if (_offline.isOnline() && _offline.requiresManualConfirmation) {
|
|
3606
|
+
@if (_offline.isOnline() && _offline.requiresManualConfirmation()) {
|
|
3557
3607
|
<ion-icon name="pause" />
|
|
3558
3608
|
}
|
|
3559
3609
|
</ion-fab-button>
|
|
@@ -3569,7 +3619,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3569
3619
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3570
3620
|
template: `
|
|
3571
3621
|
@if (
|
|
3572
|
-
_platform.is('mobile') &&
|
|
3622
|
+
_platform.is('mobile') &&
|
|
3623
|
+
(_offline.isOffline() || _offline.synchronizing() || _offline.requiresManualConfirmation())
|
|
3573
3624
|
) {
|
|
3574
3625
|
<ion-fab [vertical]="vertical()" [horizontal]="horizontal()" [edge]="edge()">
|
|
3575
3626
|
<ion-fab-button color="dark" size="small" (click)="showStatus()">
|
|
@@ -3578,11 +3629,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3578
3629
|
<ion-icon name="airplane" />
|
|
3579
3630
|
}
|
|
3580
3631
|
<!-- SYNCHRONISING -->
|
|
3581
|
-
@if (_offline.isOnline() && _offline.synchronizing) {
|
|
3632
|
+
@if (_offline.isOnline() && _offline.synchronizing()) {
|
|
3582
3633
|
<ion-icon name="sync" />
|
|
3583
3634
|
}
|
|
3584
3635
|
<!-- NEED MANAL SYNCHRONISATION -->
|
|
3585
|
-
@if (_offline.isOnline() && _offline.requiresManualConfirmation) {
|
|
3636
|
+
@if (_offline.isOnline() && _offline.requiresManualConfirmation()) {
|
|
3586
3637
|
<ion-icon name="pause" />
|
|
3587
3638
|
}
|
|
3588
3639
|
</ion-fab-button>
|
|
@@ -3597,8 +3648,12 @@ class IDEASentimentComponent {
|
|
|
3597
3648
|
this._env = inject(IDEAEnvironment);
|
|
3598
3649
|
this._API = inject(IDEAAWSAPIService);
|
|
3599
3650
|
this._translate = inject(IDEATranslationsService);
|
|
3600
|
-
this._cd = inject(ChangeDetectorRef);
|
|
3601
3651
|
this._offline = inject(IDEAOfflineService);
|
|
3652
|
+
/**
|
|
3653
|
+
* The sentiment detected from the input text.
|
|
3654
|
+
*/
|
|
3655
|
+
this.sentiment = signal(null, /* @ts-ignore */
|
|
3656
|
+
...(ngDevMode ? [{ debugName: "sentiment" }] : /* istanbul ignore next */ []));
|
|
3602
3657
|
/**
|
|
3603
3658
|
* The input text.
|
|
3604
3659
|
*/
|
|
@@ -3625,24 +3680,23 @@ class IDEASentimentComponent {
|
|
|
3625
3680
|
}
|
|
3626
3681
|
async detectSentiment(text) {
|
|
3627
3682
|
if (!text || this._offline.isOffline())
|
|
3628
|
-
this.sentiment
|
|
3683
|
+
this.sentiment.set(null);
|
|
3629
3684
|
else {
|
|
3630
3685
|
try {
|
|
3631
3686
|
const { sentiment } = await this._API.postResource('sentiment', {
|
|
3632
3687
|
idea: true,
|
|
3633
3688
|
body: { project: this._env.idea.project, language: this._translate.getCurrentLang(), text: this.text() }
|
|
3634
3689
|
});
|
|
3635
|
-
this.sentiment
|
|
3636
|
-
this.change.emit(this.sentiment);
|
|
3690
|
+
this.sentiment.set(sentiment);
|
|
3691
|
+
this.change.emit(this.sentiment());
|
|
3637
3692
|
}
|
|
3638
3693
|
catch (error) {
|
|
3639
|
-
this.sentiment
|
|
3694
|
+
this.sentiment.set(null);
|
|
3640
3695
|
}
|
|
3641
3696
|
}
|
|
3642
|
-
this._cd.markForCheck(); // zoneless: re-check after the awaited detection settles
|
|
3643
3697
|
}
|
|
3644
3698
|
getColorBySentiment(sentiment) {
|
|
3645
|
-
sentiment = sentiment || this.sentiment;
|
|
3699
|
+
sentiment = sentiment || this.sentiment();
|
|
3646
3700
|
switch (sentiment) {
|
|
3647
3701
|
case Sentiment.POSITIVE:
|
|
3648
3702
|
return 'success';
|
|
@@ -3660,17 +3714,17 @@ class IDEASentimentComponent {
|
|
|
3660
3714
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: IDEASentimentComponent, isStandalone: true, selector: "idea-sentiment", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, lines: { classPropertyName: "lines", publicName: "lines", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { change: "change" }, usesOnChanges: true, ngImport: i0, template: `
|
|
3661
3715
|
@if (text() && _offline.isOnline()) {
|
|
3662
3716
|
<ion-item [lines]="lines()" [color]="color()">
|
|
3663
|
-
@if (!sentiment) {
|
|
3717
|
+
@if (!sentiment()) {
|
|
3664
3718
|
<ion-spinner slot="end" size="small" />
|
|
3665
3719
|
}
|
|
3666
|
-
@if (sentiment) {
|
|
3720
|
+
@if (sentiment()) {
|
|
3667
3721
|
<ion-badge
|
|
3668
3722
|
slot="end"
|
|
3669
3723
|
size="small"
|
|
3670
3724
|
[color]="getColorBySentiment()"
|
|
3671
|
-
[title]="'IDEA_UNCOMMON.SENTIMENT.RESULT_HINT' | translate: { sentiment: sentiment }"
|
|
3725
|
+
[title]="'IDEA_UNCOMMON.SENTIMENT.RESULT_HINT' | translate: { sentiment: sentiment() }"
|
|
3672
3726
|
>
|
|
3673
|
-
{{ 'IDEA_UNCOMMON.SENTIMENT.RESULT.' + sentiment | translate }}
|
|
3727
|
+
{{ 'IDEA_UNCOMMON.SENTIMENT.RESULT.' + sentiment() | translate }}
|
|
3674
3728
|
</ion-badge>
|
|
3675
3729
|
}
|
|
3676
3730
|
</ion-item>
|
|
@@ -3686,17 +3740,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3686
3740
|
template: `
|
|
3687
3741
|
@if (text() && _offline.isOnline()) {
|
|
3688
3742
|
<ion-item [lines]="lines()" [color]="color()">
|
|
3689
|
-
@if (!sentiment) {
|
|
3743
|
+
@if (!sentiment()) {
|
|
3690
3744
|
<ion-spinner slot="end" size="small" />
|
|
3691
3745
|
}
|
|
3692
|
-
@if (sentiment) {
|
|
3746
|
+
@if (sentiment()) {
|
|
3693
3747
|
<ion-badge
|
|
3694
3748
|
slot="end"
|
|
3695
3749
|
size="small"
|
|
3696
3750
|
[color]="getColorBySentiment()"
|
|
3697
|
-
[title]="'IDEA_UNCOMMON.SENTIMENT.RESULT_HINT' | translate: { sentiment: sentiment }"
|
|
3751
|
+
[title]="'IDEA_UNCOMMON.SENTIMENT.RESULT_HINT' | translate: { sentiment: sentiment() }"
|
|
3698
3752
|
>
|
|
3699
|
-
{{ 'IDEA_UNCOMMON.SENTIMENT.RESULT.' + sentiment | translate }}
|
|
3753
|
+
{{ 'IDEA_UNCOMMON.SENTIMENT.RESULT.' + sentiment() | translate }}
|
|
3700
3754
|
</ion-badge>
|
|
3701
3755
|
}
|
|
3702
3756
|
</ion-item>
|
|
@@ -3712,8 +3766,6 @@ class IDEAFromTimeToTimeComponent {
|
|
|
3712
3766
|
/**
|
|
3713
3767
|
* Whether we should start picking the time displaying the afternoon (PM) or the morning (AM, default).
|
|
3714
3768
|
*/
|
|
3715
|
-
// TODO: Skipped for migration because:
|
|
3716
|
-
// Your application code writes to the input. This prevents migration.
|
|
3717
3769
|
this.period = Periods.AM;
|
|
3718
3770
|
this.Segments = Segments;
|
|
3719
3771
|
this.Periods = Periods;
|
|
@@ -3875,7 +3927,6 @@ class IDEATimeIntervalComponent {
|
|
|
3875
3927
|
constructor() {
|
|
3876
3928
|
this._modal = inject(ModalController);
|
|
3877
3929
|
this._translate = inject(IDEATranslationsService);
|
|
3878
|
-
this._cdr = inject(ChangeDetectorRef);
|
|
3879
3930
|
/**
|
|
3880
3931
|
* The time interval to set.
|
|
3881
3932
|
*/
|
|
@@ -3953,13 +4004,15 @@ class IDEATimeIntervalComponent {
|
|
|
3953
4004
|
* On select (with the field disabled) event.
|
|
3954
4005
|
*/
|
|
3955
4006
|
this.selectWhenDisabled = output();
|
|
3956
|
-
this.
|
|
4007
|
+
this.valueToDisplay = signal('', /* @ts-ignore */
|
|
4008
|
+
...(ngDevMode ? [{ debugName: "valueToDisplay" }] : /* istanbul ignore next */ []));
|
|
4009
|
+
this.isOpening = signal(false, /* @ts-ignore */
|
|
4010
|
+
...(ngDevMode ? [{ debugName: "isOpening" }] : /* istanbul ignore next */ []));
|
|
3957
4011
|
}
|
|
3958
4012
|
ngOnInit() {
|
|
3959
4013
|
// when the language changes, set the locale
|
|
3960
4014
|
this.langChangeSubscription = this._translate.onLangChange.subscribe(() => {
|
|
3961
|
-
this.valueToDisplay
|
|
3962
|
-
this._cdr.markForCheck();
|
|
4015
|
+
this.valueToDisplay.set(this.getValueToDisplay(this.timeInterval()));
|
|
3963
4016
|
});
|
|
3964
4017
|
}
|
|
3965
4018
|
ngOnDestroy() {
|
|
@@ -3968,7 +4021,7 @@ class IDEATimeIntervalComponent {
|
|
|
3968
4021
|
}
|
|
3969
4022
|
ngOnChanges(changes) {
|
|
3970
4023
|
if (changes.timeInterval)
|
|
3971
|
-
this.valueToDisplay
|
|
4024
|
+
this.valueToDisplay.set(this.getValueToDisplay(changes.timeInterval.currentValue));
|
|
3972
4025
|
}
|
|
3973
4026
|
getValueToDisplay(timeInterval) {
|
|
3974
4027
|
if (!timeInterval || !timeInterval.isSet())
|
|
@@ -3978,9 +4031,9 @@ class IDEATimeIntervalComponent {
|
|
|
3978
4031
|
return ''.concat(this._translate._('IDEA_UNCOMMON.FTTT.FROM'), ' ', new Date(timeInterval.from).toLocaleTimeString(this._translate.getCurrentLang(), dateOpts), ' ', this._translate._('IDEA_UNCOMMON.FTTT.TO').toLowerCase(), ' ', new Date(timeInterval.to).toLocaleTimeString(this._translate.getCurrentLang(), dateOpts));
|
|
3979
4032
|
}
|
|
3980
4033
|
async pickTimeInterval() {
|
|
3981
|
-
if (this.isOpening)
|
|
4034
|
+
if (this.isOpening())
|
|
3982
4035
|
return;
|
|
3983
|
-
this.isOpening
|
|
4036
|
+
this.isOpening.set(true);
|
|
3984
4037
|
const modal = await this._modal.create({
|
|
3985
4038
|
component: IDEAFromTimeToTimeComponent,
|
|
3986
4039
|
componentProps: {
|
|
@@ -3994,13 +4047,12 @@ class IDEATimeIntervalComponent {
|
|
|
3994
4047
|
modal.onDidDismiss().then((res) => {
|
|
3995
4048
|
// if the content changed, update the internal values and notify the parent component
|
|
3996
4049
|
if (res.data === true || res.data === false) {
|
|
3997
|
-
this.valueToDisplay
|
|
4050
|
+
this.valueToDisplay.set(this.getValueToDisplay(this.timeInterval()));
|
|
3998
4051
|
this.select.emit();
|
|
3999
|
-
this._cdr.markForCheck();
|
|
4000
4052
|
}
|
|
4001
4053
|
});
|
|
4002
4054
|
modal.present();
|
|
4003
|
-
this.isOpening
|
|
4055
|
+
this.isOpening.set(false);
|
|
4004
4056
|
}
|
|
4005
4057
|
doSelectWhenDisabled() {
|
|
4006
4058
|
if (this.disabled())
|
|
@@ -4018,8 +4070,8 @@ class IDEATimeIntervalComponent {
|
|
|
4018
4070
|
[color]="color()"
|
|
4019
4071
|
[lines]="lines()"
|
|
4020
4072
|
[button]="!disabled()"
|
|
4021
|
-
[disabled]="isOpening"
|
|
4022
|
-
[title]="placeholder() || valueToDisplay || ''"
|
|
4073
|
+
[disabled]="isOpening()"
|
|
4074
|
+
[title]="placeholder() || valueToDisplay() || ''"
|
|
4023
4075
|
[class.withLabel]="label()"
|
|
4024
4076
|
(click)="disabled() ? doSelectWhenDisabled() : pickTimeInterval()"
|
|
4025
4077
|
>
|
|
@@ -4043,12 +4095,12 @@ class IDEATimeIntervalComponent {
|
|
|
4043
4095
|
</ion-label>
|
|
4044
4096
|
}
|
|
4045
4097
|
<ion-label class="description" [class.selectable]="!disabled() || tappableWhenDisabled()">
|
|
4046
|
-
@if (!valueToDisplay && !disabled()) {
|
|
4098
|
+
@if (!valueToDisplay() && !disabled()) {
|
|
4047
4099
|
<ion-text class="placeholder" [class.selectable]="!disabled()">
|
|
4048
4100
|
{{ placeholder() }}
|
|
4049
4101
|
</ion-text>
|
|
4050
4102
|
}
|
|
4051
|
-
{{ valueToDisplay }}
|
|
4103
|
+
{{ valueToDisplay() }}
|
|
4052
4104
|
</ion-label>
|
|
4053
4105
|
@if (!disabled()) {
|
|
4054
4106
|
<ion-icon slot="end" name="caret-down" class="selectIcon" [class.selectable]="!disabled()" />
|
|
@@ -4064,8 +4116,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
4064
4116
|
[color]="color()"
|
|
4065
4117
|
[lines]="lines()"
|
|
4066
4118
|
[button]="!disabled()"
|
|
4067
|
-
[disabled]="isOpening"
|
|
4068
|
-
[title]="placeholder() || valueToDisplay || ''"
|
|
4119
|
+
[disabled]="isOpening()"
|
|
4120
|
+
[title]="placeholder() || valueToDisplay() || ''"
|
|
4069
4121
|
[class.withLabel]="label()"
|
|
4070
4122
|
(click)="disabled() ? doSelectWhenDisabled() : pickTimeInterval()"
|
|
4071
4123
|
>
|
|
@@ -4089,12 +4141,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
4089
4141
|
</ion-label>
|
|
4090
4142
|
}
|
|
4091
4143
|
<ion-label class="description" [class.selectable]="!disabled() || tappableWhenDisabled()">
|
|
4092
|
-
@if (!valueToDisplay && !disabled()) {
|
|
4144
|
+
@if (!valueToDisplay() && !disabled()) {
|
|
4093
4145
|
<ion-text class="placeholder" [class.selectable]="!disabled()">
|
|
4094
4146
|
{{ placeholder() }}
|
|
4095
4147
|
</ion-text>
|
|
4096
4148
|
}
|
|
4097
|
-
{{ valueToDisplay }}
|
|
4149
|
+
{{ valueToDisplay() }}
|
|
4098
4150
|
</ion-label>
|
|
4099
4151
|
@if (!disabled()) {
|
|
4100
4152
|
<ion-icon slot="end" name="caret-down" class="selectIcon" [class.selectable]="!disabled()" />
|
|
@@ -4339,6 +4391,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
4339
4391
|
|
|
4340
4392
|
/**
|
|
4341
4393
|
* To subscribe push notifications events.
|
|
4394
|
+
*
|
|
4395
|
+
* These are `Observable` streams fed by native Capacitor listeners (outside the Angular zone). On a
|
|
4396
|
+
* zoneless consumer, render any state you derive from them reactively (signals or the `async` pipe);
|
|
4397
|
+
* a plain field assigned inside `.subscribe(...)` won't schedule change detection.
|
|
4342
4398
|
*/
|
|
4343
4399
|
class IDEAPushNotificationsService {
|
|
4344
4400
|
constructor() {
|