From b8ac30b9d0ee458801312e3026330a4f5b5496ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thea=20Sch=C3=B6bl?= Date: Tue, 2 Jul 2024 17:28:57 +0200 Subject: [PATCH] refactor: migrate to angular esbuild refactor: migrate to ionic standalone components refactor: migrate ion icons to a custom element --- .changeset/forty-bulldogs-help.md | 5 + .changeset/thin-dodos-thank.md | 7 + .changeset/yellow-jobs-guess.md | 5 + .gitlab-ci.yml | 6 +- frontend/app/Dockerfile | 4 +- frontend/app/angular.json | 8 +- frontend/app/capacitor.config.ts | 2 +- frontend/app/package.json | 11 +- frontend/app/src/app/animation/fab-expand.ts | 2 +- frontend/app/src/app/app.component.spec.ts | 2 +- frontend/app/src/app/app.component.ts | 2 +- frontend/app/src/app/app.module.ts | 7 +- .../modules/about/about-licenses.component.ts | 2 +- .../app/src/app/modules/about/about.module.ts | 50 +++++- .../app/modules/about/app-version.service.ts | 4 +- .../modules/about/release-notes.component.ts | 21 ++- .../modules/assessments/assessments.module.ts | 38 ++++- .../detail/assessments-detail.component.ts | 2 +- .../page/auth-callback-page.component.ts | 2 +- .../app/modules/auth/auth-helper.service.ts | 2 +- .../app/src/app/modules/auth/auth.module.ts | 2 +- .../modules/auth/factories/http.factory.ts | 2 +- .../modules/auth/factories/storage.factory.ts | 2 +- .../calendar/add-event-review-modal.html | 2 +- .../app/modules/calendar/calendar.module.ts | 28 ++- .../src/app/modules/catalog/catalog.module.ts | 36 +++- .../modules/dashboard/dashboard-collapse.ts | 2 +- .../dashboard/dashboard.component.scss | 8 +- .../modules/dashboard/dashboard.component.ts | 4 +- .../app/modules/dashboard/dashboard.module.ts | 30 +++- .../jobs-section/job-section.component.ts | 2 + .../search-section/search-route-transition.ts | 2 +- .../search-section.component.ts | 2 +- .../data/add-event-action-chip.component.ts | 2 +- .../chips/edit-event-selection.component.ts | 2 +- .../chips/filter/chip-filter.component.ts | 1 + .../app/src/app/modules/data/data.module.ts | 91 +++++++++- .../data/debug-data-collector.service.ts | 2 +- .../detail/data-detail-content.component.ts | 2 +- .../data/detail/data-detail.component.spec.ts | 2 + .../data/detail/data-detail.component.ts | 2 +- .../data/detail/data-path.component.ts | 2 +- .../elements/favorite-button.component.scss | 3 +- .../src/app/modules/data/elements/rating.scss | 14 +- .../data/elements/share-button.component.ts | 2 +- .../modules/data/list/data-list.component.ts | 2 +- .../data/list/search-page-switch-animation.ts | 4 +- .../data/list/search-page.component.ts | 2 +- .../mensa/place-mensa-detail.component.ts | 2 +- .../favorites/favorites-page.component.ts | 2 +- .../app/modules/favorites/favorites.module.ts | 28 ++- .../feedback/feedback-page.component.ts | 2 +- .../app/modules/feedback/feedback.module.ts | 40 ++++- .../daia-availability.component.spec.ts | 2 + .../hebis/daia-availability/daia-holding.scss | 2 +- .../hebis-detail.component.spec.ts | 8 +- .../app/src/app/modules/hebis/hebis.module.ts | 42 ++++- .../app/src/app/modules/jobs/jobs.module.ts | 6 +- .../account/library-account.service.ts | 2 +- .../src/app/modules/library/library.module.ts | 46 ++++- .../map/controls/attribution.component.ts | 6 +- .../map/controls/compass-control.component.ts | 6 +- .../controls/geolocate-control.component.ts | 6 +- .../map/elements/poi-marker.component.ts | 6 +- .../modules/map/geo-navigation.directive.ts | 2 +- .../app/modules/map/map-maximize-animation.ts | 4 +- .../src/app/modules/map/map-page.component.ts | 11 +- .../app/modules/map/map-widget.component.ts | 8 +- .../context/context-menu.component.spec.ts | 4 +- .../modules/menu/context/context-menu.html | 5 +- .../app/src/app/modules/menu/menu.module.ts | 38 ++++- .../menu/navigation/navigation.module.ts | 40 ++++- .../modules/menu/navigation/navigation.scss | 6 +- .../menu/navigation/root-link.directive.ts | 2 +- .../menu/navigation/tabs-transition.ts | 4 +- .../menu/navigation/tabs.component.scss | 2 +- .../app/modules/menu/navigation/tabs.spec.ts | 2 +- .../app/src/app/modules/news/news.module.ts | 50 +++++- .../modules/news/page/news-page.component.ts | 2 +- .../src/app/modules/news/page/news-page.scss | 2 +- .../app/modules/profile/id-card.component.ts | 2 +- .../app/modules/profile/id-cards.component.ts | 4 +- .../src/app/modules/profile/profile.module.ts | 46 ++++- .../schedule/page/calendar-view.component.ts | 2 +- .../page/components/calendar.component.ts | 2 +- .../schedule/page/schedule-page.component.ts | 2 +- .../modules/schedule/page/schedule-page.scss | 2 +- .../schedule/page/schedule-view.component.ts | 2 +- .../app/modules/schedule/schedule.module.ts | 56 +++++- .../settings/item/settings-item.component.ts | 2 +- .../page/calendar-sync-settings.component.ts | 2 +- .../settings/page/settings-page.component.ts | 2 +- .../app/modules/settings/settings.module.ts | 50 +++++- .../app/translation/thing-translate.module.ts | 5 +- frontend/app/src/app/util/browser.factory.ts | 2 +- .../app/src/app/util/edit-modal.component.ts | 2 +- .../src/app/util/ion-icon/icon.component.ts | 46 ----- frontend/app/src/app/util/ion-icon/icon.html | 15 -- frontend/app/src/app/util/ion-icon/icon.scss | 31 ---- .../ion-icon/ion-back-button.directive.ts | 68 -------- .../util/ion-icon/ion-breadcrumb.directive.ts | 46 ----- .../ion-icon/ion-icon-custom-component.ts | 161 ++++++++++++++++++ .../app/util/ion-icon/ion-icon.directive.ts | 124 +++----------- .../src/app/util/ion-icon/ion-icon.module.ts | 45 ----- .../util/ion-icon/ion-reorder.directive.ts | 33 ---- .../util/ion-icon/ion-searchbar.directive.ts | 37 ---- .../app/src/app/util/ion-icon/replace-util.ts | 124 -------------- .../app/util/pending-changes-action-sheet.ts | 2 +- .../app/util/searchbar-autofocus.directive.ts | 2 +- .../app/src/app/util/section.component.ts | 2 +- frontend/app/src/app/util/util.module.ts | 28 ++- frontend/app/src/global.scss | 29 ++-- frontend/app/src/ion-icons.ts | 3 + .../app/src/theme/common/_ion-searchbar.scss | 12 +- .../app/src/theme/common/_ion-toolbar.scss | 3 +- frontend/app/src/types.d.ts | 9 + frontend/app/tsconfig.app.json | 2 +- pnpm-lock.yaml | 74 +------- 118 files changed, 1060 insertions(+), 844 deletions(-) create mode 100644 .changeset/forty-bulldogs-help.md create mode 100644 .changeset/thin-dodos-thank.md create mode 100644 .changeset/yellow-jobs-guess.md delete mode 100644 frontend/app/src/app/util/ion-icon/icon.component.ts delete mode 100644 frontend/app/src/app/util/ion-icon/icon.html delete mode 100644 frontend/app/src/app/util/ion-icon/icon.scss delete mode 100644 frontend/app/src/app/util/ion-icon/ion-back-button.directive.ts delete mode 100644 frontend/app/src/app/util/ion-icon/ion-breadcrumb.directive.ts create mode 100644 frontend/app/src/app/util/ion-icon/ion-icon-custom-component.ts delete mode 100644 frontend/app/src/app/util/ion-icon/ion-icon.module.ts delete mode 100644 frontend/app/src/app/util/ion-icon/ion-reorder.directive.ts delete mode 100644 frontend/app/src/app/util/ion-icon/ion-searchbar.directive.ts delete mode 100644 frontend/app/src/app/util/ion-icon/replace-util.ts create mode 100644 frontend/app/src/ion-icons.ts create mode 100644 frontend/app/src/types.d.ts diff --git a/.changeset/forty-bulldogs-help.md b/.changeset/forty-bulldogs-help.md new file mode 100644 index 00000000..6e15106f --- /dev/null +++ b/.changeset/forty-bulldogs-help.md @@ -0,0 +1,5 @@ +--- +"@openstapps/app": patch +--- + +Migrated IonIcons replacer to a custom component diff --git a/.changeset/thin-dodos-thank.md b/.changeset/thin-dodos-thank.md new file mode 100644 index 00000000..eb89980c --- /dev/null +++ b/.changeset/thin-dodos-thank.md @@ -0,0 +1,7 @@ +--- +"@openstapps/app": patch +--- + +Migrated to Ionic standalone components + +Angular ESBuild will not work with `IonicModule` apps diff --git a/.changeset/yellow-jobs-guess.md b/.changeset/yellow-jobs-guess.md new file mode 100644 index 00000000..2c603542 --- /dev/null +++ b/.changeset/yellow-jobs-guess.md @@ -0,0 +1,5 @@ +--- +"@openstapps/app": patch +--- + +Migrated to Angular ESBuild diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 26c480a5..ed6ad83c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -67,9 +67,9 @@ build: # "🦋 error Error: Failed to find where HEAD diverged from master. Does master exist?" # - pnpm changeset:status - pnpm build:full $TURBO_CACHE_BYPASS - - .gitlab/ci/enableGitlabReviewToolbar.sh frontend/app/www/index.html "$CI_PROJECT_ID" "$CI_OPEN_MERGE_REQUESTS" - - cp frontend/app/www/index.html frontend/app/www/200.html - - pnpm dlx surge -p frontend/app/www -d https://$CI_PROJECT_NAME-$DEPLOY_ID.surge.sh/ + - .gitlab/ci/enableGitlabReviewToolbar.sh frontend/app/www/browser/index.html "$CI_PROJECT_ID" "$CI_OPEN_MERGE_REQUESTS" + - cp frontend/app/www/browser/index.html frontend/app/www/browser/200.html + - pnpm dlx surge -p frontend/app/www/browser -d https://$CI_PROJECT_NAME-$DEPLOY_ID.surge.sh/ cache: <<: *pnpm_cache policy: pull-push diff --git a/frontend/app/Dockerfile b/frontend/app/Dockerfile index 6f826233..198fff77 100644 --- a/frontend/app/Dockerfile +++ b/frontend/app/Dockerfile @@ -4,10 +4,10 @@ FROM node:18-alpine3.18 WORKDIR /app -COPY www/ /app/www +COPY www/browser /app/www/browser COPY package.json /app EXPOSE 8100 RUN npm install -g http-server -CMD http-server www --p 8100 +CMD http-server www/browser --p 8100 diff --git a/frontend/app/angular.json b/frontend/app/angular.json index b2c7239b..62b16534 100644 --- a/frontend/app/angular.json +++ b/frontend/app/angular.json @@ -11,12 +11,12 @@ "schematics": {}, "architect": { "build": { - "builder": "@angular-devkit/build-angular:browser", + "builder": "@angular-devkit/build-angular:application", "options": { "outputPath": "www", "index": "src/index.html", - "main": "src/main.ts", - "polyfills": "zone.js", + "browser": "src/main.ts", + "polyfills": ["zone.js", "src/ion-icons.js"], "tsConfig": "tsconfig.app.json", "allowedCommonJsDependencies": [ "moment", @@ -72,9 +72,7 @@ ] }, "development": { - "buildOptimizer": false, "optimization": false, - "vendorChunk": true, "extractLicenses": false, "sourceMap": true, "namedChunks": true diff --git a/frontend/app/capacitor.config.ts b/frontend/app/capacitor.config.ts index 8d2f56e5..f3bee977 100644 --- a/frontend/app/capacitor.config.ts +++ b/frontend/app/capacitor.config.ts @@ -3,7 +3,7 @@ import {CapacitorConfig} from '@capacitor/cli'; const config: CapacitorConfig = { appId: 'de.anyschool.app', appName: 'StApps', - webDir: 'www', + webDir: 'www/browser', cordova: { preferences: { 'AndroidXEnabled': 'true', diff --git a/frontend/app/package.json b/frontend/app/package.json index 2e29fc96..19e85f67 100644 --- a/frontend/app/package.json +++ b/frontend/app/package.json @@ -14,12 +14,9 @@ "Thea Schöbl " ], "scripts": { - "analyze": "webpack-bundle-analyzer www/stats.json", - "build": "pnpm check-icons && ng build --configuration=production --stats-json && webpack-bundle-analyzer www/stats.json --mode static --report www/bundle-info.html --no-open", - "build:analyze": "npm run build:stats && npm run analyze", + "build": "pnpm check-icons && ng build --configuration=production", "build:android": "ionic capacitor build android --no-open && cd android && ./gradlew clean assemble && cd ..", "build:prod": "ng build --configuration=production", - "build:stats": "ng build --configuration=production --stats-json", "changelog": "conventional-changelog -p angular -i src/assets/about/CHANGELOG.md -s -r 0", "check-icons": "node scripts/check-icon-correctness.mjs", "chromium:no-cors": "chromium --disable-web-security --user-data-dir=\".browser-data/chromium\"", @@ -40,7 +37,7 @@ "lint:fix": "eslint --fix -c .eslintrc.json --ignore-path .eslintignore --ext .ts,.html src/ && stylelint --fix \"**/*.scss\"", "minify-icons": "node scripts/minify-icon-font.mjs", "postinstall": "jetify && echo \"skipping jetify in production mode\"", - "preview": "http-server www --p 8101 -o", + "preview": "http-server www/browser --p 8101 -o", "push": "git push && git push origin \"v$npm_package_version\"", "resources:ios": "capacitor-assets generate --ios --iconBackgroundColor $(grep -oE \"^@include ion-color\\(primary, #[a-fA-F0-9]{3,6}\" src/theme/colors.scss | grep -oE \"#[a-fA-F0-9]{3,6}\") --splashBackgroundColor $(grep -oE \"^@include ion-color\\(primary, #[a-fA-F0-9]{3,6}\" src/theme/colors.scss | grep -oE \"#[a-fA-F0-9]{3,6}\")", "run:android": "ionic capacitor run android --livereload --external", @@ -97,6 +94,7 @@ "form-data": "4.0.0", "geojson": "0.5.0", "ionic-appauth": "0.9.0", + "ionicons": "7.4.0", "jsonpath-plus": "10.0.7", "maplibre-gl": "4.0.2", "material-symbols": "0.17.1", @@ -181,8 +179,7 @@ "stylelint-config-standard-scss": "13.0.0", "surge": "0.23.1", "ts-node": "10.9.2", - "typescript": "5.4.2", - "webpack-bundle-analyzer": "4.10.1" + "typescript": "5.4.2" }, "cordova": { "plugins": {}, diff --git a/frontend/app/src/app/animation/fab-expand.ts b/frontend/app/src/app/animation/fab-expand.ts index 2de16f82..01cc4a9e 100644 --- a/frontend/app/src/app/animation/fab-expand.ts +++ b/frontend/app/src/app/animation/fab-expand.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {AnimationBuilder, AnimationController} from '@ionic/angular'; +import {AnimationBuilder, AnimationController} from '@ionic/angular/standalone'; import {AnimationOptions} from '@ionic/angular/common/providers/nav-controller'; import {iosDuration, iosEasing, mdDuration, mdEasing} from './easings'; diff --git a/frontend/app/src/app/app.component.spec.ts b/frontend/app/src/app/app.component.spec.ts index 8afad80d..a65c8e63 100644 --- a/frontend/app/src/app/app.component.spec.ts +++ b/frontend/app/src/app/app.component.spec.ts @@ -17,7 +17,7 @@ import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; import {TestBed} from '@angular/core/testing'; -import {ModalController, Platform} from '@ionic/angular'; +import {ModalController, Platform} from '@ionic/angular/standalone'; import {TranslateService} from '@ngx-translate/core'; import {ThingTranslateService} from './translation/thing-translate.service'; diff --git a/frontend/app/src/app/app.component.ts b/frontend/app/src/app/app.component.ts index ca2b6380..09df9a16 100644 --- a/frontend/app/src/app/app.component.ts +++ b/frontend/app/src/app/app.component.ts @@ -15,7 +15,7 @@ import {AfterContentInit, Component, NgZone} from '@angular/core'; import {Router} from '@angular/router'; import {App, URLOpenListenerEvent} from '@capacitor/app'; -import {Platform, ToastController} from '@ionic/angular'; +import {Platform, ToastController} from '@ionic/angular/standalone'; import {SettingsProvider} from './modules/settings/settings.provider'; import {AuthHelperService} from './modules/auth/auth-helper.service'; import {environment} from '../environments/environment'; diff --git a/frontend/app/src/app/app.module.ts b/frontend/app/src/app/app.module.ts index 80c0fcd6..1e25dc65 100644 --- a/frontend/app/src/app/app.module.ts +++ b/frontend/app/src/app/app.module.ts @@ -18,7 +18,7 @@ import localeDe from '@angular/common/locales/de'; import {APP_INITIALIZER, NgModule} from '@angular/core'; import {BrowserModule} from '@angular/platform-browser'; import {RouteReuseStrategy} from '@angular/router'; -import {IonicModule, IonicRouteStrategy, Platform} from '@ionic/angular'; +import {IonicRouteStrategy, Platform, provideIonicAngular, IonApp} from '@ionic/angular/standalone'; import {TranslateLoader, TranslateModule, TranslateService} from '@ngx-translate/core'; import {TranslateHttpLoader} from '@ngx-translate/http-loader'; import moment from 'moment'; @@ -61,7 +61,6 @@ import {RoutingStackService} from './util/routing-stack.service'; import {SCLanguageCode, SCSettingValue} from '@openstapps/core'; import {DefaultAuthService} from './modules/auth/default-auth.service'; import {PAIAAuthService} from './modules/auth/paia/paia-auth.service'; -import {IonIconModule} from './util/ion-icon/ion-icon.module'; import {NavigationModule} from './modules/menu/navigation/navigation.module'; import {browserFactory, SimpleBrowser} from './util/browser.factory'; import {getDateFnsLocale} from './translation/dfns-locale'; @@ -156,8 +155,6 @@ export function createTranslateLoader(http: HttpClient) { DashboardModule, DataModule, HebisModule, - IonicModule.forRoot(), - IonIconModule, JobModule, FavoritesModule, LibraryModule, @@ -185,6 +182,7 @@ export function createTranslateLoader(http: HttpClient) { LoggerModule.forRoot({ level: environment.production ? NgxLoggerLevel.FATAL : NgxLoggerLevel.TRACE, }), + IonApp, ], providers: [ { @@ -221,6 +219,7 @@ export function createTranslateLoader(http: HttpClient) { useClass: ServiceHandlerInterceptor, multi: true, }, + provideIonicAngular(), ], }) export class AppModule { diff --git a/frontend/app/src/app/modules/about/about-licenses.component.ts b/frontend/app/src/app/modules/about/about-licenses.component.ts index 79bab44d..068b7019 100644 --- a/frontend/app/src/app/modules/about/about-licenses.component.ts +++ b/frontend/app/src/app/modules/about/about-licenses.component.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ import {Component, OnInit} from '@angular/core'; -import {ModalController} from '@ionic/angular'; +import {ModalController} from '@ionic/angular/standalone'; import {AboutLicenseModalComponent} from './about-license-modal.component'; import licensesFile from 'src/assets/about/licenses.json'; diff --git a/frontend/app/src/app/modules/about/about.module.ts b/frontend/app/src/app/modules/about/about.module.ts index daa93fed..49b1fa84 100644 --- a/frontend/app/src/app/modules/about/about.module.ts +++ b/frontend/app/src/app/modules/about/about.module.ts @@ -16,7 +16,6 @@ import {RouterModule, Routes} from '@angular/router'; import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; import {FormsModule} from '@angular/forms'; -import {IonicModule} from '@ionic/angular'; import {TranslateModule} from '@ngx-translate/core'; import {ThingTranslateModule} from '../../translation/thing-translate.module'; import {AboutPageComponent} from './about-page/about-page.component'; @@ -28,8 +27,31 @@ import {ScrollingModule} from '@angular/cdk/scrolling'; import {AboutLicenseModalComponent} from './about-license-modal.component'; import {AboutChangelogComponent} from './about-changelog.component'; import {UtilModule} from '../../util/util.module'; -import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; import {AboutReleaseNotesComponent} from './about-release-notes.component'; +import { + IonBackButton, + IonButton, + IonButtons, + IonCard, + IonCardContent, + IonCardHeader, + IonCardSubtitle, + IonCardTitle, + IonChip, + IonCol, + IonContent, + IonGrid, + IonHeader, + IonLabel, + IonList, + IonRouterLink, + IonRow, + IonSkeletonText, + IonText, + IonTitle, + IonToolbar, +} from '@ionic/angular/standalone'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; const settingsRoutes: Routes = [ {path: 'about', component: AboutPageComponent}, @@ -55,9 +77,8 @@ const settingsRoutes: Routes = [ ], imports: [ CommonModule, - IonIconModule, + IonIconDirective, FormsModule, - IonicModule.forRoot(), TranslateModule.forChild(), ThingTranslateModule.forChild(), RouterModule.forChild(settingsRoutes), @@ -65,6 +86,27 @@ const settingsRoutes: Routes = [ DataModule, ScrollingModule, UtilModule, + IonRouterLink, + IonBackButton, + IonButton, + IonButtons, + IonText, + IonSkeletonText, + IonTitle, + IonToolbar, + IonHeader, + IonLabel, + IonGrid, + IonRow, + IonCol, + IonCard, + IonCardHeader, + IonCardTitle, + IonCardContent, + IonCardSubtitle, + IonChip, + IonList, + IonContent, ], }) export class AboutModule {} diff --git a/frontend/app/src/app/modules/about/app-version.service.ts b/frontend/app/src/app/modules/about/app-version.service.ts index c7d57db3..2a53c721 100644 --- a/frontend/app/src/app/modules/about/app-version.service.ts +++ b/frontend/app/src/app/modules/about/app-version.service.ts @@ -1,12 +1,12 @@ import {Injectable} from '@angular/core'; import {StorageProvider} from '../storage/storage.provider'; import {ConfigProvider} from '../config/config.provider'; -import {ModalController} from '@ionic/angular'; +import {ModalController} from '@ionic/angular/standalone'; +import {Capacitor} from '@capacitor/core'; import {ReleaseNotesComponent} from './release-notes.component'; import {SCAppVersionInfo} from '@openstapps/core'; import {App} from '@capacitor/app'; import {coerce} from 'semver'; -import {Capacitor} from '@capacitor/core'; export const RELEASE_NOTES_SHOWN_KEY = 'release_notes_shown'; diff --git a/frontend/app/src/app/modules/about/release-notes.component.ts b/frontend/app/src/app/modules/about/release-notes.component.ts index 47610b4e..8e7a3d52 100644 --- a/frontend/app/src/app/modules/about/release-notes.component.ts +++ b/frontend/app/src/app/modules/about/release-notes.component.ts @@ -2,7 +2,14 @@ import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; import {SCAppVersionInfo} from '@openstapps/core'; import {MarkdownModule} from 'ngx-markdown'; import {ThingTranslateModule} from '../../translation/thing-translate.module'; -import {IonicModule, ModalController} from '@ionic/angular'; +import { + IonButton, + IonButtons, + IonHeader, + IonTitle, + IonToolbar, + ModalController, +} from '@ionic/angular/standalone'; import {TranslateModule} from '@ngx-translate/core'; import {UtilModule} from '../../util/util.module'; @@ -12,7 +19,17 @@ import {UtilModule} from '../../util/util.module'; styleUrls: ['release-notes.scss', 'release-notes-markdown.scss'], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, - imports: [UtilModule, MarkdownModule, ThingTranslateModule, IonicModule, TranslateModule], + imports: [ + UtilModule, + MarkdownModule, + ThingTranslateModule, + TranslateModule, + IonButton, + IonButtons, + IonToolbar, + IonHeader, + IonTitle, + ], }) export class ReleaseNotesComponent { @Input() versionInfos: SCAppVersionInfo[]; diff --git a/frontend/app/src/app/modules/assessments/assessments.module.ts b/frontend/app/src/app/modules/assessments/assessments.module.ts index a6eb1373..05293a2b 100644 --- a/frontend/app/src/app/modules/assessments/assessments.module.ts +++ b/frontend/app/src/app/modules/assessments/assessments.module.ts @@ -19,7 +19,6 @@ import {AssessmentBaseInfoComponent} from './types/assessment/assessment-base-in import {AssessmentDetailComponent} from './types/assessment/assessment-detail.component'; import {CommonModule} from '@angular/common'; import {FormsModule} from '@angular/forms'; -import {IonicModule} from '@ionic/angular'; import {TranslateModule} from '@ngx-translate/core'; import {DataModule} from '../data/data.module'; import {ThingTranslateModule} from '../../translation/thing-translate.module'; @@ -35,8 +34,25 @@ import {AssessmentsProvider} from './assessments.provider'; import {AssessmentsSimpleDataListComponent} from './list/assessments-simple-data-list.component'; import {ProtectedRoutes} from '../auth/protected.routes'; import {AssessmentsTreeListComponent} from './list/assessments-tree-list.component'; -import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; import {UtilModule} from '../../util/util.module'; +import { + IonBackButton, + IonButton, + IonButtons, + IonCard, + IonCardContent, + IonContent, + IonHeader, + IonItem, + IonLabel, + IonList, + IonNote, + IonSegment, + IonSegmentButton, + IonTitle, + IonToolbar, +} from '@ionic/angular/standalone'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; const routes: ProtectedRoutes = [ { @@ -69,14 +85,28 @@ const routes: ProtectedRoutes = [ imports: [ CommonModule, FormsModule, - IonIconModule, - IonicModule, + IonIconDirective, RouterModule.forChild(routes), TranslateModule, DataModule, ThingTranslateModule, MomentModule, UtilModule, + IonBackButton, + IonList, + IonItem, + IonNote, + IonCardContent, + IonCard, + IonLabel, + IonSegment, + IonSegmentButton, + IonButtons, + IonTitle, + IonContent, + IonHeader, + IonToolbar, + IonButton, ], providers: [AssessmentsProvider], exports: [], diff --git a/frontend/app/src/app/modules/assessments/detail/assessments-detail.component.ts b/frontend/app/src/app/modules/assessments/detail/assessments-detail.component.ts index 0ce6359c..744c6bc2 100644 --- a/frontend/app/src/app/modules/assessments/detail/assessments-detail.component.ts +++ b/frontend/app/src/app/modules/assessments/detail/assessments-detail.component.ts @@ -17,7 +17,7 @@ import {Component, DestroyRef, inject, Input, OnInit, ViewChild} from '@angular/ import {ActivatedRoute} from '@angular/router'; import {AssessmentsProvider} from '../assessments.provider'; import {DataDetailComponent, ExternalDataLoadEvent} from '../../data/detail/data-detail.component'; -import {NavController} from '@ionic/angular'; +import {NavController} from '@ionic/angular/standalone'; import {DataRoutingService} from '../../data/data-routing.service'; import {SCAssessment} from '@openstapps/core'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; diff --git a/frontend/app/src/app/modules/auth/auth-callback/page/auth-callback-page.component.ts b/frontend/app/src/app/modules/auth/auth-callback/page/auth-callback-page.component.ts index c21ab68f..cd45070e 100644 --- a/frontend/app/src/app/modules/auth/auth-callback/page/auth-callback-page.component.ts +++ b/frontend/app/src/app/modules/auth/auth-callback/page/auth-callback-page.component.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ import {Component} from '@angular/core'; -import {NavController} from '@ionic/angular'; +import {NavController} from '@ionic/angular/standalone'; import {Router} from '@angular/router'; import {AuthActions, IAuthAction} from 'ionic-appauth'; import {AuthHelperService} from '../../auth-helper.service'; diff --git a/frontend/app/src/app/modules/auth/auth-helper.service.ts b/frontend/app/src/app/modules/auth/auth-helper.service.ts index e62435b0..bb3a6db4 100644 --- a/frontend/app/src/app/modules/auth/auth-helper.service.ts +++ b/frontend/app/src/app/modules/auth/auth-helper.service.ts @@ -29,7 +29,7 @@ import {StorageProvider} from '../storage/storage.provider'; import {DefaultAuthService} from './default-auth.service'; import {PAIAAuthService} from './paia/paia-auth.service'; import {SimpleBrowser} from '../../util/browser.factory'; -import {AlertController} from '@ionic/angular'; +import {AlertController} from '@ionic/angular/standalone'; const AUTH_ORIGIN_PATH = 'stapps.auth.origin_path'; diff --git a/frontend/app/src/app/modules/auth/auth.module.ts b/frontend/app/src/app/modules/auth/auth.module.ts index 690a4c2c..9b47b366 100644 --- a/frontend/app/src/app/modules/auth/auth.module.ts +++ b/frontend/app/src/app/modules/auth/auth.module.ts @@ -1,6 +1,6 @@ import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; -import {Platform} from '@ionic/angular'; +import {Platform} from '@ionic/angular/standalone'; import {Requestor, StorageBackend} from '@openid/appauth'; import {storageFactory} from './factories'; import {Browser} from 'ionic-appauth'; diff --git a/frontend/app/src/app/modules/auth/factories/http.factory.ts b/frontend/app/src/app/modules/auth/factories/http.factory.ts index 6ba5e276..ec137d73 100644 --- a/frontend/app/src/app/modules/auth/factories/http.factory.ts +++ b/frontend/app/src/app/modules/auth/factories/http.factory.ts @@ -14,7 +14,7 @@ */ import {HttpClient} from '@angular/common/http'; -import {Platform} from '@ionic/angular'; +import {Platform} from '@ionic/angular/standalone'; import {CapacitorRequestor} from '../capacitor-requestor'; import {NgHttpService} from '../ng-http.service'; diff --git a/frontend/app/src/app/modules/auth/factories/storage.factory.ts b/frontend/app/src/app/modules/auth/factories/storage.factory.ts index 0bb5f194..2b9a3449 100644 --- a/frontend/app/src/app/modules/auth/factories/storage.factory.ts +++ b/frontend/app/src/app/modules/auth/factories/storage.factory.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {Platform} from '@ionic/angular'; +import {Platform} from '@ionic/angular/standalone'; import {IonicStorage} from 'ionic-appauth/lib'; import {SafeCapacitorSecureStorage} from '../../storage/capacitor-secure-storage'; diff --git a/frontend/app/src/app/modules/calendar/add-event-review-modal.html b/frontend/app/src/app/modules/calendar/add-event-review-modal.html index 5d9081fa..a5da178e 100644 --- a/frontend/app/src/app/modules/calendar/add-event-review-modal.html +++ b/frontend/app/src/app/modules/calendar/add-event-review-modal.html @@ -67,7 +67,7 @@
{{ 'share' | translate }} - + @if (isWeb) { diff --git a/frontend/app/src/app/modules/calendar/calendar.module.ts b/frontend/app/src/app/modules/calendar/calendar.module.ts index b28658fe..751b06e7 100644 --- a/frontend/app/src/app/modules/calendar/calendar.module.ts +++ b/frontend/app/src/app/modules/calendar/calendar.module.ts @@ -18,26 +18,46 @@ import {AddEventReviewModalComponent} from './add-event-review-modal.component'; import {Calendar} from '@awesome-cordova-plugins/calendar/ngx'; import {CalendarService} from './calendar.service'; import {ScheduleProvider} from './schedule.provider'; -import {IonicModule} from '@ionic/angular'; import {TranslateModule} from '@ngx-translate/core'; import {ThingTranslateModule} from '../../translation/thing-translate.module'; import {FormsModule} from '@angular/forms'; import {CommonModule} from '@angular/common'; import {MomentModule} from 'ngx-moment'; import {UtilModule} from '../../util/util.module'; -import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; +import { + IonButton, + IonCardContent, + IonCardHeader, + IonCardTitle, + IonItem, + IonItemDivider, + IonItemGroup, + IonLabel, + IonList, + IonNote, +} from '@ionic/angular/standalone'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; @NgModule({ declarations: [AddEventReviewModalComponent], imports: [ - IonicModule.forRoot(), TranslateModule.forChild(), ThingTranslateModule.forChild(), - IonIconModule, + IonIconDirective, FormsModule, CommonModule, MomentModule, UtilModule, + IonButton, + IonItem, + IonNote, + IonLabel, + IonList, + IonItemGroup, + IonItemDivider, + IonCardContent, + IonCardTitle, + IonCardHeader, ], exports: [], providers: [Calendar, CalendarService, ScheduleProvider], diff --git a/frontend/app/src/app/modules/catalog/catalog.module.ts b/frontend/app/src/app/modules/catalog/catalog.module.ts index 88644e69..ca5b720c 100644 --- a/frontend/app/src/app/modules/catalog/catalog.module.ts +++ b/frontend/app/src/app/modules/catalog/catalog.module.ts @@ -16,14 +16,29 @@ import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {RouterModule, Routes} from '@angular/router'; -import {IonicModule} from '@ionic/angular'; import {TranslateModule} from '@ngx-translate/core'; import {MomentModule} from 'ngx-moment'; import {DataModule} from '../data/data.module'; import {SettingsProvider} from '../settings/settings.provider'; import {CatalogComponent} from './catalog.component'; import {UtilModule} from '../../util/util.module'; -import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; +import { + IonHeader, + IonToolbar, + IonButtons, + IonBackButton, + IonTitle, + IonSegment, + IonSegmentButton, + IonLabel, + IonContent, + IonList, + IonItem, + IonGrid, + IonRow, + IonCol, +} from '@ionic/angular/standalone'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; const catalogRoutes: Routes = [ {path: 'catalog', component: CatalogComponent}, @@ -36,15 +51,28 @@ const catalogRoutes: Routes = [ @NgModule({ declarations: [CatalogComponent], imports: [ - IonicModule.forRoot(), FormsModule, TranslateModule.forChild(), RouterModule.forChild(catalogRoutes), - IonIconModule, + IonIconDirective, CommonModule, MomentModule, DataModule, UtilModule, + IonHeader, + IonToolbar, + IonButtons, + IonBackButton, + IonTitle, + IonSegment, + IonSegmentButton, + IonLabel, + IonContent, + IonList, + IonItem, + IonGrid, + IonRow, + IonCol, ], providers: [SettingsProvider], }) diff --git a/frontend/app/src/app/modules/dashboard/dashboard-collapse.ts b/frontend/app/src/app/modules/dashboard/dashboard-collapse.ts index 790ccf34..a9a169f3 100644 --- a/frontend/app/src/app/modules/dashboard/dashboard-collapse.ts +++ b/frontend/app/src/app/modules/dashboard/dashboard-collapse.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {Animation, AnimationController} from '@ionic/angular'; +import {Animation, AnimationController} from '@ionic/angular/standalone'; import {NgZone} from '@angular/core'; export class DashboardCollapse { diff --git a/frontend/app/src/app/modules/dashboard/dashboard.component.scss b/frontend/app/src/app/modules/dashboard/dashboard.component.scss index 93348a1b..f0a43530 100644 --- a/frontend/app/src/app/modules/dashboard/dashboard.component.scss +++ b/frontend/app/src/app/modules/dashboard/dashboard.component.scss @@ -118,10 +118,6 @@ ion-content { font-weight: var(--font-weight-semi-bold); word-break: break-word; } - - &:hover ::ng-deep stapps-icon { - --fill: 1; - } } a:last-child { @@ -159,4 +155,8 @@ ion-content { line-height: 1.2; } } + + a:first-child:hover { + --fill: 1; + } } diff --git a/frontend/app/src/app/modules/dashboard/dashboard.component.ts b/frontend/app/src/app/modules/dashboard/dashboard.component.ts index 94311164..2e6946e6 100644 --- a/frontend/app/src/app/modules/dashboard/dashboard.component.ts +++ b/frontend/app/src/app/modules/dashboard/dashboard.component.ts @@ -29,7 +29,7 @@ import moment from 'moment'; import {SCDateSeries, SCUuid} from '@openstapps/core'; import {DataRoutingService} from '../data/data-routing.service'; import {ScheduleProvider} from '../calendar/schedule.provider'; -import {AnimationController, IonContent} from '@ionic/angular'; +import {AnimationController, IonContent} from '@ionic/angular/standalone'; import {DashboardCollapse} from './dashboard-collapse'; import {BreakpointObserver} from '@angular/cdk/layout'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; @@ -37,7 +37,7 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; @Component({ selector: 'app-dashboard', templateUrl: './dashboard.component.html', - styleUrls: ['./dashboard.component.scss', '/dashboard.collapse.component.scss'], + styleUrls: ['./dashboard.component.scss', './dashboard.collapse.component.scss'], }) export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { @ViewChild('toolbar', {read: ElementRef}) toolbarRef: ElementRef; diff --git a/frontend/app/src/app/modules/dashboard/dashboard.module.ts b/frontend/app/src/app/modules/dashboard/dashboard.module.ts index a39c0daa..e81bc4e8 100644 --- a/frontend/app/src/app/modules/dashboard/dashboard.module.ts +++ b/frontend/app/src/app/modules/dashboard/dashboard.module.ts @@ -16,7 +16,6 @@ import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {RouterModule, Routes} from '@angular/router'; -import {IonicModule} from '@ionic/angular'; import {SwiperModule} from 'swiper/angular'; import {TranslateModule, TranslatePipe} from '@ngx-translate/core'; import {MomentModule} from 'ngx-moment'; @@ -30,10 +29,23 @@ import {MensaSectionContentComponent} from './sections/mensa-section/mensa-secti import {FavoritesSectionComponent} from './sections/favorites-section/favorites-section.component'; import {ThingTranslateModule} from '../../translation/thing-translate.module'; import {UtilModule} from '../../util/util.module'; -import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; import {NewsModule} from '../news/news.module'; import {JobSectionComponent} from './sections/jobs-section/job-section.component'; import {JobModule} from '../jobs/jobs.module'; +import { + IonHeader, + IonToolbar, + IonLabel, + IonImg, + IonContent, + IonButton, + IonItem, + IonThumbnail, + IonSearchbar, + IonRippleEffect, + IonRouterLink, +} from '@ionic/angular/standalone'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; const catalogRoutes: Routes = [ { @@ -56,8 +68,7 @@ const catalogRoutes: Routes = [ JobSectionComponent, ], imports: [ - IonicModule.forRoot(), - IonIconModule, + IonIconDirective, FormsModule, TranslateModule.forChild(), RouterModule.forChild(catalogRoutes), @@ -69,6 +80,17 @@ const catalogRoutes: Routes = [ UtilModule, NewsModule, JobModule, + IonHeader, + IonToolbar, + IonImg, + IonContent, + IonButton, + IonItem, + IonLabel, + IonThumbnail, + IonSearchbar, + IonRippleEffect, + IonRouterLink, ], providers: [SettingsProvider, TranslatePipe], }) diff --git a/frontend/app/src/app/modules/dashboard/sections/jobs-section/job-section.component.ts b/frontend/app/src/app/modules/dashboard/sections/jobs-section/job-section.component.ts index a4778413..23d2e38a 100644 --- a/frontend/app/src/app/modules/dashboard/sections/jobs-section/job-section.component.ts +++ b/frontend/app/src/app/modules/dashboard/sections/jobs-section/job-section.component.ts @@ -35,4 +35,6 @@ export class JobSectionComponent { from: 0, }) .then((result: SCSearchResult) => result.data); + + constructor() {} } diff --git a/frontend/app/src/app/modules/dashboard/sections/search-section/search-route-transition.ts b/frontend/app/src/app/modules/dashboard/sections/search-section/search-route-transition.ts index ec0c6662..40ff6d23 100644 --- a/frontend/app/src/app/modules/dashboard/sections/search-section/search-route-transition.ts +++ b/frontend/app/src/app/modules/dashboard/sections/search-section/search-route-transition.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {AnimationController} from '@ionic/angular'; +import {AnimationController} from '@ionic/angular/standalone'; import {AnimationOptions} from '@ionic/angular/common/providers/nav-controller'; /** diff --git a/frontend/app/src/app/modules/dashboard/sections/search-section/search-section.component.ts b/frontend/app/src/app/modules/dashboard/sections/search-section/search-section.component.ts index a4c4783a..d1aa97c7 100644 --- a/frontend/app/src/app/modules/dashboard/sections/search-section/search-section.component.ts +++ b/frontend/app/src/app/modules/dashboard/sections/search-section/search-section.component.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ import {Component} from '@angular/core'; -import {AnimationController} from '@ionic/angular'; +import {AnimationController} from '@ionic/angular/standalone'; import {homePageSearchTransition} from './search-route-transition'; /** diff --git a/frontend/app/src/app/modules/data/chips/data/add-event-action-chip.component.ts b/frontend/app/src/app/modules/data/chips/data/add-event-action-chip.component.ts index 2460160a..e3d2c588 100644 --- a/frontend/app/src/app/modules/data/chips/data/add-event-action-chip.component.ts +++ b/frontend/app/src/app/modules/data/chips/data/add-event-action-chip.component.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ import {Component, DestroyRef, inject, Input, ViewChild} from '@angular/core'; -import {IonRouterOutlet, ModalController} from '@ionic/angular'; +import {IonRouterOutlet, ModalController} from '@ionic/angular/standalone'; import {SCDateSeries, SCThing, SCThingType, SCUuid} from '@openstapps/core'; import {Subscription} from 'rxjs'; import {ScheduleProvider} from '../../../calendar/schedule.provider'; diff --git a/frontend/app/src/app/modules/data/chips/edit-event-selection.component.ts b/frontend/app/src/app/modules/data/chips/edit-event-selection.component.ts index 1ef33120..dd0ea5e0 100644 --- a/frontend/app/src/app/modules/data/chips/edit-event-selection.component.ts +++ b/frontend/app/src/app/modules/data/chips/edit-event-selection.component.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ import {ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; -import {ModalController} from '@ionic/angular'; +import {ModalController} from '@ionic/angular/standalone'; import {SCDateSeries} from '@openstapps/core'; import { DateSeriesRelevantData, diff --git a/frontend/app/src/app/modules/data/chips/filter/chip-filter.component.ts b/frontend/app/src/app/modules/data/chips/filter/chip-filter.component.ts index ddcebd8c..0e438078 100644 --- a/frontend/app/src/app/modules/data/chips/filter/chip-filter.component.ts +++ b/frontend/app/src/app/modules/data/chips/filter/chip-filter.component.ts @@ -13,6 +13,7 @@ * this program. If not, see . */ import {Component, EventEmitter, Input, Output} from '@angular/core'; + /** * Shows a chip filter */ diff --git a/frontend/app/src/app/modules/data/data.module.ts b/frontend/app/src/app/modules/data/data.module.ts index a8f89ec5..503b26a8 100644 --- a/frontend/app/src/app/modules/data/data.module.ts +++ b/frontend/app/src/app/modules/data/data.module.ts @@ -17,13 +17,55 @@ import {CommonModule} from '@angular/common'; import {HttpClientModule} from '@angular/common/http'; import {NgModule} from '@angular/core'; import {FormsModule} from '@angular/forms'; -import {IonicModule, Platform} from '@ionic/angular'; +import { + IonAccordion, + IonButton, + IonCard, + IonCardHeader, + IonCardTitle, + IonCardContent, + IonAccordionGroup, + IonBreadcrumb, + IonBreadcrumbs, + IonButtons, + IonChip, + IonCol, + IonContent, + IonGrid, + IonHeader, + IonImg, + IonLabel, + IonList, + IonListHeader, + IonNote, + IonPopover, + IonRow, + IonSegment, + IonSegmentButton, + IonText, + IonThumbnail, + IonToolbar, + Platform, + IonMenuButton, + IonSearchbar, + IonTitle, + IonBackButton, + IonInfiniteScroll, + IonInfiniteScrollContent, + IonItem, + IonSkeletonText, + IonToast, + IonBadge, + IonCardSubtitle, + IonCheckbox, + IonFooter, + IonRouterLink, +} from '@ionic/angular/standalone'; import {TranslateModule} from '@ngx-translate/core'; import {MarkdownModule} from 'ngx-markdown'; import {MomentModule} from 'ngx-moment'; import {ThingTranslateModule} from '../../translation/thing-translate.module'; import {SimpleBrowser, browserFactory} from '../../util/browser.factory'; -import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; import {RoutingStackService} from '../../util/routing-stack.service'; import {UtilModule} from '../../util/util.module'; import {CalendarService} from '../calendar/calendar.service'; @@ -106,6 +148,7 @@ import {SemesterListItemComponent} from './types/semester/semester-list-item.com import {VideoDetailContentComponent} from './types/video/video-detail-content.component'; import {VideoListItemComponent} from './types/video/video-list-item.component'; import {ShareButtonComponent} from './elements/share-button.component'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; /** * Module for handling data @@ -187,10 +230,9 @@ import {ShareButtonComponent} from './elements/share-button.component'; FormsModule, MapWidgetComponent, HttpClientModule, - IonicModule.forRoot(), MarkdownModule.forRoot(), MenuModule, - IonIconModule, + IonIconDirective, MomentModule.forRoot({ relativeTimeThresholdOptions: { m: 59, @@ -202,6 +244,47 @@ import {ShareButtonComponent} from './elements/share-button.component'; ThingTranslateModule.forChild(), UtilModule, GeoNavigationDirective, + IonButton, + IonCard, + IonCardHeader, + IonCardTitle, + IonCardContent, + IonCardSubtitle, + IonNote, + IonLabel, + IonGrid, + IonCol, + IonRow, + IonList, + IonSegment, + IonListHeader, + IonSegmentButton, + IonChip, + IonImg, + IonPopover, + IonThumbnail, + IonBreadcrumbs, + IonBreadcrumb, + IonAccordion, + IonAccordionGroup, + IonText, + IonContent, + IonButtons, + IonHeader, + IonToolbar, + IonMenuButton, + IonSearchbar, + IonTitle, + IonBackButton, + IonInfiniteScroll, + IonInfiniteScrollContent, + IonItem, + IonSkeletonText, + IonToast, + IonBadge, + IonCheckbox, + IonFooter, + IonRouterLink, ], providers: [ CoordinatedSearchProvider, diff --git a/frontend/app/src/app/modules/data/debug-data-collector.service.ts b/frontend/app/src/app/modules/data/debug-data-collector.service.ts index 9a40acff..6cbfd533 100644 --- a/frontend/app/src/app/modules/data/debug-data-collector.service.ts +++ b/frontend/app/src/app/modules/data/debug-data-collector.service.ts @@ -14,7 +14,7 @@ */ import {Injectable} from '@angular/core'; import {SCFeedbackRequestMetaData} from '@openstapps/core'; -import {Platform} from '@ionic/angular'; +import {Platform} from '@ionic/angular/standalone'; import {DataProvider} from './data.provider'; import {NavigationEnd, Router} from '@angular/router'; import {SettingsProvider} from '../settings/settings.provider'; diff --git a/frontend/app/src/app/modules/data/detail/data-detail-content.component.ts b/frontend/app/src/app/modules/data/detail/data-detail-content.component.ts index 31e1ac46..fd9ee45d 100644 --- a/frontend/app/src/app/modules/data/detail/data-detail-content.component.ts +++ b/frontend/app/src/app/modules/data/detail/data-detail-content.component.ts @@ -15,7 +15,7 @@ import {Component, Input, TemplateRef} from '@angular/core'; import {SCThings} from '@openstapps/core'; import {DataListContext} from '../list/data-list.component'; -import {ModalController} from '@ionic/angular'; +import {ModalController} from '@ionic/angular/standalone'; /** * TODO diff --git a/frontend/app/src/app/modules/data/detail/data-detail.component.spec.ts b/frontend/app/src/app/modules/data/detail/data-detail.component.spec.ts index 4307ce1d..fb3b7a04 100644 --- a/frontend/app/src/app/modules/data/detail/data-detail.component.spec.ts +++ b/frontend/app/src/app/modules/data/detail/data-detail.component.spec.ts @@ -26,6 +26,7 @@ import {DataDetailComponent} from './data-detail.component'; import {Observable, of} from 'rxjs'; import {StorageProvider} from '../../storage/storage.provider'; import {LoggerModule, NgxLoggerLevel} from 'ngx-logger'; +import {provideIonicAngular} from '@ionic/angular/standalone'; const translations: any = {data: {detail: {TITLE: 'Foo'}}}; @@ -71,6 +72,7 @@ describe('DataDetailComponent', () => { LoggerModule.forRoot({level: NgxLoggerLevel.TRACE}), ], providers: [ + provideIonicAngular(), { provide: ActivatedRoute, useValue: fakeActivatedRoute, diff --git a/frontend/app/src/app/modules/data/detail/data-detail.component.ts b/frontend/app/src/app/modules/data/detail/data-detail.component.ts index 9ac757b4..715cd133 100644 --- a/frontend/app/src/app/modules/data/detail/data-detail.component.ts +++ b/frontend/app/src/app/modules/data/detail/data-detail.component.ts @@ -14,7 +14,7 @@ */ import {Component, ContentChild, EventEmitter, Input, OnInit, Output, TemplateRef} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; -import {ModalController} from '@ionic/angular'; +import {ModalController} from '@ionic/angular/standalone'; import {LangChangeEvent, TranslateService} from '@ngx-translate/core'; import {SCLanguageCode, SCSaveableThing, SCThings, SCUuid} from '@openstapps/core'; import {DataProvider, DataScope} from '../data.provider'; diff --git a/frontend/app/src/app/modules/data/detail/data-path.component.ts b/frontend/app/src/app/modules/data/detail/data-path.component.ts index ccbff453..73e00ad1 100644 --- a/frontend/app/src/app/modules/data/detail/data-path.component.ts +++ b/frontend/app/src/app/modules/data/detail/data-path.component.ts @@ -19,7 +19,7 @@ import {DataProvider, DataScope} from '../data.provider'; import {fromEvent, Observable} from 'rxjs'; import {map, startWith} from 'rxjs/operators'; import {DataRoutingService} from '../data-routing.service'; -import {NavController} from '@ionic/angular'; +import {NavController} from '@ionic/angular/standalone'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; @Component({ diff --git a/frontend/app/src/app/modules/data/elements/favorite-button.component.scss b/frontend/app/src/app/modules/data/elements/favorite-button.component.scss index b0c40b27..60230210 100644 --- a/frontend/app/src/app/modules/data/elements/favorite-button.component.scss +++ b/frontend/app/src/app/modules/data/elements/favorite-button.component.scss @@ -18,7 +18,6 @@ ion-button { --background-hover: currentcolor; --background-focused: currentcolor; - aspect-ratio: 1; color: inherit; } @@ -27,7 +26,7 @@ ion-button { } @media (hover: hover) { - ion-button:hover ::ng-deep stapps-icon { + ion-button:hover > ion-icon { --fill: 1 !important; } } diff --git a/frontend/app/src/app/modules/data/elements/rating.scss b/frontend/app/src/app/modules/data/elements/rating.scss index e83bcf41..2d391ca1 100644 --- a/frontend/app/src/app/modules/data/elements/rating.scss +++ b/frontend/app/src/app/modules/data/elements/rating.scss @@ -15,7 +15,7 @@ ion-button { margin: 0; - &.button-disabled::ng-deep stapps-icon { + &.button-disabled { --fill: 1; } } @@ -39,17 +39,17 @@ ion-button { border-radius: var(--border-radius-default); > ion-icon { - &:active::ng-deep stapps-icon, - &:has(:checked)::ng-deep stapps-icon, - &:has(:checked)::ng-deep ~ *::ng-deep stapps-icon, - &:active::ng-deep ~ *::ng-deep stapps-icon { + &:active, + &:has(:checked), + &:has(:checked) ~ *, + &:active ~ * { --fill: 1; color: var(--ion-color-dark); } @media (hover: hover) { - &:hover ~ *::ng-deep stapps-icon, - &:hover::ng-deep stapps-icon { + &:hover ~ *, + &:hover { --fill: 1; } } diff --git a/frontend/app/src/app/modules/data/elements/share-button.component.ts b/frontend/app/src/app/modules/data/elements/share-button.component.ts index f7fc4890..823ff2fb 100644 --- a/frontend/app/src/app/modules/data/elements/share-button.component.ts +++ b/frontend/app/src/app/modules/data/elements/share-button.component.ts @@ -1,5 +1,5 @@ import {Component, Input} from '@angular/core'; -import {ToastController} from '@ionic/angular'; +import {ToastController} from '@ionic/angular/standalone'; import {environment} from '../../../../environments/environment'; @Component({ diff --git a/frontend/app/src/app/modules/data/list/data-list.component.ts b/frontend/app/src/app/modules/data/list/data-list.component.ts index a261c035..5763a36e 100644 --- a/frontend/app/src/app/modules/data/list/data-list.component.ts +++ b/frontend/app/src/app/modules/data/list/data-list.component.ts @@ -29,7 +29,7 @@ import { } from '@angular/core'; import {SCThings} from '@openstapps/core'; import {BehaviorSubject, Observable} from 'rxjs'; -import {IonInfiniteScroll} from '@ionic/angular'; +import {IonInfiniteScroll} from '@ionic/angular/standalone'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; export interface DataListContext { diff --git a/frontend/app/src/app/modules/data/list/search-page-switch-animation.ts b/frontend/app/src/app/modules/data/list/search-page-switch-animation.ts index e466f9d6..ba802e65 100644 --- a/frontend/app/src/app/modules/data/list/search-page-switch-animation.ts +++ b/frontend/app/src/app/modules/data/list/search-page-switch-animation.ts @@ -13,8 +13,8 @@ * this program. If not, see . */ -import type {AnimationBuilder} from '@ionic/angular'; -import {AnimationController} from '@ionic/angular'; +import type {AnimationBuilder} from '@ionic/angular/standalone'; +import {AnimationController} from '@ionic/angular/standalone'; import type {AnimationOptions} from '@ionic/angular/common/providers/nav-controller'; /** diff --git a/frontend/app/src/app/modules/data/list/search-page.component.ts b/frontend/app/src/app/modules/data/list/search-page.component.ts index 2eb8ebd0..c9dca4b0 100644 --- a/frontend/app/src/app/modules/data/list/search-page.component.ts +++ b/frontend/app/src/app/modules/data/list/search-page.component.ts @@ -15,7 +15,7 @@ import {Component, DestroyRef, inject, Input, OnInit} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {Keyboard} from '@capacitor/keyboard'; -import {AlertController, AnimationBuilder, AnimationController} from '@ionic/angular'; +import {AlertController, AnimationBuilder, AnimationController} from '@ionic/angular/standalone'; import {Capacitor} from '@capacitor/core'; import { SCFacet, diff --git a/frontend/app/src/app/modules/data/types/place/special/mensa/place-mensa-detail.component.ts b/frontend/app/src/app/modules/data/types/place/special/mensa/place-mensa-detail.component.ts index 4a739f5d..e2b43574 100644 --- a/frontend/app/src/app/modules/data/types/place/special/mensa/place-mensa-detail.component.ts +++ b/frontend/app/src/app/modules/data/types/place/special/mensa/place-mensa-detail.component.ts @@ -16,7 +16,7 @@ import {AfterViewInit, Component, DestroyRef, inject, Input} from '@angular/core import {SCDish, SCISO8601Date, SCPlace} from '@openstapps/core'; import {PlaceMensaService} from './place-mensa-service'; import {Router} from '@angular/router'; -import {IonRouterOutlet} from '@ionic/angular'; +import {IonRouterOutlet} from '@ionic/angular/standalone'; import {DataRoutingService} from '../../../../data-routing.service'; import {groupBy} from '@openstapps/collection-utils'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; diff --git a/frontend/app/src/app/modules/favorites/favorites-page.component.ts b/frontend/app/src/app/modules/favorites/favorites-page.component.ts index 167f863a..15a8378d 100644 --- a/frontend/app/src/app/modules/favorites/favorites-page.component.ts +++ b/frontend/app/src/app/modules/favorites/favorites-page.component.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ import {Component, OnInit} from '@angular/core'; -import {AlertController, AnimationController} from '@ionic/angular'; +import {AlertController, AnimationController} from '@ionic/angular/standalone'; import {ActivatedRoute, Router} from '@angular/router'; import {NGXLogger} from 'ngx-logger'; import {debounceTime, distinctUntilChanged, startWith, take} from 'rxjs/operators'; diff --git a/frontend/app/src/app/modules/favorites/favorites.module.ts b/frontend/app/src/app/modules/favorites/favorites.module.ts index e9a69b9f..71997d97 100644 --- a/frontend/app/src/app/modules/favorites/favorites.module.ts +++ b/frontend/app/src/app/modules/favorites/favorites.module.ts @@ -15,14 +15,25 @@ import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; import {FormsModule} from '@angular/forms'; -import {IonicModule} from '@ionic/angular'; import {FavoritesPageComponent} from './favorites-page.component'; import {RouterModule, Routes} from '@angular/router'; import {MenuModule} from '../menu/menu.module'; import {TranslateModule} from '@ngx-translate/core'; import {DataModule} from '../data/data.module'; import {UtilModule} from '../../util/util.module'; -import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; +import { + IonBackButton, + IonButton, + IonButtons, + IonContent, + IonHeader, + IonLabel, + IonMenuButton, + IonSearchbar, + IonTitle, + IonToolbar, +} from '@ionic/angular/standalone'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; const favoritesRoutes: Routes = [ { @@ -35,13 +46,22 @@ const favoritesRoutes: Routes = [ imports: [ CommonModule, FormsModule, - IonicModule, RouterModule.forChild(favoritesRoutes), MenuModule, TranslateModule, DataModule, - IonIconModule, + IonIconDirective, UtilModule, + IonLabel, + IonHeader, + IonToolbar, + IonButtons, + IonContent, + IonButton, + IonMenuButton, + IonSearchbar, + IonTitle, + IonBackButton, ], declarations: [FavoritesPageComponent], }) diff --git a/frontend/app/src/app/modules/feedback/feedback-page.component.ts b/frontend/app/src/app/modules/feedback/feedback-page.component.ts index 51f38360..43b5427c 100644 --- a/frontend/app/src/app/modules/feedback/feedback-page.component.ts +++ b/frontend/app/src/app/modules/feedback/feedback-page.component.ts @@ -23,7 +23,7 @@ import { } from '@openstapps/core'; import {DataProvider} from '../data/data.provider'; import {DebugDataCollectorService} from '../data/debug-data-collector.service'; -import {AlertController, ToastController} from '@ionic/angular'; +import {AlertController, ToastController} from '@ionic/angular/standalone'; import {TranslateService} from '@ngx-translate/core'; @Component({ diff --git a/frontend/app/src/app/modules/feedback/feedback.module.ts b/frontend/app/src/app/modules/feedback/feedback.module.ts index bd3d58ba..0da80952 100644 --- a/frontend/app/src/app/modules/feedback/feedback.module.ts +++ b/frontend/app/src/app/modules/feedback/feedback.module.ts @@ -15,13 +15,30 @@ import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; import {FormsModule} from '@angular/forms'; -import {IonicModule} from '@ionic/angular'; import {FeedbackPageComponent} from './feedback-page.component'; import {RouterModule, Routes} from '@angular/router'; import {TranslateModule} from '@ngx-translate/core'; import {MarkdownModule} from 'ngx-markdown'; import {UtilModule} from '../../util/util.module'; -import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; +import { + IonBackButton, + IonButton, + IonButtons, + IonCard, + IonCardContent, + IonCardTitle, + IonCheckbox, + IonHeader, + IonInput, + IonItem, + IonLabel, + IonSelect, + IonSelectOption, + IonTextarea, + IonTitle, + IonToolbar, +} from '@ionic/angular/standalone'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; const feedbackRoutes: Routes = [ { @@ -34,12 +51,27 @@ const feedbackRoutes: Routes = [ imports: [ CommonModule, FormsModule, - IonicModule, - IonIconModule, + IonIconDirective, RouterModule.forChild(feedbackRoutes), TranslateModule, MarkdownModule, UtilModule, + IonBackButton, + IonCard, + IonCardContent, + IonButton, + IonItem, + IonLabel, + IonCardTitle, + IonCheckbox, + IonTextarea, + IonInput, + IonSelect, + IonSelectOption, + IonTitle, + IonButtons, + IonToolbar, + IonHeader, ], declarations: [FeedbackPageComponent], }) diff --git a/frontend/app/src/app/modules/hebis/daia-availability/daia-availability.component.spec.ts b/frontend/app/src/app/modules/hebis/daia-availability/daia-availability.component.spec.ts index a1fa70a4..4b95cede 100644 --- a/frontend/app/src/app/modules/hebis/daia-availability/daia-availability.component.spec.ts +++ b/frontend/app/src/app/modules/hebis/daia-availability/daia-availability.component.spec.ts @@ -27,6 +27,7 @@ import {StorageProvider} from '../../storage/storage.provider'; import {DaiaDataProvider} from '../daia-data.provider'; import {ConfigProvider} from '../../config/config.provider'; import {LoggerTestingModule} from 'ngx-logger/testing'; +import {provideIonicAngular} from '@ionic/angular/standalone'; const translations: any = {data: {detail: {TITLE: 'Foo'}}}; @@ -74,6 +75,7 @@ describe('DaiaAvailabilityComponent', () => { LoggerTestingModule, ], providers: [ + provideIonicAngular(), { provide: ActivatedRoute, useValue: fakeActivatedRoute, diff --git a/frontend/app/src/app/modules/hebis/daia-availability/daia-holding.scss b/frontend/app/src/app/modules/hebis/daia-availability/daia-holding.scss index c8c8ed5a..9a43f436 100644 --- a/frontend/app/src/app/modules/hebis/daia-availability/daia-holding.scss +++ b/frontend/app/src/app/modules/hebis/daia-availability/daia-holding.scss @@ -37,6 +37,6 @@ ion-grid { } } -ion-icon ::ng-deep stapps-icon { +ion-icon { --fill: 1; } diff --git a/frontend/app/src/app/modules/hebis/hebis-detail/hebis-detail.component.spec.ts b/frontend/app/src/app/modules/hebis/hebis-detail/hebis-detail.component.spec.ts index 05845805..26397055 100644 --- a/frontend/app/src/app/modules/hebis/hebis-detail/hebis-detail.component.spec.ts +++ b/frontend/app/src/app/modules/hebis/hebis-detail/hebis-detail.component.spec.ts @@ -26,9 +26,9 @@ import {HebisDataProvider} from '../hebis-data.provider'; import {HebisDetailComponent} from './hebis-detail.component'; import {Observable, of} from 'rxjs'; import {StorageProvider} from '../../storage/storage.provider'; -import {IonicModule} from '@ionic/angular'; -import {IonIconModule} from '../../../util/ion-icon/ion-icon.module'; import {LoggerModule, NgxLoggerLevel} from 'ngx-logger'; +import {IonIconDirective} from '../../../util/ion-icon/ion-icon.directive'; +import {provideIonicAngular} from '@ionic/angular/standalone'; const translations: any = {data: {detail: {TITLE: 'Foo'}}}; @@ -68,14 +68,14 @@ describe('HebisDetailComponent', () => { RouterModule.forRoot([]), HebisRoutingModule, HebisModule, - IonicModule, - IonIconModule, + IonIconDirective, TranslateModule.forRoot({ loader: {provide: TranslateLoader, useClass: TranslateFakeLoader}, }), LoggerModule.forRoot({level: NgxLoggerLevel.TRACE}), ], providers: [ + provideIonicAngular(), { provide: ActivatedRoute, useValue: fakeActivatedRoute, diff --git a/frontend/app/src/app/modules/hebis/hebis.module.ts b/frontend/app/src/app/modules/hebis/hebis.module.ts index 863bdd9b..35050c9d 100644 --- a/frontend/app/src/app/modules/hebis/hebis.module.ts +++ b/frontend/app/src/app/modules/hebis/hebis.module.ts @@ -17,7 +17,6 @@ import {CommonModule} from '@angular/common'; import {HttpClientModule} from '@angular/common/http'; import {NgModule} from '@angular/core'; import {FormsModule} from '@angular/forms'; -import {IonicModule} from '@ionic/angular'; import {TranslateModule} from '@ngx-translate/core'; import {MarkdownModule} from 'ngx-markdown'; import {MomentModule} from 'ngx-moment'; @@ -34,8 +33,27 @@ import {HebisRoutingModule} from './hebis-routing.module'; import {DataModule} from '../data/data.module'; import {DaiaAvailabilityComponent} from './daia-availability/daia-availability.component'; import {UtilModule} from '../../util/util.module'; -import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; import {DaiaHoldingComponent} from './daia-availability/daia-holding.component'; +import { + IonBackButton, + IonButton, + IonButtons, + IonCard, + IonCardContent, + IonCardHeader, + IonCol, + IonContent, + IonGrid, + IonHeader, + IonItem, + IonLabel, + IonNote, + IonRow, + IonThumbnail, + IonTitle, + IonToolbar, +} from '@ionic/angular/standalone'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; /** * Module for handling data @@ -53,9 +71,8 @@ import {DaiaHoldingComponent} from './daia-availability/daia-holding.component'; DataModule, FormsModule, HebisRoutingModule, - IonIconModule, + IonIconDirective, HttpClientModule, - IonicModule.forRoot(), MarkdownModule.forRoot(), MenuModule, MomentModule.forRoot({ @@ -68,6 +85,23 @@ import {DaiaHoldingComponent} from './daia-availability/daia-holding.component'; TranslateModule.forChild(), ThingTranslateModule.forChild(), UtilModule, + IonBackButton, + IonLabel, + IonButton, + IonContent, + IonButtons, + IonTitle, + IonToolbar, + IonNote, + IonHeader, + IonGrid, + IonRow, + IonCol, + IonCard, + IonCardContent, + IonCardHeader, + IonItem, + IonThumbnail, ], providers: [HebisDataProvider, DaiaDataProvider, StAppsWebHttpClient], }) diff --git a/frontend/app/src/app/modules/jobs/jobs.module.ts b/frontend/app/src/app/modules/jobs/jobs.module.ts index 5d00f5be..ab77fb96 100644 --- a/frontend/app/src/app/modules/jobs/jobs.module.ts +++ b/frontend/app/src/app/modules/jobs/jobs.module.ts @@ -1,25 +1,23 @@ import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; -import {IonicModule} from '@ionic/angular'; import {TranslateModule} from '@ngx-translate/core'; import {MomentModule} from 'ngx-moment'; import {DataModule} from '../data/data.module'; import {UtilModule} from '../../util/util.module'; -import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; import {ThingTranslateModule} from '../../translation/thing-translate.module'; import {RouterModule, Routes} from '@angular/router'; import {JobsPageComponent} from './page/jobs-page.component'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; const jobsRoutes: Routes = [{path: 'jobs', component: JobsPageComponent}]; @NgModule({ declarations: [JobsPageComponent], imports: [ - IonicModule.forRoot(), ThingTranslateModule.forChild(), TranslateModule.forChild(), RouterModule.forChild(jobsRoutes), - IonIconModule, + IonIconDirective, CommonModule, MomentModule, DataModule, diff --git a/frontend/app/src/app/modules/library/account/library-account.service.ts b/frontend/app/src/app/modules/library/account/library-account.service.ts index b316f039..0c5cd458 100644 --- a/frontend/app/src/app/modules/library/account/library-account.service.ts +++ b/frontend/app/src/app/modules/library/account/library-account.service.ts @@ -34,7 +34,7 @@ import {PAIATokenResponse} from '../../auth/paia/paia-token-response'; import {AuthHelperService} from '../../auth/auth-helper.service'; import {ConfigProvider} from '../../config/config.provider'; import {TranslateService} from '@ngx-translate/core'; -import {AlertController, ToastController} from '@ionic/angular'; +import {AlertController, ToastController} from '@ionic/angular/standalone'; import {HebisSearchResponse} from '../../hebis/protocol/response'; @Injectable({ diff --git a/frontend/app/src/app/modules/library/library.module.ts b/frontend/app/src/app/modules/library/library.module.ts index 8cef1d92..8f778563 100644 --- a/frontend/app/src/app/modules/library/library.module.ts +++ b/frontend/app/src/app/modules/library/library.module.ts @@ -16,7 +16,6 @@ import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; import {FormsModule} from '@angular/forms'; -import {IonicModule} from '@ionic/angular'; import {RouterModule, Routes} from '@angular/router'; import {TranslateModule} from '@ngx-translate/core'; import {LibraryAccountPageComponent} from './account/account.page'; @@ -32,7 +31,28 @@ import {MomentModule} from 'ngx-moment'; import {FeeItemComponent} from './account/elements/fee-item/fee-item.component'; import {DataModule} from '../data/data.module'; import {UtilModule} from '../../util/util.module'; -import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; +import { + IonHeader, + IonToolbar, + IonButtons, + IonBackButton, + IonTitle, + IonContent, + IonSkeletonText, + IonItem, + IonGrid, + IonCol, + IonRow, + IonLabel, + IonCard, + IonCardContent, + IonList, + IonSegment, + IonSegmentButton, + IonButton, + IonBadge, +} from '@ionic/angular/standalone'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; const routes: ProtectedRoutes | Routes = [ { @@ -71,13 +91,31 @@ const routes: ProtectedRoutes | Routes = [ imports: [ CommonModule, FormsModule, - IonicModule, - IonIconModule, + IonIconDirective, RouterModule.forChild(routes), TranslateModule, MomentModule, DataModule, UtilModule, + IonHeader, + IonBadge, + IonToolbar, + IonButtons, + IonBackButton, + IonTitle, + IonContent, + IonSkeletonText, + IonItem, + IonGrid, + IonCol, + IonRow, + IonLabel, + IonCard, + IonCardContent, + IonList, + IonSegment, + IonSegmentButton, + IonButton, ], declarations: [ LibraryAccountPageComponent, diff --git a/frontend/app/src/app/modules/map/controls/attribution.component.ts b/frontend/app/src/app/modules/map/controls/attribution.component.ts index 7c5186b2..235c7407 100644 --- a/frontend/app/src/app/modules/map/controls/attribution.component.ts +++ b/frontend/app/src/app/modules/map/controls/attribution.component.ts @@ -1,10 +1,10 @@ import {animate, style, transition, trigger} from '@angular/animations'; import {AsyncPipe} from '@angular/common'; import {ChangeDetectionStrategy, Component, Input, inject} from '@angular/core'; -import {IonicModule} from '@ionic/angular'; +import {IonButton} from '@ionic/angular/standalone'; import {MapService} from '@maplibre/ngx-maplibre-gl'; import {map, delay, Subject, race, mergeWith} from 'rxjs'; -import {IonIconModule} from 'src/app/util/ion-icon/ion-icon.module'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; @Component({ selector: 'stapps-map-attribution', @@ -12,7 +12,7 @@ import {IonIconModule} from 'src/app/util/ion-icon/ion-icon.module'; styleUrl: './attribution.scss', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, - imports: [IonicModule, IonIconModule, AsyncPipe], + imports: [IonIconDirective, AsyncPipe, IonButton], animations: [ trigger('fade', [ transition(':enter', [ diff --git a/frontend/app/src/app/modules/map/controls/compass-control.component.ts b/frontend/app/src/app/modules/map/controls/compass-control.component.ts index 9a931ba3..ab99118b 100644 --- a/frontend/app/src/app/modules/map/controls/compass-control.component.ts +++ b/frontend/app/src/app/modules/map/controls/compass-control.component.ts @@ -1,10 +1,10 @@ import {AsyncPipe} from '@angular/common'; import {ChangeDetectionStrategy, Component} from '@angular/core'; -import {IonicModule} from '@ionic/angular'; +import {IonFabButton} from '@ionic/angular/standalone'; import {MapService} from '@maplibre/ngx-maplibre-gl'; import {MapEventType} from 'maplibre-gl'; import {map, mergeMap, fromEventPattern, merge} from 'rxjs'; -import {IonIconModule} from 'src/app/util/ion-icon/ion-icon.module'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; @Component({ selector: 'stapps-compass-control', @@ -12,7 +12,7 @@ import {IonIconModule} from 'src/app/util/ion-icon/ion-icon.module'; styleUrl: './compass-control.scss', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, - imports: [AsyncPipe, IonicModule, IonIconModule], + imports: [AsyncPipe, IonIconDirective, IonFabButton], }) export class CompassControlComponent { transform = this.mapService.mapCreated$.pipe( diff --git a/frontend/app/src/app/modules/map/controls/geolocate-control.component.ts b/frontend/app/src/app/modules/map/controls/geolocate-control.component.ts index 98b955d9..89a15f1f 100644 --- a/frontend/app/src/app/modules/map/controls/geolocate-control.component.ts +++ b/frontend/app/src/app/modules/map/controls/geolocate-control.component.ts @@ -8,12 +8,12 @@ import { OnDestroy, ViewChild, } from '@angular/core'; -import {IonicModule} from '@ionic/angular'; +import {IonFabButton} from '@ionic/angular/standalone'; import {MapService} from '@maplibre/ngx-maplibre-gl'; import {FitBoundsOptions, GeolocateControl, GeolocateControlOptions} from 'maplibre-gl'; import {Map as MapLibre} from 'maplibre-gl'; import {BehaviorSubject} from 'rxjs'; -import {IonIconModule} from 'src/app/util/ion-icon/ion-icon.module'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; type WatchState = InstanceType['_watchState']; @@ -52,7 +52,7 @@ class CustomGeolocateControl extends GeolocateControl { styleUrl: './geolocate-control.scss', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, - imports: [AsyncPipe, IonicModule, IonIconModule], + imports: [AsyncPipe, IonIconDirective, IonFabButton], }) export class GeolocateControlComponent implements AfterContentInit, OnDestroy { @Input() position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; diff --git a/frontend/app/src/app/modules/map/elements/poi-marker.component.ts b/frontend/app/src/app/modules/map/elements/poi-marker.component.ts index e4ad1132..ec7dfc85 100644 --- a/frontend/app/src/app/modules/map/elements/poi-marker.component.ts +++ b/frontend/app/src/app/modules/map/elements/poi-marker.component.ts @@ -1,12 +1,12 @@ import {ChangeDetectionStrategy, Component, HostBinding, Input, OnInit, Optional} from '@angular/core'; -import {IonicModule} from '@ionic/angular'; -import {IonIconModule} from 'src/app/util/ion-icon/ion-icon.module'; import {MapIconDirective} from '../map-icon.directive'; import {Feature, Point} from 'geojson'; import {SCFeatureProperties} from '../feature-collection.pipe'; import {MapDataProvider} from '../map-data.provider'; import {DataRoutingService} from '../../data/data-routing.service'; import {AddWordBreakOpportunitiesPipe} from '../../../util/word-break-opportunities.pipe'; +import {IonButton, IonLabel} from '@ionic/angular/standalone'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; @Component({ selector: 'stapps-poi-marker', @@ -14,7 +14,7 @@ import {AddWordBreakOpportunitiesPipe} from '../../../util/word-break-opportunit styleUrl: './poi-marker.scss', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, - imports: [IonicModule, IonIconModule, MapIconDirective, AddWordBreakOpportunitiesPipe], + imports: [IonIconDirective, MapIconDirective, AddWordBreakOpportunitiesPipe, IonLabel, IonButton], }) export class PoiMarkerComponent implements OnInit { @Input({required: true}) feature: Feature; diff --git a/frontend/app/src/app/modules/map/geo-navigation.directive.ts b/frontend/app/src/app/modules/map/geo-navigation.directive.ts index e12eabdd..7bea13b8 100644 --- a/frontend/app/src/app/modules/map/geo-navigation.directive.ts +++ b/frontend/app/src/app/modules/map/geo-navigation.directive.ts @@ -1,7 +1,7 @@ import {Directive, HostListener, Input} from '@angular/core'; import {SCPlaceWithoutReferences, SCThings, SCThingWithoutReferences} from '@openstapps/core'; import {Device} from '@capacitor/device'; -import {ActionSheetController, ActionSheetOptions, ToastController} from '@ionic/angular'; +import {ActionSheetController, ActionSheetOptions, ToastController} from '@ionic/angular/standalone'; import {TranslateService} from '@ngx-translate/core'; import {ThingTranslateService} from '../../translation/thing-translate.service'; import {Clipboard} from '@capacitor/clipboard'; diff --git a/frontend/app/src/app/modules/map/map-maximize-animation.ts b/frontend/app/src/app/modules/map/map-maximize-animation.ts index 46ee5f53..5fd297fa 100644 --- a/frontend/app/src/app/modules/map/map-maximize-animation.ts +++ b/frontend/app/src/app/modules/map/map-maximize-animation.ts @@ -12,8 +12,8 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import type {AnimationBuilder} from '@ionic/angular'; -import {AnimationController} from '@ionic/angular'; +import type {AnimationBuilder} from '@ionic/angular/standalone'; +import {AnimationController} from '@ionic/angular/standalone'; import type {AnimationOptions} from '@ionic/angular/common/providers/nav-controller'; import {iosDuration, iosEasing, mdDuration, mdEasing} from 'src/app/animation/easings'; diff --git a/frontend/app/src/app/modules/map/map-page.component.ts b/frontend/app/src/app/modules/map/map-page.component.ts index 81d6c939..a9db54df 100644 --- a/frontend/app/src/app/modules/map/map-page.component.ts +++ b/frontend/app/src/app/modules/map/map-page.component.ts @@ -13,7 +13,6 @@ * this program. If not, see . */ import {ChangeDetectionStrategy, Component} from '@angular/core'; -import {IonicModule} from '@ionic/angular'; import {LngLatBoundsLike, MapLibreEvent} from 'maplibre-gl'; import { ControlComponent, @@ -28,7 +27,6 @@ import {MediaQueryPipe} from '../../util/media-query.pipe'; import {MapStyleDirective} from './map-style.directive'; import {DataProvider} from '../data/data.provider'; import {SCSearchFilter, SCThingType} from '@openstapps/core'; -import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; import {DataModule} from '../data/data.module'; import {AsyncPipe} from '@angular/common'; import {GeolocateControlComponent} from './controls/geolocate-control.component'; @@ -40,6 +38,8 @@ import {BuildingMarkersComponent} from './elements/building-markers.component'; import {PoiMarkersComponent} from './elements/poi-markers.component'; import {AttributionComponent} from './controls/attribution.component'; import {filter, map} from 'rxjs'; +import {IonButton, IonContent, IonLabel, IonRouterLink} from '@ionic/angular/standalone'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; /** * The main page of the map @@ -65,8 +65,7 @@ import {filter, map} from 'rxjs'; DataModule, GeolocateControlComponent, GeolocateControlDirective, - IonIconModule, - IonicModule, + IonIconDirective, MapAuto3dDirective, MapComponent, MapSizeFixDirective, @@ -78,6 +77,10 @@ import {filter, map} from 'rxjs'; ThingPoiFeatureCollectionPipe, ThingPolygonFeatureCollectionPipe, TranslateModule, + IonContent, + IonLabel, + IonRouterLink, + IonButton, ], }) export class MapPageComponent { diff --git a/frontend/app/src/app/modules/map/map-widget.component.ts b/frontend/app/src/app/modules/map/map-widget.component.ts index 675d1788..62edff57 100644 --- a/frontend/app/src/app/modules/map/map-widget.component.ts +++ b/frontend/app/src/app/modules/map/map-widget.component.ts @@ -15,11 +15,10 @@ import {ChangeDetectionStrategy, Component, HostBinding, Input, inject} from '@angular/core'; import {RouterLink} from '@angular/router'; import {ControlComponent, MapComponent, MarkerComponent} from '@maplibre/ngx-maplibre-gl'; -import {AnimationController, IonicModule} from '@ionic/angular'; +import {AnimationController, IonRouterLink} from '@ionic/angular/standalone'; import {GeoNavigationDirective} from './geo-navigation.directive'; import {TranslateModule} from '@ngx-translate/core'; import {CommonModule} from '@angular/common'; -import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; import {MapAuto3dDirective} from './map-auto-3d.directive'; import {MediaQueryPipe} from 'src/app/util/media-query.pipe'; import {MapStyleDirective} from './map-style.directive'; @@ -31,6 +30,7 @@ import {BuildingMarkersComponent} from './elements/building-markers.component'; import {ThingBoundsPipe} from './thing-bounds.pipe'; import {AttributionComponent} from './controls/attribution.component'; import {mapMaximizeAnimation} from './map-maximize-animation'; +import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; /** * The map widget (needs a container with explicit size) @@ -47,8 +47,7 @@ import {mapMaximizeAnimation} from './map-maximize-animation'; CommonModule, ControlComponent, GeoNavigationDirective, - IonIconModule, - IonicModule, + IonIconDirective, MapAuto3dDirective, MapComponent, MapSizeFixDirective, @@ -61,6 +60,7 @@ import {mapMaximizeAnimation} from './map-maximize-animation'; ThingPoiFeatureCollectionPipe, ThingPolygonFeatureCollectionPipe, TranslateModule, + IonRouterLink, ], }) export class MapWidgetComponent { diff --git a/frontend/app/src/app/modules/menu/context/context-menu.component.spec.ts b/frontend/app/src/app/modules/menu/context/context-menu.component.spec.ts index 58d2e78c..1808a04a 100644 --- a/frontend/app/src/app/modules/menu/context/context-menu.component.spec.ts +++ b/frontend/app/src/app/modules/menu/context/context-menu.component.spec.ts @@ -17,7 +17,6 @@ import {APP_BASE_HREF, CommonModule, Location, LocationStrategy, PathLocationStr import {ComponentFixture, TestBed} from '@angular/core/testing'; import {FormsModule} from '@angular/forms'; import {ChildrenOutletContexts, RouterModule, UrlSerializer} from '@angular/router'; -import {IonicModule} from '@ionic/angular'; import {TranslateModule} from '@ngx-translate/core'; import {SCFacet, SCThingType} from '@openstapps/core'; import {ContextMenuComponent} from './context-menu.component'; @@ -26,6 +25,7 @@ import {ContextMenuService} from './context-menu.service'; import {FilterContext, SortContext} from './context-type'; import {Component} from '@angular/core'; import {By} from '@angular/platform-browser'; +import {provideIonicAngular} from '@ionic/angular/standalone'; @Component({ template: ` `, @@ -40,6 +40,7 @@ describe('ContextMenuComponent', async () => { TestBed.configureTestingModule({ declarations: [ContextMenuComponent, ContextMenuContainerComponent], providers: [ + provideIonicAngular(), ChildrenOutletContexts, Location, UrlSerializer, @@ -49,7 +50,6 @@ describe('ContextMenuComponent', async () => { ], imports: [ FormsModule, - IonicModule.forRoot(), TranslateModule.forRoot(), CommonModule, SettingsModule, diff --git a/frontend/app/src/app/modules/menu/context/context-menu.html b/frontend/app/src/app/modules/menu/context/context-menu.html index bbe3ff35..2986d7d6 100644 --- a/frontend/app/src/app/modules/menu/context/context-menu.html +++ b/frontend/app/src/app/modules/menu/context/context-menu.html @@ -50,7 +50,7 @@ @if (filterOption) { -
+
{{ 'menu.context.filter.title' | translate | titlecase }} @@ -80,6 +80,7 @@ ([ + [SCIcon.arrow_back, SCIcon.arrow_back_ios], + [SCIcon.arrow_forward, SCIcon.arrow_forward_ios], + [SCIcon.share, SCIcon.ios_share], +]); + +/** + * Maps hardcoded icon SVGs to our icon names. + * Thanks, Ionic. + */ +const iconMap = new Map([ + [arrowBackOutline, SCIcon.arrow_back], + [chevronBackOutline, SCIcon.arrow_back], + [chevronForwardOutline, SCIcon.arrow_forward], + [menu, SCIcon.menu], + [menuSharp, SCIcon.menu], + [searchOutline, SCIcon.search], + [searchSharp, SCIcon.search], + [chevronExpand, SCIcon.expand_more], + [caretDownSharp, SCIcon.expand_more], + [close, SCIcon.close], + [closeSharp, SCIcon.close], + [closeCircle, SCIcon.cancel], + [ellipsisHorizontal, SCIcon.more_horiz], + ['chevron-down-outline', SCIcon.expand_more], + ['arrow_back', SCIcon.arrow_back], +]); diff --git a/frontend/app/src/app/util/ion-icon/ion-icon.directive.ts b/frontend/app/src/app/util/ion-icon/ion-icon.directive.ts index d2884600..f47dd774 100644 --- a/frontend/app/src/app/util/ion-icon/ion-icon.directive.ts +++ b/frontend/app/src/app/util/ion-icon/ion-icon.directive.ts @@ -13,121 +13,37 @@ * this program. If not, see . */ -import { - ComponentRef, - Directive, - ElementRef, - Host, - Input, - OnChanges, - OnDestroy, - OnInit, - Optional, - Self, - ViewContainerRef, -} from '@angular/core'; -import {IconComponent} from './icon.component'; -import {IonIcon} from '@ionic/angular'; -import {MaterialSymbol} from 'material-symbols'; - -// eslint-disable-next-line @typescript-eslint/no-empty-function -const noop = () => {}; -const noopProperty = { - set: noop, - get: noop, -}; +import {Directive, ElementRef, Input} from '@angular/core'; +import {IonIconCustomElement} from './ion-icon-custom-component'; @Directive({ selector: 'ion-icon', + standalone: true, }) -export class IonIconDirective implements OnInit, OnDestroy, OnChanges { - @Input() name: MaterialSymbol; - - @Input() md: string; - - @Input() ios: string; - - @Input() fill: boolean; - - @Input() weight: number; - - @Input() size: number | 'small' | 'large'; - - @Input() grade: number; - - @Input() style: string; - - private mutationObserver: MutationObserver; - - iconComponent?: ComponentRef; - - private get mode(): 'md' | 'ios' { - return document.querySelector(':root')?.getAttribute('mode') as 'md' | 'ios'; +export class IonIconDirective { + @Input({required: true}) set name(value: IonIconCustomElement['name']) { + this.elementRef.nativeElement.name = value; } - constructor( - private element: ElementRef, - private viewContainerRef: ViewContainerRef, - @Host() @Self() @Optional() private ionIcon: IonIcon, - ) {} - - ngOnInit() { - this.iconComponent = this.viewContainerRef.createComponent(IconComponent, {}); - - this.element.nativeElement.insertBefore( - this.iconComponent.location.nativeElement, - this.element.nativeElement.firstChild, - ); - - this.mutationObserver = new MutationObserver(() => { - const inner = this.element.nativeElement.shadowRoot.querySelector('.icon-inner'); - if (!inner) return; - - inner.insertBefore(document.createElement('slot'), inner.firstChild); - }); - this.mutationObserver.observe(this.element.nativeElement.shadowRoot, { - childList: true, - }); - - this.ngOnChanges(); - // this will effectively completely disable the ion-icon component - for (const name of ['src', 'name', 'icon', 'md', 'ios']) { - this.disableProperty(name); - } + @Input() set size(value: IonIconCustomElement['size']) { + this.elementRef.nativeElement.size = value; } - ngOnDestroy() { - this.mutationObserver.disconnect(); + @Input() set color(value: IonIconCustomElement['color']) { + this.elementRef.nativeElement.color = value; } - ngOnChanges() { - if (!this.iconComponent) return; - - this.iconComponent.setInput('fill', this.fill === true ? 1 : this.fill === false ? 0 : this.fill); - this.iconComponent.setInput('weight', this.weight); - this.iconComponent.setInput('grade', this.grade); - - if (this.mode === 'ios') { - this.iconComponent.setInput('name', this.ios || this.name); - } else { - this.iconComponent.setInput('name', this.md || this.name); - } - - if (this.size) { - const size = this.size === 'small' ? 16 : this.size === 'large' ? 24 : this.size; - this.element.nativeElement.style.fontSize = `${size}px`; - } - - if (this.style) { - this.element.nativeElement.style.cssText += this.style; - } + @Input() set fill(value: IonIconCustomElement['fill']) { + this.elementRef.nativeElement.fill = value; } - disableProperty(name: string) { - Object.defineProperty( - Object.getPrototypeOf((this.ionIcon as unknown as {el: HTMLElement}).el), - name, - noopProperty, - ); + @Input() set weight(value: IonIconCustomElement['weight']) { + this.elementRef.nativeElement.weight = value; } + + @Input() set grade(value: IonIconCustomElement['grade']) { + this.elementRef.nativeElement.grade = value; + } + + constructor(private elementRef: ElementRef) {} } diff --git a/frontend/app/src/app/util/ion-icon/ion-icon.module.ts b/frontend/app/src/app/util/ion-icon/ion-icon.module.ts deleted file mode 100644 index b5395c38..00000000 --- a/frontend/app/src/app/util/ion-icon/ion-icon.module.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -import {NgModule} from '@angular/core'; -import {IconComponent} from './icon.component'; -import {IonIconDirective} from './ion-icon.directive'; -import {IonBackButtonDirective} from './ion-back-button.directive'; -import {IonSearchbarDirective} from './ion-searchbar.directive'; -import {IonBreadcrumbDirective} from './ion-breadcrumb.directive'; -import {IonReorderDirective} from './ion-reorder.directive'; -import {TranslateModule, TranslateService} from '@ngx-translate/core'; -import {CommonModule, TitleCasePipe} from '@angular/common'; - -@NgModule({ - imports: [TranslateModule, CommonModule], - declarations: [ - IconComponent, - IonIconDirective, - IonBackButtonDirective, - IonSearchbarDirective, - IonBreadcrumbDirective, - IonReorderDirective, - ], - exports: [ - IonIconDirective, - IonReorderDirective, - IonBackButtonDirective, - IonSearchbarDirective, - IonBreadcrumbDirective, - ], - providers: [TranslateService, TitleCasePipe], -}) -export class IonIconModule {} diff --git a/frontend/app/src/app/util/ion-icon/ion-reorder.directive.ts b/frontend/app/src/app/util/ion-icon/ion-reorder.directive.ts deleted file mode 100644 index d53a8463..00000000 --- a/frontend/app/src/app/util/ion-icon/ion-reorder.directive.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ -import {Directive, ElementRef, ViewContainerRef} from '@angular/core'; -import {SCIcon} from './icon'; -import {IconReplacer} from './replace-util'; - -@Directive({ - selector: 'ion-reorder', -}) -export class IonReorderDirective extends IconReplacer { - constructor(element: ElementRef, viewContainerRef: ViewContainerRef) { - super(element, viewContainerRef, 'shadow'); - } - - replace() { - this.replaceIcon(this.host, { - name: SCIcon.reorder, - size: 24, - }); - } -} diff --git a/frontend/app/src/app/util/ion-icon/ion-searchbar.directive.ts b/frontend/app/src/app/util/ion-icon/ion-searchbar.directive.ts deleted file mode 100644 index eef39ce8..00000000 --- a/frontend/app/src/app/util/ion-icon/ion-searchbar.directive.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ -import {Directive, ElementRef, ViewContainerRef} from '@angular/core'; -import {SCIcon} from './icon'; -import {IconReplacer} from './replace-util'; - -@Directive({ - selector: 'ion-searchbar', -}) -export class IonSearchbarDirective extends IconReplacer { - constructor(element: ElementRef, viewContainerRef: ViewContainerRef) { - super(element, viewContainerRef, 'light'); - } - - replace() { - this.replaceIcon(this.host.querySelector('.searchbar-input-container'), { - name: SCIcon.search, - size: 24, - }); - this.replaceIcon(this.host.querySelector('.searchbar-clear-button'), { - name: SCIcon.close, - size: 24, - }); - } -} diff --git a/frontend/app/src/app/util/ion-icon/replace-util.ts b/frontend/app/src/app/util/ion-icon/replace-util.ts deleted file mode 100644 index 5dd03d32..00000000 --- a/frontend/app/src/app/util/ion-icon/replace-util.ts +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -import {ComponentRef, Directive, ElementRef, OnDestroy, OnInit, ViewContainerRef} from '@angular/core'; -import {IonIcon} from '@ionic/angular'; -import {IonIconDirective} from './ion-icon.directive'; -import {waitForElement} from './shadow-attacher'; - -export type IconData = Omit< - Partial, - 'ngOnChanges' | 'ngOnInit' | 'viewContainerRef' | 'ngOnDestroy' | 'element' | 'ionIcon' | 'disableProperty' ->; - -/** - * A utility class to replace ion-icons in other ionic components. - */ -@Directive() -export abstract class IconReplacer implements OnInit, OnDestroy { - private mutationObserver: MutationObserver; - - protected slotName = 'sc-icon'; - - protected maxAttempts = 10; - - protected retryAfterMs = 10; - - /** - * The host element - * - * This will be either element.nativeElement.shadowRoot or element.nativeElement - * depending on the iconDomLocation - */ - protected get host() { - return this.iconDomLocation === 'shadow' - ? this.element.nativeElement.shadowRoot - : this.element.nativeElement; - } - - /** - * @param element The host element - * @param viewContainerRef The view container ref - * @param iconDomLocation If the icon is placed inside the shadow dom or not - * @protected - */ - protected constructor( - private readonly element: ElementRef, - private readonly viewContainerRef: ViewContainerRef, - private readonly iconDomLocation: 'shadow' | 'light', - ) {} - - /** - * Replace the icons here - */ - abstract replace(): void; - - async ngOnInit() { - if (this.host) { - this.attachObserver(); - } else { - console.warn("Shadow root didn't exist for ion icon replacer, retrying..."); - await waitForElement(() => this.host); - this.replace(); - } - } - - private attachObserver() { - this.mutationObserver = new MutationObserver(() => this.replace()); - this.mutationObserver.observe(this.host, { - childList: true, - }); - } - - replaceIcon(parent: HTMLElement | null, iconData: IconData, slotName = '') { - if (!parent) return; - - const icon = parent.querySelector('ion-icon'); - if (!icon) return; - - const scIcon = this.createIcon(iconData); - // @ts-expect-error can be spread - scIcon.location.nativeElement.classList.add(...icon.classList); - - if (this.iconDomLocation === 'shadow') { - // shadow dom needs to utilize slotting, to put it outside the shadow dom - // otherwise it won't receive any css data - const slot = document.createElement('slot'); - slot.name = this.slotName + slotName; - icon.replaceWith(slot); - - scIcon.location.nativeElement.slot = this.slotName + slotName; - this.element.nativeElement.append(scIcon.location.nativeElement); - } else { - icon.replaceWith(scIcon.location.nativeElement); - } - } - - private createIcon(iconData: IconData): ComponentRef { - const ionIcon = this.viewContainerRef.createComponent(IonIcon, {}); - const iconDirective = new IonIconDirective(ionIcon.location, this.viewContainerRef, ionIcon.instance); - for (const key in iconData) { - // @ts-expect-error type mismatch - iconDirective[key] = iconData[key]; - } - iconDirective.ngOnInit(); - - return ionIcon; - } - - ngOnDestroy() { - this.mutationObserver?.disconnect(); - } -} diff --git a/frontend/app/src/app/util/pending-changes-action-sheet.ts b/frontend/app/src/app/util/pending-changes-action-sheet.ts index 37cbce5a..addf8548 100644 --- a/frontend/app/src/app/util/pending-changes-action-sheet.ts +++ b/frontend/app/src/app/util/pending-changes-action-sheet.ts @@ -14,7 +14,7 @@ */ import {TranslatePipe} from '@ngx-translate/core'; -import {ActionSheetOptions, AlertOptions} from '@ionic/angular'; +import {ActionSheetOptions, AlertOptions} from '@ionic/angular/standalone'; export enum PendingChangesRole { SAVE = 'save', diff --git a/frontend/app/src/app/util/searchbar-autofocus.directive.ts b/frontend/app/src/app/util/searchbar-autofocus.directive.ts index 39ddae79..053b277f 100644 --- a/frontend/app/src/app/util/searchbar-autofocus.directive.ts +++ b/frontend/app/src/app/util/searchbar-autofocus.directive.ts @@ -14,7 +14,7 @@ */ import {AfterViewInit, Directive, ElementRef, Input} from '@angular/core'; -import {IonSearchbar} from '@ionic/angular'; +import {IonSearchbar} from '@ionic/angular/standalone'; @Directive({ selector: 'ion-searchbar[autofocus]', diff --git a/frontend/app/src/app/util/section.component.ts b/frontend/app/src/app/util/section.component.ts index d4eb7b40..d57863f5 100644 --- a/frontend/app/src/app/util/section.component.ts +++ b/frontend/app/src/app/util/section.component.ts @@ -40,7 +40,7 @@ function isSlideVisible( @Component({ selector: 'stapps-section', templateUrl: 'section.html', - styleUrls: ['section.scss'], + styleUrl: 'section.scss', changeDetection: ChangeDetectionStrategy.OnPush, }) export class SectionComponent implements AfterContentInit { diff --git a/frontend/app/src/app/util/util.module.ts b/frontend/app/src/app/util/util.module.ts index aec72aaf..0626d55d 100644 --- a/frontend/app/src/app/util/util.module.ts +++ b/frontend/app/src/app/util/util.module.ts @@ -20,7 +20,6 @@ import {DaytimeKeyPipe} from './daytime-key.pipe'; import {LazyPipe} from './lazy.pipe'; import {NextDateInListPipe} from './next-date-in-list.pipe'; import {EditModalComponent} from './edit-modal.component'; -import {IonicModule} from '@ionic/angular'; import {TranslateModule} from '@ngx-translate/core'; import {ElementSizeChangeDirective} from './element-size-change.directive'; import {OpeningHoursComponent} from './opening-hours.component'; @@ -32,16 +31,41 @@ import {RouterModule} from '@angular/router'; import {IonContentParallaxDirective} from './ion-content-parallax.directive'; import {FormatDistanceToNowStrictPipeModule, FormatRelativeToNowPipeModule} from 'ngx-date-fns'; import {CommonModule} from '@angular/common'; +import { + IonBadge, + IonButton, + IonButtons, + IonCol, + IonGrid, + IonHeader, + IonLabel, + IonModal, + IonRow, + IonTitle, + IonToolbar, +} from '@ionic/angular/standalone'; +import {IonIconDirective} from './ion-icon/ion-icon.directive'; @NgModule({ imports: [ CommonModule, - IonicModule, TranslateModule, ThingTranslateModule.forChild(), RouterModule, FormatRelativeToNowPipeModule, FormatDistanceToNowStrictPipeModule, + IonIconDirective, + IonGrid, + IonRow, + IonCol, + IonButton, + IonLabel, + IonBadge, + IonButtons, + IonTitle, + IonToolbar, + IonHeader, + IonModal, ], declarations: [ IonContentParallaxDirective, diff --git a/frontend/app/src/global.scss b/frontend/app/src/global.scss index af853d92..fcfa0021 100644 --- a/frontend/app/src/global.scss +++ b/frontend/app/src/global.scss @@ -14,19 +14,19 @@ */ // http://ionicframework.com/docs/theming/ -@import '~@ionic/angular/css/normalize.css'; -@import '~@ionic/angular/css/structure.css'; -@import '~@ionic/angular/css/typography.css'; -@import '~@ionic/angular/css/core.css'; +@import '@ionic/angular/css/normalize.css'; +@import '@ionic/angular/css/structure.css'; +@import '@ionic/angular/css/typography.css'; +@import '@ionic/angular/css/core.css'; -@import '~@ionic/angular/css/padding.css'; -@import '~@ionic/angular/css/float-elements.css'; -@import '~@ionic/angular/css/text-alignment.css'; -@import '~@ionic/angular/css/text-transformation.css'; -@import '~@ionic/angular/css/flex-utils.css'; -@import '~@ionic/angular/css/display.css'; +@import '@ionic/angular/css/padding.css'; +@import '@ionic/angular/css/float-elements.css'; +@import '@ionic/angular/css/text-alignment.css'; +@import '@ionic/angular/css/text-transformation.css'; +@import '@ionic/angular/css/flex-utils.css'; +@import '@ionic/angular/css/display.css'; -@import '~maplibre-gl/dist/maplibre-gl.css'; +@import 'maplibre-gl/dist/maplibre-gl.css'; @import 'swiper/scss'; @import 'swiper/scss/controller'; @@ -59,13 +59,6 @@ @import './theme/variables'; -stapps-icon { - --size-unit: 1px; - --weight: 400; - --grade: 0; - --fill: 0; -} - .add-event-popover { --width: fit-content; --max-width: 95%; diff --git a/frontend/app/src/ion-icons.ts b/frontend/app/src/ion-icons.ts new file mode 100644 index 00000000..19898a3e --- /dev/null +++ b/frontend/app/src/ion-icons.ts @@ -0,0 +1,3 @@ +import {IonIconCustomElement} from './app/util/ion-icon/ion-icon-custom-component'; + +customElements.define('ion-icon', IonIconCustomElement); diff --git a/frontend/app/src/theme/common/_ion-searchbar.scss b/frontend/app/src/theme/common/_ion-searchbar.scss index 8fe7c9ba..bb56e504 100644 --- a/frontend/app/src/theme/common/_ion-searchbar.scss +++ b/frontend/app/src/theme/common/_ion-searchbar.scss @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -$icon-size: 23px; +$icon-size: 22px; app-root ion-searchbar[class*='sc-ion-searchbar-'] { --border-radius: var(--border-radius-default); @@ -40,20 +40,20 @@ app-root ion-searchbar[class*='sc-ion-searchbar-'] { } } + ion-icon { + font-size: $icon-size; + } + ion-icon.searchbar-search-icon { top: 50%; left: var(--spacing-sm); transform: translateY(-50%); - - width: $icon-size; - height: $icon-size; - color: var(--ion-color-medium-shade); } input.searchbar-input { padding-top: var(--spacing-xs); padding-bottom: var(--spacing-xs); - padding-left: calc(var(--spacing-lg) + #{$icon-size}); + padding-inline-start: calc(var(--spacing-lg) + #{$icon-size}) !important; } } diff --git a/frontend/app/src/theme/common/_ion-toolbar.scss b/frontend/app/src/theme/common/_ion-toolbar.scss index d981d7d8..c9f30c17 100644 --- a/frontend/app/src/theme/common/_ion-toolbar.scss +++ b/frontend/app/src/theme/common/_ion-toolbar.scss @@ -67,7 +67,8 @@ app-root ion-toolbar.in-toolbar { } ion-back-button { - --icon-margin-end: var(--spacing-xs); + --icon-margin-end: 0; + --icon-margin-start: 0; height: 42px; // this prevents the back button to become a .x px value } diff --git a/frontend/app/src/types.d.ts b/frontend/app/src/types.d.ts new file mode 100644 index 00000000..85571011 --- /dev/null +++ b/frontend/app/src/types.d.ts @@ -0,0 +1,9 @@ +import {IonIconCustomElement} from './app/util/ion-icon/ion-icon-custom-component'; + +declare global { + interface HTMLElementTagNameMap { + 'ion-icon': IonIconCustomElement; + } +} + +export default {}; diff --git a/frontend/app/tsconfig.app.json b/frontend/app/tsconfig.app.json index 62a5bc4d..1bdd437f 100644 --- a/frontend/app/tsconfig.app.json +++ b/frontend/app/tsconfig.app.json @@ -3,6 +3,6 @@ "compilerOptions": { "outDir": "../out-tsc/app" }, - "files": ["src/main.ts"], + "files": ["src/main.ts", "src/ion-icons.ts"], "include": ["src/**/*.d.ts"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index debfce69..e5a2bb46 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -836,6 +836,9 @@ importers: ionic-appauth: specifier: 0.9.0 version: 0.9.0(rxjs@7.8.1) + ionicons: + specifier: 7.4.0 + version: 7.4.0 jsonpath-plus: specifier: 10.0.7 version: 10.0.7 @@ -1089,9 +1092,6 @@ importers: typescript: specifier: 5.4.2 version: 5.4.2 - webpack-bundle-analyzer: - specifier: 4.10.1 - version: 4.10.1 images/app-builder: {} @@ -7427,10 +7427,6 @@ packages: engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} dev: true - /@polka/url@1.0.0-next.25: - resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} - dev: true - /@prettier/plugin-xml@2.2.0: resolution: {integrity: sha512-UWRmygBsyj4bVXvDiqSccwT1kmsorcwQwaIy30yVh8T+Gspx4OlC0shX1y+ZuwXZvgnafmpRYKks0bAu9urJew==} dependencies: @@ -10380,6 +10376,9 @@ packages: /commander@7.2.0: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} + requiresBuild: true + dev: false + optional: true /commander@8.3.0: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} @@ -11434,10 +11433,6 @@ packages: /dayjs@1.11.12: resolution: {integrity: sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==} - /debounce@1.2.1: - resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} - dev: true - /debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -13665,13 +13660,6 @@ packages: resolution: {integrity: sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==} dev: false - /gzip-size@6.0.0: - resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} - engines: {node: '>=10'} - dependencies: - duplexer: 0.1.2 - dev: true - /hammerjs@2.0.8: resolution: {integrity: sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==} engines: {node: '>=0.8.0'} @@ -19243,15 +19231,6 @@ packages: supports-color: 7.2.0 dev: true - /sirv@2.0.4: - resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} - engines: {node: '>= 10'} - dependencies: - '@polka/url': 1.0.0-next.25 - mrmime: 2.0.0 - totalist: 3.0.1 - dev: true - /sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} dev: true @@ -20480,11 +20459,6 @@ packages: resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} dev: false - /totalist@3.0.1: - resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} - engines: {node: '>=6'} - dev: true - /touch@3.1.1: resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} hasBin: true @@ -21457,29 +21431,6 @@ packages: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} dev: true - /webpack-bundle-analyzer@4.10.1: - resolution: {integrity: sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==} - engines: {node: '>= 10.13.0'} - hasBin: true - dependencies: - '@discoveryjs/json-ext': 0.5.7 - acorn: 8.12.1 - acorn-walk: 8.3.3 - commander: 7.2.0 - debounce: 1.2.1 - escape-string-regexp: 4.0.0 - gzip-size: 6.0.0 - html-escaper: 2.0.2 - is-plain-object: 5.0.0 - opener: 1.5.2 - picocolors: 1.0.1 - sirv: 2.0.4 - ws: 7.5.10 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: true - /webpack-dev-middleware@5.3.4(webpack@5.90.3): resolution: {integrity: sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==} engines: {node: '>= 12.13.0'} @@ -21805,19 +21756,6 @@ packages: signal-exit: 4.1.0 dev: true - /ws@7.5.10: - resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - /ws@8.17.1: resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} engines: {node: '>=10.0.0'}