refactor: update to ionic v6

This commit is contained in:
Rainer Killinger
2022-03-21 11:23:07 +00:00
parent e68d1b73f9
commit edd2ccffe9
25 changed files with 401 additions and 285 deletions

152
package-lock.json generated
View File

@@ -601,6 +601,13 @@
"integrity": "sha512-HVi3RBaT3srGKXssWnnxpE+yKbcejHI4Ymt1JefeubJ883B6siVBWIxAg8fXk82QO0+sBQKpoIu7ISfYszK6mA==", "integrity": "sha512-HVi3RBaT3srGKXssWnnxpE+yKbcejHI4Ymt1JefeubJ883B6siVBWIxAg8fXk82QO0+sBQKpoIu7ISfYszK6mA==",
"requires": { "requires": {
"@types/cordova": "^0.0.34" "@types/cordova": "^0.0.34"
},
"dependencies": {
"@types/cordova": {
"version": "0.0.34",
"resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz",
"integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ="
}
} }
}, },
"@awesome-cordova-plugins/core": { "@awesome-cordova-plugins/core": {
@@ -609,6 +616,13 @@
"integrity": "sha512-tk5QlnXfSE2Zu3mJVC3f11Guu5iqnLtNkvvClNHjz/e4FsJEmprfXWCv/QImWs5fLsismHcn31LKYBfWIhOv9g==", "integrity": "sha512-tk5QlnXfSE2Zu3mJVC3f11Guu5iqnLtNkvvClNHjz/e4FsJEmprfXWCv/QImWs5fLsismHcn31LKYBfWIhOv9g==",
"requires": { "requires": {
"@types/cordova": "^0.0.34" "@types/cordova": "^0.0.34"
},
"dependencies": {
"@types/cordova": {
"version": "0.0.34",
"resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz",
"integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ="
}
} }
}, },
"@babel/code-frame": { "@babel/code-frame": {
@@ -2499,6 +2513,16 @@
"serve-index": "^1.9.1" "serve-index": "^1.9.1"
}, },
"dependencies": { "dependencies": {
"cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"dev": true,
"requires": {
"object-assign": "^4",
"vary": "^1"
}
},
"debug": { "debug": {
"version": "2.6.9", "version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -2545,6 +2569,12 @@
"is-wsl": "^2.2.0" "is-wsl": "^2.2.0"
} }
}, },
"proxy-middleware": {
"version": "0.15.0",
"resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.15.0.tgz",
"integrity": "sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY=",
"dev": true
},
"send": { "send": {
"version": "0.17.2", "version": "0.17.2",
"resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz",
@@ -2799,6 +2829,13 @@
"integrity": "sha512-lOrkktadlKYbYf1LrDyAtsu1JnQ0oCCdkOU7iHQ8oXnNOkMwobFfD2m62F1CoOr0u9LIkpYnZSPjng8lZbmbNw==", "integrity": "sha512-lOrkktadlKYbYf1LrDyAtsu1JnQ0oCCdkOU7iHQ8oXnNOkMwobFfD2m62F1CoOr0u9LIkpYnZSPjng8lZbmbNw==",
"requires": { "requires": {
"@types/cordova": "^0.0.34" "@types/cordova": "^0.0.34"
},
"dependencies": {
"@types/cordova": {
"version": "0.0.34",
"resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz",
"integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ="
}
} }
}, },
"@ionic-native/file-opener": { "@ionic-native/file-opener": {
@@ -2807,6 +2844,13 @@
"integrity": "sha512-UKp3pbqvQXsAtLMJ5JE+KcTMxpjSZMFebf6nvy/KJvwy85JGIaCV4ZVM/H9CFUrHJMWBH6wDbY+WPygnsrl4Yg==", "integrity": "sha512-UKp3pbqvQXsAtLMJ5JE+KcTMxpjSZMFebf6nvy/KJvwy85JGIaCV4ZVM/H9CFUrHJMWBH6wDbY+WPygnsrl4Yg==",
"requires": { "requires": {
"@types/cordova": "^0.0.34" "@types/cordova": "^0.0.34"
},
"dependencies": {
"@types/cordova": {
"version": "0.0.34",
"resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz",
"integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ="
}
} }
}, },
"@ionic-native/http": { "@ionic-native/http": {
@@ -2816,6 +2860,14 @@
"optional": true, "optional": true,
"requires": { "requires": {
"@types/cordova": "^0.0.34" "@types/cordova": "^0.0.34"
},
"dependencies": {
"@types/cordova": {
"version": "0.0.34",
"resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz",
"integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ=",
"optional": true
}
} }
}, },
"@ionic-native/in-app-browser": { "@ionic-native/in-app-browser": {
@@ -2825,6 +2877,14 @@
"optional": true, "optional": true,
"requires": { "requires": {
"@types/cordova": "^0.0.34" "@types/cordova": "^0.0.34"
},
"dependencies": {
"@types/cordova": {
"version": "0.0.34",
"resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz",
"integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ=",
"optional": true
}
} }
}, },
"@ionic-native/safari-view-controller": { "@ionic-native/safari-view-controller": {
@@ -2834,6 +2894,14 @@
"optional": true, "optional": true,
"requires": { "requires": {
"@types/cordova": "^0.0.34" "@types/cordova": "^0.0.34"
},
"dependencies": {
"@types/cordova": {
"version": "0.0.34",
"resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz",
"integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ=",
"optional": true
}
} }
}, },
"@ionic-native/secure-storage": { "@ionic-native/secure-storage": {
@@ -2843,22 +2911,24 @@
"optional": true, "optional": true,
"requires": { "requires": {
"@types/cordova": "^0.0.34" "@types/cordova": "^0.0.34"
},
"dependencies": {
"@types/cordova": {
"version": "0.0.34",
"resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz",
"integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ=",
"optional": true
}
} }
}, },
"@ionic/angular": { "@ionic/angular": {
"version": "5.9.3", "version": "6.0.8",
"resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-5.9.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-6.0.8.tgz",
"integrity": "sha512-0j4JZeGHpRvaTH0iyLTiUc4TF01bGVmk0zHZA7qS/OpS/WnGRHYNpVX/F75oODfckNvAa9uacoIMOTu54Cpx3w==", "integrity": "sha512-sPXQ17SCym0Skx1vbFmhHyPCNH5NoKIyuHee8ROZcTvNizavJYajoU+YTcr6v3w37CecsTz/JgpCXbAUHxxrcQ==",
"requires": { "requires": {
"@ionic/core": "5.9.3", "@ionic/core": "^6.0.8",
"tslib": "^1.9.3" "jsonc-parser": "^3.0.0",
}, "tslib": "^2.0.0"
"dependencies": {
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
}
} }
}, },
"@ionic/angular-toolkit": { "@ionic/angular-toolkit": {
@@ -3016,12 +3086,12 @@
} }
}, },
"@ionic/core": { "@ionic/core": {
"version": "5.9.3", "version": "6.0.11",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.9.3.tgz", "resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.0.11.tgz",
"integrity": "sha512-WM50vVxAAw+MQYqWXKUK4usBgkr7iQ9UWSb6t59mG4ZSy/fPAb7ZIdAjxY0U5i1ykk6A7Ur4B9ZJMpC/a7nnug==", "integrity": "sha512-2gtyEoWN+CnfIHOUXctEYc9KHQiUapWJoo1AqCTxcsuXLrMnaPa4orrFpdkBXlT0gugVLM222TW+Stlt5Kq8yg==",
"requires": { "requires": {
"@stencil/core": "^2.4.0", "@stencil/core": "^2.14.1",
"ionicons": "^5.5.3", "ionicons": "^6.0.0",
"tslib": "^2.1.0" "tslib": "^2.1.0"
} }
}, },
@@ -4060,11 +4130,6 @@
"integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==",
"dev": true "dev": true
}, },
"@types/cordova": {
"version": "0.0.34",
"resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz",
"integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ="
},
"@types/cors": { "@types/cors": {
"version": "2.8.12", "version": "2.8.12",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz",
@@ -5739,6 +5804,25 @@
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true "dev": true
}, },
"bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"dev": true,
"optional": true,
"requires": {
"file-uri-to-path": "1.0.0"
},
"dependencies": {
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"dev": true,
"optional": true
}
}
},
"bl": { "bl": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
@@ -10746,17 +10830,17 @@
} }
}, },
"ionicons": { "ionicons": {
"version": "5.5.4", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.4.tgz", "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-6.0.1.tgz",
"integrity": "sha512-3ph8X9my3inhabWEZ7N0XRA0MnnNQ1v9a602mLNgWsIXnxE9G5BybIZ/pws/OZZ/hoNlvSjk801N03yL9/FNgQ==", "integrity": "sha512-xQekOJsxH82O7oB+3F60zeRggCdND9pJ/k0E6IJDVUGGlCj5mlyFqNgxUimytKgstPGv3S+3EmCxjefvtGgWUg==",
"requires": { "requires": {
"@stencil/core": "~2.10.0" "@stencil/core": "~2.12.0"
}, },
"dependencies": { "dependencies": {
"@stencil/core": { "@stencil/core": {
"version": "2.10.0", "version": "2.12.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.10.0.tgz", "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.12.1.tgz",
"integrity": "sha512-15rWMTPQ/sp0lSV82HVCXkIya3QLN+uBl7pqK4JnTrp4HiLrzLmNbWjbvgCs55gw0lULbCIGbRIEsFz+Pe/Q+A==" "integrity": "sha512-u24TZ+FEvjnZt5ZgIkLjLpUNsO6Ml3mUZqwmqk81w6RWWz75hgB5p4RFI5rvuErFeh2xvMIGo+pNdG24XUBz1A=="
} }
} }
}, },
@@ -11437,8 +11521,7 @@
"jsonc-parser": { "jsonc-parser": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz",
"integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA=="
"dev": true
}, },
"jsonfile": { "jsonfile": {
"version": "6.1.0", "version": "6.1.0",
@@ -16184,12 +16267,6 @@
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"dev": true "dev": true
}, },
"proxy-middleware": {
"version": "0.15.0",
"resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.15.0.tgz",
"integrity": "sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY=",
"dev": true
},
"prr": { "prr": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
@@ -19974,6 +20051,7 @@
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
"bindings": "^1.5.0",
"nan": "^2.12.1" "nan": "^2.12.1"
} }
}, },

View File

@@ -75,7 +75,7 @@
"@capacitor/storage": "1.2.5", "@capacitor/storage": "1.2.5",
"@ionic-native/core": "5.36.0", "@ionic-native/core": "5.36.0",
"@ionic-native/file-opener": "5.36.0", "@ionic-native/file-opener": "5.36.0",
"@ionic/angular": "5.9.3", "@ionic/angular": "6.0.8",
"@ionic/storage-angular": "3.0.6", "@ionic/storage-angular": "3.0.6",
"@ngx-translate/core": "13.0.0", "@ngx-translate/core": "13.0.0",
"@ngx-translate/http-loader": "6.0.0", "@ngx-translate/http-loader": "6.0.0",

View File

@@ -21,7 +21,7 @@ import {
TemplateRef, TemplateRef,
} from '@angular/core'; } from '@angular/core';
import {ActivatedRoute} from '@angular/router'; import {ActivatedRoute} from '@angular/router';
import {IonRefresher, ViewWillEnter} from '@ionic/angular'; import {IonRefresher, ViewWillEnter, ModalController} from '@ionic/angular';
import {LangChangeEvent, TranslateService} from '@ngx-translate/core'; import {LangChangeEvent, TranslateService} from '@ngx-translate/core';
import { import {
SCLanguageCode, SCLanguageCode,
@@ -57,6 +57,10 @@ export class DataDetailComponent implements ViewWillEnter {
*/ */
item?: SCThings | null = undefined; item?: SCThings | null = undefined;
@Input() inputItem?: SCThings;
@Input() isModal = false;
/** /**
* The language of the item * The language of the item
*/ */
@@ -100,12 +104,14 @@ export class DataDetailComponent implements ViewWillEnter {
* @param route the route the page was accessed from * @param route the route the page was accessed from
* @param dataProvider the data provider * @param dataProvider the data provider
* @param favoritesService the favorites provider * @param favoritesService the favorites provider
* @param modalController the modal controller
* @param translateService he translate provider * @param translateService he translate provider
*/ */
constructor( constructor(
protected readonly route: ActivatedRoute, protected readonly route: ActivatedRoute,
private readonly dataProvider: DataProvider, private readonly dataProvider: DataProvider,
private readonly favoritesService: FavoritesService, private readonly favoritesService: FavoritesService,
readonly modalController: ModalController,
translateService: TranslateService, translateService: TranslateService,
) { ) {
this.language = translateService.currentLang as SCLanguageCode; this.language = translateService.currentLang as SCLanguageCode;
@@ -127,11 +133,13 @@ export class DataDetailComponent implements ViewWillEnter {
*/ */
async getItem(uid: SCUuid, forceReload: boolean) { async getItem(uid: SCUuid, forceReload: boolean) {
try { try {
const item = await (this.externalData const item =
? new Promise<SCThings | null | undefined>(resolve => this.inputItem ??
this.loadItem.emit({uid, forceReload, resolve}), (await (this.externalData
) ? new Promise<SCThings | null | undefined>(resolve =>
: this.dataProvider.get(uid, DataScope.Remote)); this.loadItem.emit({uid, forceReload, resolve}),
)
: this.dataProvider.get(uid, DataScope.Remote)));
this.item = !item this.item = !item
? // eslint-disable-next-line unicorn/no-null ? // eslint-disable-next-line unicorn/no-null
@@ -170,7 +178,9 @@ export class DataDetailComponent implements ViewWillEnter {
* @param refresher Refresher component that triggers the update * @param refresher Refresher component that triggers the update
*/ */
async refresh(refresher: IonRefresher) { async refresh(refresher: IonRefresher) {
await this.getItem(this.route.snapshot.paramMap.get('uid') ?? '', true); if (!this.inputItem) {
await this.getItem(this.route.snapshot.paramMap.get('uid') ?? '', true);
}
await refresher.complete(); await refresher.complete();
} }
} }

View File

@@ -1,16 +1,21 @@
<ion-header *ngIf="defaultHeader"> <ion-header *ngIf="defaultHeader">
<ion-toolbar color="primary"> <ion-toolbar color="primary">
<ion-buttons slot="start"> <ion-buttons slot="start" *ngIf="!isModal">
<ion-back-button></ion-back-button> <ion-back-button></ion-back-button>
<ion-menu-button></ion-menu-button> <ion-menu-button></ion-menu-button>
</ion-buttons> </ion-buttons>
<ion-title>{{ 'data.detail.TITLE' | translate }}</ion-title> <ion-title>{{ 'data.detail.TITLE' | translate }}</ion-title>
<ion-buttons slot="primary"> <ion-buttons [slot]="isModal ? 'start' : 'primary'">
<stapps-favorite-button <stapps-favorite-button
*ngIf="item" *ngIf="item"
[item]="$any(item)" [item]="$any(item)"
></stapps-favorite-button> ></stapps-favorite-button>
</ion-buttons> </ion-buttons>
<ion-buttons slot="end" *ngIf="isModal">
<ion-button fill="clear" (click)="modalController.dismiss()">
<ion-label>{{ 'modal.DISMISS' | translate }}</ion-label>
</ion-button>
</ion-buttons>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
<ng-content select="[header]"></ng-content> <ng-content select="[header]"></ng-content>

View File

@@ -50,6 +50,11 @@ export class SearchPageComponent implements OnInit, OnDestroy {
*/ */
@Input() showDefaultData = false; @Input() showDefaultData = false;
/**
* Show the navigation drawer
*/
@Input() showDrawer = true;
/** /**
* Api query filter * Api query filter
*/ */

View File

@@ -3,7 +3,7 @@
<ion-toolbar color="primary"> <ion-toolbar color="primary">
<ion-buttons slot="start"> <ion-buttons slot="start">
<ion-back-button></ion-back-button> <ion-back-button></ion-back-button>
<ion-menu-button></ion-menu-button> <ion-menu-button *ngIf="showDrawer"></ion-menu-button>
</ion-buttons> </ion-buttons>
<ion-buttons slot="end"> <ion-buttons slot="end">
<ion-menu-button menu="context" auto-hide="false"> <ion-menu-button menu="context" auto-hide="false">

View File

@@ -1,7 +1,22 @@
<ng-container *ngIf="items | async as items; else loading"> <!--
~ Copyright (C) 2022 StApps
~ This program is free software: you can redistribute it and/or modify it
~ under the terms of the GNU General Public License as published by the Free
~ Software Foundation, version 3.
~
~ This program is distributed in the hope that it will be useful, but WITHOUT
~ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
~ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licens for
~ more details.
~
~ You should have received a copy of the GNU General Public License along with
~ this program. If not, see <https://www.gnu.org/licenses/>.
-->
<ng-container *ngIf="items as items; else loading">
<ion-list> <ion-list>
<ng-container *ngIf="!listHeader; else header"></ng-container> <ng-container *ngIf="!listHeader; else header"></ng-container>
<ng-container *ngFor="let item of items"> <ng-container *ngFor="let item of items | async">
<ng-container <ng-container
*ngTemplateOutlet=" *ngTemplateOutlet="
listItemTemplateRef || defaultListItem; listItemTemplateRef || defaultListItem;

View File

@@ -21,6 +21,7 @@ import {DataProvider} from '../../data/data.provider';
import {DataDetailComponent} from '../../data/detail/data-detail.component'; import {DataDetailComponent} from '../../data/detail/data-detail.component';
import {DaiaDataProvider} from '../daia-data.provider'; import {DaiaDataProvider} from '../daia-data.provider';
import {SCDaiaHoldings} from '../protocol/response'; import {SCDaiaHoldings} from '../protocol/response';
import {ModalController} from '@ionic/angular';
/** /**
* A Component to display an SCThing detailed * A Component to display an SCThing detailed
@@ -41,6 +42,7 @@ export class DaiaAvailabilityComponent
* @param route the route the page was accessed from * @param route the route the page was accessed from
* @param dataProvider the data provider * @param dataProvider the data provider
* @param favoritesService the favorites provider * @param favoritesService the favorites provider
* @param modalController the modal controller
* @param translateService he translate provider * @param translateService he translate provider
* @param daiaDataProvider DaiaDataProvider * @param daiaDataProvider DaiaDataProvider
*/ */
@@ -48,10 +50,17 @@ export class DaiaAvailabilityComponent
route: ActivatedRoute, route: ActivatedRoute,
dataProvider: DataProvider, dataProvider: DataProvider,
favoritesService: FavoritesService, favoritesService: FavoritesService,
modalController: ModalController,
translateService: TranslateService, translateService: TranslateService,
private daiaDataProvider: DaiaDataProvider, private daiaDataProvider: DaiaDataProvider,
) { ) {
super(route, dataProvider, favoritesService, translateService); super(
route,
dataProvider,
favoritesService,
modalController,
translateService,
);
} }
/** /**

View File

@@ -21,6 +21,7 @@ import {FavoritesService} from '../../favorites/favorites.service';
import {DataProvider} from '../../data/data.provider'; import {DataProvider} from '../../data/data.provider';
import {DataDetailComponent} from '../../data/detail/data-detail.component'; import {DataDetailComponent} from '../../data/detail/data-detail.component';
import {SCDaiaHoldings} from '../protocol/response'; import {SCDaiaHoldings} from '../protocol/response';
import {ModalController} from '@ionic/angular';
/** /**
* A Component to display an SCThing detailed * A Component to display an SCThing detailed
@@ -38,6 +39,7 @@ export class HebisDetailComponent extends DataDetailComponent {
* @param route the route the page was accessed from * @param route the route the page was accessed from
* @param dataProvider the data provider * @param dataProvider the data provider
* @param favoritesService the favorites provider * @param favoritesService the favorites provider
* @param modalController the modal controller
* @param translateService he translate provider * @param translateService he translate provider
* @param hebisDataProvider HebisDataProvider * @param hebisDataProvider HebisDataProvider
*/ */
@@ -45,10 +47,17 @@ export class HebisDetailComponent extends DataDetailComponent {
route: ActivatedRoute, route: ActivatedRoute,
dataProvider: DataProvider, dataProvider: DataProvider,
favoritesService: FavoritesService, favoritesService: FavoritesService,
modalController: ModalController,
translateService: TranslateService, translateService: TranslateService,
private hebisDataProvider: HebisDataProvider, private hebisDataProvider: HebisDataProvider,
) { ) {
super(route, dataProvider, favoritesService, translateService); super(
route,
dataProvider,
favoritesService,
modalController,
translateService,
);
} }
/** /**

View File

@@ -1,9 +1,19 @@
<ion-card class="compact"> <ion-card class="compact">
<ion-card-header> <ion-card-header>
<stapps-data-list-item <stapps-data-list-item
[item]="item" [item]="$any(item)"
(click)="showMore()" id="show-more"
></stapps-data-list-item> ></stapps-data-list-item>
<ion-modal
trigger="show-more"
[presentingElement]="routerOutlet.nativeEl"
swipeToClose="true"
>
<ng-template>
<app-map-single-modal [item]="item" style="height: 100%">
</app-map-single-modal>
</ng-template>
</ion-modal>
<stapps-skeleton-list-item *ngIf="!item"></stapps-skeleton-list-item> <stapps-skeleton-list-item *ngIf="!item"></stapps-skeleton-list-item>
</ion-card-header> </ion-card-header>
<ion-card-content> <ion-card-content>
@@ -12,15 +22,27 @@
<ion-col size="7"> <ion-col size="7">
<ion-note> <ion-note>
<span *ngIf="item.address as address"> <span *ngIf="item.address as address">
<span *ngIf="item.inPlace">{{ item.inPlace.name }},</span> <span *ngIf="$any(item).inPlace"
>{{ $any(item).inPlace.name }},</span
>
{{ address.streetAddress }}, {{ address.addressLocality }} {{ address.streetAddress }}, {{ address.addressLocality }}
</span> </span>
</ion-note> </ion-note>
</ion-col> </ion-col>
<ion-col size="5"> <ion-col size="5">
<ion-button size="small" (click)="showMore()" <ion-button size="small" id="show-more-button"
>More&nbsp;<ion-icon name="information-circle"></ion-icon >More&nbsp;<ion-icon name="information-circle"></ion-icon
></ion-button> ></ion-button>
<ion-modal
trigger="show-more-button"
swipeToClose="true"
[presentingElement]="routerOutlet.nativeEl"
>
<ng-template>
<app-map-single-modal [item]="item" style="height: 100%">
</app-map-single-modal>
</ng-template>
</ion-modal>
</ion-col> </ion-col>
</ion-row> </ion-row>
</ion-grid> </ion-grid>

View File

@@ -12,8 +12,9 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, EventEmitter, Input, Output} from '@angular/core'; import {Component, Input} from '@angular/core';
import {SCPlace} from '@openstapps/core'; import {SCPlace} from '@openstapps/core';
import {IonRouterOutlet} from '@ionic/angular';
@Component({ @Component({
selector: 'stapps-map-item', selector: 'stapps-map-item',
@@ -26,15 +27,5 @@ export class MapItemComponent {
*/ */
@Input() item: SCPlace; @Input() item: SCPlace;
/** constructor(readonly routerOutlet: IonRouterOutlet) {}
* An item to show
*/
@Output() showDetails = new EventEmitter<SCPlace>();
/**
* Emit event to signalize to show more information
*/
showMore() {
this.showDetails.emit(this.item);
}
} }

View File

@@ -20,7 +20,11 @@ import {
ViewChild, ViewChild,
} from '@angular/core'; } from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {AlertController, ModalController} from '@ionic/angular'; import {
AlertController,
IonRouterOutlet,
ModalController,
} from '@ionic/angular';
import {TranslateService} from '@ngx-translate/core'; import {TranslateService} from '@ngx-translate/core';
import { import {
SCBuilding, SCBuilding,
@@ -44,8 +48,6 @@ import {DataRoutingService} from '../../data/data-routing.service';
import {ContextMenuService} from '../../menu/context/context-menu.service'; import {ContextMenuService} from '../../menu/context/context-menu.service';
import {MapProvider} from '../map.provider'; import {MapProvider} from '../map.provider';
import {MapPosition, PositionService} from '../position.service'; import {MapPosition, PositionService} from '../position.service';
import {MapListModalComponent} from './modals/map-list-modal.component';
import {MapSingleModalComponent} from './modals/map-single-modal.component';
import {Geolocation, PermissionStatus} from '@capacitor/geolocation'; import {Geolocation, PermissionStatus} from '@capacitor/geolocation';
import {Capacitor} from '@capacitor/core'; import {Capacitor} from '@capacitor/core';
@@ -116,11 +118,6 @@ export class MapPageComponent {
*/ */
MAX_ZOOM = 18; MAX_ZOOM = 18;
/**
* Modal for additional information on places or for a list of places
*/
modal: HTMLIonModalElement;
/** /**
* Options of the leaflet map * Options of the leaflet map
*/ */
@@ -158,6 +155,7 @@ export class MapPageComponent {
private modalController: ModalController, private modalController: ModalController,
private dataRoutingService: DataRoutingService, private dataRoutingService: DataRoutingService,
private positionService: PositionService, private positionService: PositionService,
readonly routerOutlet: IonRouterOutlet,
) { ) {
// initialize the options // initialize the options
this.options = { this.options = {
@@ -277,8 +275,10 @@ export class MapPageComponent {
this.dataRoutingService.itemSelectListener().subscribe(async item => { this.dataRoutingService.itemSelectListener().subscribe(async item => {
// in case the list item is clicked // in case the list item is clicked
if (this.items.length > 1) { if (this.items.length > 1) {
await this.modal.dismiss(); await Promise.all([
await this.showItem(item.uid); this.modalController.dismiss(),
this.showItem(item.uid),
]);
} }
}), }),
this.positionService.watchCurrentLocation({maximumAge: 3000}).subscribe({ this.positionService.watchCurrentLocation({maximumAge: 3000}).subscribe({
@@ -439,45 +439,4 @@ export class MapPageComponent {
// center the selected place // center the selected place
this.focus(geoJSON(this.items[0].geo.point).getBounds().getCenter()); this.focus(geoJSON(this.items[0].geo.point).getBounds().getCenter());
} }
/**
* Show a single place
*/
async showItemModal(item: SCPlace) {
const placeWithNullLocation = {
...item,
geo: {point: {coordinates: [0, 0]}},
};
this.modal = await this.modalController.create({
component: MapSingleModalComponent,
swipeToClose: true,
componentProps: {
item: placeWithNullLocation,
dismissAction: () => {
this.modal.dismiss();
},
},
});
await this.modal.present();
}
/**
* Show the list of shown places
*/
async showListModal() {
this.modal = await this.modalController.create({
component: MapListModalComponent,
swipeToClose: true,
componentProps: {
filterQuery: this.filterQuery,
queryText: this.queryText,
dismissAction: () => {
this.modal.dismiss();
},
},
});
await this.modal.present();
}
} }

View File

@@ -1,3 +1,18 @@
<!--
~ Copyright (C) 2022 StApps
~ This program is free software: you can redistribute it and/or modify it
~ under the terms of the GNU General Public License as published by the Free
~ Software Foundation, version 3.
~
~ This program is distributed in the hope that it will be useful, but WITHOUT
~ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
~ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licens for
~ more details.
~
~ You should have received a copy of the GNU General Public License along with
~ this program. If not, see <https://www.gnu.org/licenses/>.
-->
<stapps-context contentId="map"></stapps-context> <stapps-context contentId="map"></stapps-context>
<ion-header class="ion-no-border" translucent="true"> <ion-header class="ion-no-border" translucent="true">
@@ -46,7 +61,7 @@
color="light" color="light"
shape="round" shape="round"
size="small" size="small"
(click)="showListModal()" (click)="mapListModal.present()"
> >
<ion-icon name="list"></ion-icon>&nbsp;&nbsp;{{ <ion-icon name="list"></ion-icon>&nbsp;&nbsp;{{
'map.page.buttons.SHOW_LIST' | translate 'map.page.buttons.SHOW_LIST' | translate
@@ -71,7 +86,6 @@
<stapps-map-item <stapps-map-item
*ngIf="items.length === 1" *ngIf="items.length === 1"
[item]="items[0]" [item]="items[0]"
(showDetails)="showItemModal($event)"
></stapps-map-item> ></stapps-map-item>
</div> </div>
<div class="map-buttons floating-buttons"> <div class="map-buttons floating-buttons">
@@ -80,7 +94,7 @@
color="light" color="light"
shape="round" shape="round"
size="small" size="small"
(click)="showListModal()" (click)="mapListModal.present()"
> >
<ion-icon name="list"></ion-icon>&nbsp;&nbsp;{{ <ion-icon name="list"></ion-icon>&nbsp;&nbsp;{{
'map.page.buttons.SHOW_LIST' | translate 'map.page.buttons.SHOW_LIST' | translate
@@ -102,4 +116,18 @@
</ng-template> </ng-template>
</ion-button> </ion-button>
</div> </div>
<ion-modal
[swipeToClose]="true"
[presentingElement]="routerOutlet.nativeEl"
#mapListModal
>
<ng-template>
<map-list-modal
style="height: 100%"
[filterQuery]="filterQuery"
[queryText]="queryText"
></map-list-modal>
</ng-template>
</ion-modal>
</ion-content> </ion-content>

View File

@@ -15,6 +15,7 @@
import {Component, Input, OnInit} from '@angular/core'; import {Component, Input, OnInit} from '@angular/core';
import {SCPlace, SCSearchFilter} from '@openstapps/core'; import {SCPlace, SCSearchFilter} from '@openstapps/core';
import {MapProvider} from '../../map.provider'; import {MapProvider} from '../../map.provider';
import {ModalController} from '@ionic/angular';
/** /**
* Modal showing a provided list of places * Modal showing a provided list of places
@@ -25,11 +26,6 @@ import {MapProvider} from '../../map.provider';
styleUrls: ['map-list.scss'], styleUrls: ['map-list.scss'],
}) })
export class MapListModalComponent implements OnInit { export class MapListModalComponent implements OnInit {
/**
* Action when close is pressed
*/
@Input() dismissAction: () => void;
/** /**
* Used for creating the search for the shown list * Used for creating the search for the shown list
*/ */
@@ -45,7 +41,10 @@ export class MapListModalComponent implements OnInit {
*/ */
@Input() queryText?: string; @Input() queryText?: string;
constructor(private mapProvider: MapProvider) {} constructor(
private mapProvider: MapProvider,
readonly modalController: ModalController,
) {}
/** /**
* Populate the list with the results from the search * Populate the list with the results from the search

View File

@@ -1,13 +1,33 @@
<ion-header translucent> <!--
<ion-toolbar color="primary"> ~ Copyright (C) 2022 StApps
<ion-title>{{ 'map.modals.list.TITLE' | translate }}</ion-title> ~ This program is free software: you can redistribute it and/or modify it
<ion-buttons slot="end"> ~ under the terms of the GNU General Public License as published by the Free
<ion-button (click)="dismissAction()">{{ ~ Software Foundation, version 3.
'app.ui.CLOSE' | translate ~
}}</ion-button> ~ This program is distributed in the hope that it will be useful, but WITHOUT
</ion-buttons> ~ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
</ion-toolbar> ~ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licens for
</ion-header> ~ more details.
<ion-content> ~
<stapps-data-list [items]="items"></stapps-data-list> ~ You should have received a copy of the GNU General Public License along with
</ion-content> ~ this program. If not, see <https://www.gnu.org/licenses/>.
-->
<div class="container">
<ion-header translucent>
<ion-toolbar color="primary">
<ion-title>{{ 'map.modals.list.TITLE' | translate }}</ion-title>
<ion-buttons slot="end">
<ion-button (click)="modalController.dismiss()">{{
'app.ui.CLOSE' | translate
}}</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content fullscreen>
<stapps-data-list
[loading]="!items"
[items]="$any(items)"
></stapps-data-list>
</ion-content>
</div>

View File

@@ -0,0 +1,20 @@
/*!
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licens for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
.container {
display: flex;
flex-direction: column;
height: 100%;
}

View File

@@ -14,6 +14,7 @@
*/ */
import {Component, Input} from '@angular/core'; import {Component, Input} from '@angular/core';
import {SCPlace} from '@openstapps/core'; import {SCPlace} from '@openstapps/core';
import {ModalController} from '@ionic/angular';
@Component({ @Component({
selector: 'app-map-single-modal', selector: 'app-map-single-modal',
@@ -21,13 +22,10 @@ import {SCPlace} from '@openstapps/core';
styleUrls: ['./map-single.scss'], styleUrls: ['./map-single.scss'],
}) })
export class MapSingleModalComponent { export class MapSingleModalComponent {
/**
* Action when close is pressed
*/
@Input() dismissAction: () => void;
/** /**
* The item to be shown * The item to be shown
*/ */
@Input() item: SCPlace; @Input() item: SCPlace;
constructor(readonly modalController: ModalController) {}
} }

View File

@@ -2,12 +2,12 @@
<ion-toolbar color="primary"> <ion-toolbar color="primary">
<ion-title>{{ 'map.modals.single.TITLE' | translate }}</ion-title> <ion-title>{{ 'map.modals.single.TITLE' | translate }}</ion-title>
<ion-buttons slot="end"> <ion-buttons slot="end">
<ion-button (click)="dismissAction()">{{ <ion-button (click)="modalController.dismiss()">{{
'app.ui.CLOSE' | translate 'app.ui.CLOSE' | translate
}}</ion-button> }}</ion-button>
</ion-buttons> </ion-buttons>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
<ion-content> <ion-content>
<stapps-data-detail-content [item]="item"></stapps-data-detail-content> <stapps-data-detail-content [item]="$any(item)"></stapps-data-detail-content>
</ion-content> </ion-content>

View File

@@ -40,7 +40,11 @@
*ngIf="index | dateFromIndex: baselineDate as date" *ngIf="index | dateFromIndex: baselineDate as date"
class="day-labels" class="day-labels"
> >
<ion-button expand="block" fill="clear" (click)="datetime.open()"> <ion-button
expand="block"
fill="clear"
[id]="'date-select-button' + index"
>
<ion-label> <ion-label>
{{ {{
date date
@@ -49,19 +53,23 @@
</ion-label> </ion-label>
</ion-button> </ion-button>
<!-- This poor datetime element is a phantom element to provide us with a date picker --> <ion-popover [trigger]="'date-select-button' + index">
<ion-datetime <ng-template>
class="phantom" <ion-datetime
#datetime #popoverDateTime
[displayFormat]="localDateFormat" presentation="date"
[value]="date.toISOString()" [value]="date | amDateFormat: 'YYYY-MM-DD'"
(ionChange)=" (ionChange)="
mainSwiper.goToIndex( mainSwiper.goToIndex(
moment($event.detail.value).diff(baselineDate, 'days') moment(popoverDateTime.value).diff(baselineDate, 'days') -
) (index - headerSwiper.virtualIndex)
" );
> popoverDateTime.confirm(true)
</ion-datetime> "
>
</ion-datetime>
</ng-template>
</ion-popover>
</div> </div>
</ng-template> </ng-template>
</infinite-swiper> </infinite-swiper>

View File

@@ -12,8 +12,12 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {Component, OnDestroy, OnInit} from '@angular/core';
import {SCSearchFilter, SCThingType} from '@openstapps/core'; import {SCSearchFilter, SCThingType} from '@openstapps/core';
import {ModalController} from '@ionic/angular';
import {DataRoutingService} from '../../../data/data-routing.service';
import {DataDetailComponent} from '../../../data/detail/data-detail.component';
import {Subscription} from 'rxjs';
/** /**
* TODO * TODO
@@ -23,11 +27,34 @@ import {SCSearchFilter, SCThingType} from '@openstapps/core';
templateUrl: 'modal-event-creator.html', templateUrl: 'modal-event-creator.html',
styleUrls: ['modal-event-creator.scss'], styleUrls: ['modal-event-creator.scss'],
}) })
export class ModalEventCreatorComponent { export class ModalEventCreatorComponent implements OnInit, OnDestroy {
/** subscriptions: Subscription[] = [];
* Action when close is pressed
*/ constructor(
@Input() dismissAction: () => void; readonly modalController: ModalController,
readonly dataRoutingService: DataRoutingService,
) {}
ngOnInit() {
this.subscriptions.push(
this.dataRoutingService.itemSelectListener().subscribe(async item => {
const modal = await this.modalController.create({
component: DataDetailComponent,
componentProps: {
isModal: true,
inputItem: item,
},
swipeToClose: true,
presentingElement: await this.modalController.getTop(),
});
return modal.present();
}),
);
}
ngOnDestroy() {
for (const subscription of this.subscriptions) subscription.unsubscribe();
}
/** /**
* Forced filter * Forced filter

View File

@@ -18,7 +18,7 @@
'schedule.addEventModal.addEvent' | translate | titlecase 'schedule.addEventModal.addEvent' | translate | titlecase
}}</ion-title> }}</ion-title>
<ion-buttons slot="end"> <ion-buttons slot="end">
<ion-button fill="clear" (click)="dismissAction()"> <ion-button fill="clear" (click)="modalController.dismiss()">
<ion-label>{{ 'modal.DISMISS' | translate }}</ion-label> <ion-label>{{ 'modal.DISMISS' | translate }}</ion-label>
</ion-button> </ion-button>
</ion-buttons> </ion-buttons>
@@ -26,6 +26,7 @@
<ion-card-content> <ion-card-content>
<stapps-search-page <stapps-search-page
[showDrawer]="false"
[forcedFilter]="filter" [forcedFilter]="filter"
[itemRouting]="false" [itemRouting]="false"
></stapps-search-page> ></stapps-search-page>

View File

@@ -1,15 +1,13 @@
ion-button { ion-button {
ion-label { ion-label {
color: var(--ion-color-primary); color: var(--ion-color-light);
} }
} }
ion-card-content { ion-card-content {
height: 100%; height: 100%;
padding-left: 0; padding: 0;
padding-right: 0;
stapps-data-list { stapps-data-list {
height: available; height: 100%;
} }
} }

View File

@@ -21,12 +21,10 @@ import {
} from '@angular/core'; } from '@angular/core';
import {Location} from '@angular/common'; import {Location} from '@angular/common';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {AnimationController, ModalController} from '@ionic/angular'; import {IonRouterOutlet} from '@ionic/angular';
import {SharedAxisChoreographer} from '../../../animation/animation-choreographer'; import {SharedAxisChoreographer} from '../../../animation/animation-choreographer';
import {materialSharedAxisX} from '../../../animation/material-motion'; import {materialSharedAxisX} from '../../../animation/material-motion';
import {ModalEventCreatorComponent} from './modal/modal-event-creator.component';
import {ScheduleResponsiveBreakpoint} from './schema/schema'; import {ScheduleResponsiveBreakpoint} from './schema/schema';
import {animate, style, transition, trigger} from '@angular/animations';
/** /**
* This needs to be sorted by break point low -> high * This needs to be sorted by break point low -> high
@@ -51,23 +49,6 @@ const responsiveConfig: ScheduleResponsiveBreakpoint[] = [
}, },
]; ];
const fabAnimations = trigger('fabAnimation', [
transition(':leave', [
style({opacity: 1, transform: 'translate(0vw, 0vh) scale(100%)'}),
animate(
'100ms ease-in',
style({opacity: 0, transform: 'translate(-5vw, -5vh) scale(200%)'}),
),
]),
transition(':enter', [
style({opacity: 0, transform: 'translate(-5vw, -5vh) scale(200%)'}),
animate(
'200ms ease-out',
style({opacity: 1, transform: 'translate(0vw, 0vh) scale(100%)'}),
),
]),
]);
/** /**
* Component that displays the schedule * Component that displays the schedule
*/ */
@@ -75,7 +56,7 @@ const fabAnimations = trigger('fabAnimation', [
selector: 'stapps-schedule-page', selector: 'stapps-schedule-page',
templateUrl: 'schedule-page.html', templateUrl: 'schedule-page.html',
styleUrls: ['schedule-page.scss'], styleUrls: ['schedule-page.scss'],
animations: [materialSharedAxisX, fabAnimations], animations: [materialSharedAxisX],
}) })
export class SchedulePageComponent implements OnInit, AfterViewInit { export class SchedulePageComponent implements OnInit, AfterViewInit {
/** /**
@@ -88,8 +69,6 @@ export class SchedulePageComponent implements OnInit, AfterViewInit {
*/ */
actualSegmentValue?: string | null; actualSegmentValue?: string | null;
fabVisible = true;
/** /**
* Layout * Layout
*/ */
@@ -124,9 +103,8 @@ export class SchedulePageComponent implements OnInit, AfterViewInit {
} }
constructor( constructor(
private readonly modalController: ModalController,
private readonly activatedRoute: ActivatedRoute, private readonly activatedRoute: ActivatedRoute,
private readonly animationController: AnimationController, readonly routerOutlet: IonRouterOutlet,
private router: Router, private router: Router,
private location: Location, private location: Location,
) {} ) {}
@@ -171,63 +149,4 @@ export class SchedulePageComponent implements OnInit, AfterViewInit {
this.location.go(url); this.location.go(url);
this.tabChoreographer.changeViewForState(this.segmentView.value); this.tabChoreographer.changeViewForState(this.segmentView.value);
} }
/**
* Add event modal sheet
*/
async showCreateEventModal() {
this.fabVisible = false;
// eslint-disable-next-line @typescript-eslint/no-explicit-any,unicorn/consistent-function-scoping
const enterAnimation = (baseElement: any) => {
const backdropAnimation = this.animationController
.create()
.addElement(baseElement.querySelector('.modal-wrapper'))
.fromTo('opacity', '0', 'var(--backdrop-opacity)');
const wrapperAnimation = this.animationController
.create()
.addElement(baseElement.querySelector('.modal-wrapper'))
.keyframes([
{
opacity: '0',
transform: 'translate(30vw, 30vh) scale(0.5)',
},
{
opacity: '1',
transform: 'translate(0vw, 0vh) scale(1)',
},
]);
return this.animationController
.create()
.addElement(baseElement)
.easing('ease-out')
.duration(150)
.addAnimation([backdropAnimation, wrapperAnimation]);
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any,unicorn/consistent-function-scoping
const leaveAnimation = (baseElement: any) => {
return enterAnimation(baseElement).direction('reverse');
};
const modal = await this.modalController.create({
component: ModalEventCreatorComponent,
swipeToClose: true,
cssClass: 'add-modal',
componentProps: {
dismissAction: () => {
modal.dismiss();
},
},
enterAnimation,
leaveAnimation,
});
await modal.present();
await modal.onWillDismiss();
this.fabVisible = true;
}
} }

View File

@@ -51,14 +51,18 @@
<stapps-single-events *ngSwitchCase="'single'"></stapps-single-events> <stapps-single-events *ngSwitchCase="'single'"></stapps-single-events>
</div> </div>
<ion-fab <ion-fab id="add-events-fab" vertical="bottom" horizontal="end" slot="fixed">
*ngIf="fabVisible" <ion-fab-button>
@fabAnimation
vertical="bottom"
horizontal="end"
slot="fixed"
>
<ion-fab-button (click)="showCreateEventModal()">
<ion-icon name="add"></ion-icon> <ion-icon name="add"></ion-icon>
</ion-fab-button> </ion-fab-button>
</ion-fab> </ion-fab>
<ion-modal
trigger="add-events-fab"
swipeToClose="true"
[presentingElement]="routerOutlet.nativeEl"
>
<ng-template>
<modal-event-creator style="height: 100%"></modal-event-creator>
</ng-template>
</ion-modal>

View File

@@ -1,16 +1,16 @@
/*! /*!
* Copyright (C) 2021 StApps * Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free * under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3. * Software Foundation, version 3.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licens for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -30,12 +30,3 @@ div {
ion-segment-button { ion-segment-button {
text-transform: none; text-transform: none;
} }
.add-modal {
align-items: flex-end !important;
justify-content: flex-end !important;
.modal-wrapper {
transform-origin: bottom right !important;
}
}