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

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,7 @@
<ion-toolbar color="primary">
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
<ion-menu-button></ion-menu-button>
<ion-menu-button *ngIf="showDrawer"></ion-menu-button>
</ion-buttons>
<ion-buttons slot="end">
<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>
<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
*ngTemplateOutlet="
listItemTemplateRef || defaultListItem;

View File

@@ -21,6 +21,7 @@ import {DataProvider} from '../../data/data.provider';
import {DataDetailComponent} from '../../data/detail/data-detail.component';
import {DaiaDataProvider} from '../daia-data.provider';
import {SCDaiaHoldings} from '../protocol/response';
import {ModalController} from '@ionic/angular';
/**
* A Component to display an SCThing detailed
@@ -41,6 +42,7 @@ export class DaiaAvailabilityComponent
* @param route the route the page was accessed from
* @param dataProvider the data provider
* @param favoritesService the favorites provider
* @param modalController the modal controller
* @param translateService he translate provider
* @param daiaDataProvider DaiaDataProvider
*/
@@ -48,10 +50,17 @@ export class DaiaAvailabilityComponent
route: ActivatedRoute,
dataProvider: DataProvider,
favoritesService: FavoritesService,
modalController: ModalController,
translateService: TranslateService,
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 {DataDetailComponent} from '../../data/detail/data-detail.component';
import {SCDaiaHoldings} from '../protocol/response';
import {ModalController} from '@ionic/angular';
/**
* 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 dataProvider the data provider
* @param favoritesService the favorites provider
* @param modalController the modal controller
* @param translateService he translate provider
* @param hebisDataProvider HebisDataProvider
*/
@@ -45,10 +47,17 @@ export class HebisDetailComponent extends DataDetailComponent {
route: ActivatedRoute,
dataProvider: DataProvider,
favoritesService: FavoritesService,
modalController: ModalController,
translateService: TranslateService,
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-header>
<stapps-data-list-item
[item]="item"
(click)="showMore()"
[item]="$any(item)"
id="show-more"
></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>
</ion-card-header>
<ion-card-content>
@@ -12,15 +22,27 @@
<ion-col size="7">
<ion-note>
<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 }}
</span>
</ion-note>
</ion-col>
<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
></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-row>
</ion-grid>

View File

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

View File

@@ -20,7 +20,11 @@ import {
ViewChild,
} from '@angular/core';
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 {
SCBuilding,
@@ -44,8 +48,6 @@ import {DataRoutingService} from '../../data/data-routing.service';
import {ContextMenuService} from '../../menu/context/context-menu.service';
import {MapProvider} from '../map.provider';
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 {Capacitor} from '@capacitor/core';
@@ -116,11 +118,6 @@ export class MapPageComponent {
*/
MAX_ZOOM = 18;
/**
* Modal for additional information on places or for a list of places
*/
modal: HTMLIonModalElement;
/**
* Options of the leaflet map
*/
@@ -158,6 +155,7 @@ export class MapPageComponent {
private modalController: ModalController,
private dataRoutingService: DataRoutingService,
private positionService: PositionService,
readonly routerOutlet: IonRouterOutlet,
) {
// initialize the options
this.options = {
@@ -277,8 +275,10 @@ export class MapPageComponent {
this.dataRoutingService.itemSelectListener().subscribe(async item => {
// in case the list item is clicked
if (this.items.length > 1) {
await this.modal.dismiss();
await this.showItem(item.uid);
await Promise.all([
this.modalController.dismiss(),
this.showItem(item.uid),
]);
}
}),
this.positionService.watchCurrentLocation({maximumAge: 3000}).subscribe({
@@ -439,45 +439,4 @@ export class MapPageComponent {
// center the selected place
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>
<ion-header class="ion-no-border" translucent="true">
@@ -46,7 +61,7 @@
color="light"
shape="round"
size="small"
(click)="showListModal()"
(click)="mapListModal.present()"
>
<ion-icon name="list"></ion-icon>&nbsp;&nbsp;{{
'map.page.buttons.SHOW_LIST' | translate
@@ -71,7 +86,6 @@
<stapps-map-item
*ngIf="items.length === 1"
[item]="items[0]"
(showDetails)="showItemModal($event)"
></stapps-map-item>
</div>
<div class="map-buttons floating-buttons">
@@ -80,7 +94,7 @@
color="light"
shape="round"
size="small"
(click)="showListModal()"
(click)="mapListModal.present()"
>
<ion-icon name="list"></ion-icon>&nbsp;&nbsp;{{
'map.page.buttons.SHOW_LIST' | translate
@@ -102,4 +116,18 @@
</ng-template>
</ion-button>
</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>

View File

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

View File

@@ -1,13 +1,33 @@
<ion-header translucent>
<ion-toolbar color="primary">
<ion-title>{{ 'map.modals.list.TITLE' | translate }}</ion-title>
<ion-buttons slot="end">
<ion-button (click)="dismissAction()">{{
'app.ui.CLOSE' | translate
}}</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
<stapps-data-list [items]="items"></stapps-data-list>
</ion-content>
<!--
~ 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/>.
-->
<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 {SCPlace} from '@openstapps/core';
import {ModalController} from '@ionic/angular';
@Component({
selector: 'app-map-single-modal',
@@ -21,13 +22,10 @@ import {SCPlace} from '@openstapps/core';
styleUrls: ['./map-single.scss'],
})
export class MapSingleModalComponent {
/**
* Action when close is pressed
*/
@Input() dismissAction: () => void;
/**
* The item to be shown
*/
@Input() item: SCPlace;
constructor(readonly modalController: ModalController) {}
}

View File

@@ -2,12 +2,12 @@
<ion-toolbar color="primary">
<ion-title>{{ 'map.modals.single.TITLE' | translate }}</ion-title>
<ion-buttons slot="end">
<ion-button (click)="dismissAction()">{{
<ion-button (click)="modalController.dismiss()">{{
'app.ui.CLOSE' | translate
}}</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<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>

View File

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

View File

@@ -12,8 +12,12 @@
* You should have received a copy of the GNU General Public License along with
* 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 {ModalController} from '@ionic/angular';
import {DataRoutingService} from '../../../data/data-routing.service';
import {DataDetailComponent} from '../../../data/detail/data-detail.component';
import {Subscription} from 'rxjs';
/**
* TODO
@@ -23,11 +27,34 @@ import {SCSearchFilter, SCThingType} from '@openstapps/core';
templateUrl: 'modal-event-creator.html',
styleUrls: ['modal-event-creator.scss'],
})
export class ModalEventCreatorComponent {
/**
* Action when close is pressed
*/
@Input() dismissAction: () => void;
export class ModalEventCreatorComponent implements OnInit, OnDestroy {
subscriptions: Subscription[] = [];
constructor(
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

View File

@@ -18,7 +18,7 @@
'schedule.addEventModal.addEvent' | translate | titlecase
}}</ion-title>
<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-button>
</ion-buttons>
@@ -26,6 +26,7 @@
<ion-card-content>
<stapps-search-page
[showDrawer]="false"
[forcedFilter]="filter"
[itemRouting]="false"
></stapps-search-page>

View File

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

View File

@@ -21,12 +21,10 @@ import {
} from '@angular/core';
import {Location} from '@angular/common';
import {ActivatedRoute, Router} from '@angular/router';
import {AnimationController, ModalController} from '@ionic/angular';
import {IonRouterOutlet} from '@ionic/angular';
import {SharedAxisChoreographer} from '../../../animation/animation-choreographer';
import {materialSharedAxisX} from '../../../animation/material-motion';
import {ModalEventCreatorComponent} from './modal/modal-event-creator.component';
import {ScheduleResponsiveBreakpoint} from './schema/schema';
import {animate, style, transition, trigger} from '@angular/animations';
/**
* 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
*/
@@ -75,7 +56,7 @@ const fabAnimations = trigger('fabAnimation', [
selector: 'stapps-schedule-page',
templateUrl: 'schedule-page.html',
styleUrls: ['schedule-page.scss'],
animations: [materialSharedAxisX, fabAnimations],
animations: [materialSharedAxisX],
})
export class SchedulePageComponent implements OnInit, AfterViewInit {
/**
@@ -88,8 +69,6 @@ export class SchedulePageComponent implements OnInit, AfterViewInit {
*/
actualSegmentValue?: string | null;
fabVisible = true;
/**
* Layout
*/
@@ -124,9 +103,8 @@ export class SchedulePageComponent implements OnInit, AfterViewInit {
}
constructor(
private readonly modalController: ModalController,
private readonly activatedRoute: ActivatedRoute,
private readonly animationController: AnimationController,
readonly routerOutlet: IonRouterOutlet,
private router: Router,
private location: Location,
) {}
@@ -171,63 +149,4 @@ export class SchedulePageComponent implements OnInit, AfterViewInit {
this.location.go(url);
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>
</div>
<ion-fab
*ngIf="fabVisible"
@fabAnimation
vertical="bottom"
horizontal="end"
slot="fixed"
>
<ion-fab-button (click)="showCreateEventModal()">
<ion-fab id="add-events-fab" vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button>
<ion-icon name="add"></ion-icon>
</ion-fab-button>
</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
* 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.
* 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 License for
* more details.
* 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/>.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
@@ -30,12 +30,3 @@ div {
ion-segment-button {
text-transform: none;
}
.add-modal {
align-items: flex-end !important;
justify-content: flex-end !important;
.modal-wrapper {
transform-origin: bottom right !important;
}
}