From 55951c48b0ae8ca6b550c3f1f097424754d2fb83 Mon Sep 17 00:00:00 2001 From: lucas-angermann Date: Tue, 5 Nov 2024 09:27:45 +0100 Subject: [PATCH 1/7] docs: updating tutorial content --- TUTORIALS.md | 125 +++++++++++++++++++++++---------------------------- 1 file changed, 57 insertions(+), 68 deletions(-) diff --git a/TUTORIALS.md b/TUTORIALS.md index fa3251ed..952b22d6 100644 --- a/TUTORIALS.md +++ b/TUTORIALS.md @@ -6,7 +6,7 @@ In this guide you will follow the necessary steps for creating a basic web map a For this tutorial to work you need a code editor of your choice (e.g. Visual Studio Code) and npm installed. ## Setting up UKIS core-ui -### 1. Generate a new [Angular application](https://angular.io/cli/new) in the same Version like specified in our package.json [@angular/core](package.json). +### 1. Generate a new [Angular application](https://angular.dev/cli/new) in the same Version like specified in our package.json [@angular/core](package.json). For this you have to install `@angular/cli` in this specific Version first. - See ukis-frontend-libraries package.json [version of @angular/core](package.json) ``` @@ -32,20 +32,23 @@ npm install @cds/core@ @clr/angular@ @clr/ui@ - Add Clarity Styles: This is done later by adding the UKIS Theme -- Add the Clarity module to app.config.ts: +- Add the Clarity module and others to app.config.ts: ``` -import { ApplicationConfig, importProvidersFrom } from '@angular/core'; -import { ClarityModule } from '@clr/angular'; -import { provideAnimations } from '@angular/platform-browser/animations'; +import { ApplicationConfig, importProvidersFrom, provideZoneChangeDetection } from '@angular/core'; +import { ClarityModule } from '@clr/angular'; +import { provideAnimations } from '@angular/platform-browser/animations'; import { BrowserModule } from '@angular/platform-browser'; +import { provideRouter } from '@angular/router'; +import { routes } from './app.routes'; export const appConfig: ApplicationConfig = { providers: [ - ... - importProvidersFrom(BrowserModule, ClarityModule, ...), - provideAnimations() //Replacement for BrowserAnimationsModule - ] + provideZoneChangeDetection({ eventCoalescing: true }), + provideRouter(routes), + importProvidersFrom(BrowserModule, ClarityModule), + provideAnimations() + ] }; ``` @@ -64,12 +67,11 @@ ClarityIcons.addIcons(...essentialCollectionIcons); - Set Clarity Theme (index.html) ``` - + ``` -- For more information see -- [Adding Clarity to an Angular project](https://clarity.design/documentation/get-started#seedProjectAngular) -- [Step 2: Include the Clarity and Core Styles](https://clarity.design/pages/developing) -- [Step 5: Add Clarity to Angular Application](https://clarity.design/pages/developing) +For more information see +- [Getting Started with Clarity Design System](https://clarity.design/documentation/get-started#seedProjectAngular) +- [Adding Clarity to an Existing Angular Application](https://clarity.design/pages/developing#adding-clarity-to-an-existing-angular-application) ### 4. Run the ng add command for the UKIS core-ui @@ -90,20 +92,20 @@ to add files and styles from ukis-frontend-libraries in the desired version. ### 5. Start and view the application - Run `npm start` - Open [http://localhost:4200/](http://localhost:4200/) on a browser -- You should now be able to see the basic application layout in the browser. +- You should now be able to see the basic application layout (still without a map) in the browser. ## Installing map libraries In the following the components neccessary for the display of a web map are installed. More information can be found [in the map-ol library folder](projects/map-ol/README.md). ### 1. Add the following libraries: ``` -npm install @dlr-eoc/map-ol @dlr-eoc/base-layers-raster +npm install @dlr-eoc/map-ol @dlr-eoc/layer-control @dlr-eoc/base-layers-raster ``` The base layers raster library is optional, but it makes it easier to add a basemap. Without a given basemap the map canvas would be empty. ### 2. Add styles from OpenLayers to your application -e.g. in your apps style file (src/styles.css) +e.g. in your apps style file (src/styles.scss) ``` @import 'ol/ol.css'; ... @@ -113,8 +115,11 @@ e.g. in your apps style file (src/styles.css) ### 3. Add the following to example-view.component.ts: ``` import { MapOlComponent, MapOlService } from '@dlr-eoc/map-ol'; -import { LayerControlComponent, LayersService } from '@dlr-eoc/layer-control'; +import { LayerControlComponent, BaseLayerControlComponent} from '@dlr-eoc/layer-control'; +import { LayersService } from '@dlr-eoc/services-layers'; import { MapStateService } from '@dlr-eoc/services-map-state'; +import { IMapControls } from '@dlr-eoc/map-ol'; +import { OsmTileLayer, EocLitemap, BlueMarbleTile, EocLiteoverlayTile } from '@dlr-eoc/base-layers-raster'; ... @@ -123,46 +128,34 @@ standalone: true, imports: [ ... MapOlComponent, - LayerControlComponent + LayerControlComponent, + BaseLayerControlComponent ] -``` -### 4. Also replace the example-view.component.html with: -``` -
- -
-``` -### 5. Remove the contents of example-view.component.scss -This is necessary, as we do not have a footer or a side nav at the moment. - -### 6. Add the following to example-view.component.ts: -``` ... -import { IMapControls } from '@dlr-eoc/map-ol'; -import { OsmTileLayer, EocLitemap, BlueMarbleTile } from '@dlr-eoc/base-layers-raster'; -... -controls: IMapControls; - constructor( - public layerSvc: LayersService, - public mapStateSvc: MapStateService +controls!: IMapControls; +constructor( + public layerSvc: LayersService, + public mapStateSvc: MapStateService ) { } -ngOnInit() { +ngOnInit(): void { this.addBaselayers(); } +... + addBaselayers() { const layers = [ new OsmTileLayer({ - visible: false + visible: false }), new EocLitemap({ - visible: true + visible: true }), new BlueMarbleTile({ - visible: false + visible: false }) ]; @@ -170,27 +163,20 @@ addBaselayers() { } ``` - -- After these steps save your changes and visit your browser again. You should now see a working web map. As we have not included the layer control yet, you are only able to see the layers with visibility set to 'true'. - -## Adding layer controll and layers -To enable more interaction with the application we are now adding the layer control, overlays and layers. -### 1. First, install the layer control library and add the module to app.module.ts: -``` -npm install @dlr-eoc/layer-control +### 4. Also replace the example-view.component.html with: ``` +
+ +
``` -import { LayerControlComponent } from '@dlr-eoc/layer-control'; +### 5. Remove the contents of example-view.component.scss +- This is necessary, as we do not have a footer or a side nav at the moment. -... +After these steps save your changes and visit your browser again. You should now see a working web map. As we have not included the layer control html yet, you are only able to see the baselayer with visibility set to 'true'. - imports: [ - ... - LayerControlComponent - ] -``` -More information about this library can be found [in the layer-control library folder](projects/layer-control/README.md). -### 2. Next, include the following code in the example-view.component.html: +## Adding layer controll and layers to the app +To enable more interaction with the application we are now adding the layer control, overlays and layers. +### 1. First, add the layer control html code in the example-view.component.html: ``` @@ -222,14 +208,17 @@ More information about this library can be found [in the layer-control library f ``` -### 3. Extend the following import in the example-view.component.ts: -``` - -import { LayersService, Layer, WmtsLayer, RasterLayer } from '@dlr-eoc/services-layers'; +More information about this library can be found [in the layer-control library folder](projects/layer-control/README.md). +### 2. Extend the import in the example-view.component.ts: ``` -### 4. Add the overlays and layers next to the already existing baselayers in the example-view.component.ts: +import { LayersService, Layer, WmtsLayer, RasterLayer } from '@dlr-eoc/services-layers'; +import { ClarityIcons, layersIcon} from '@cds/core/icon'; +ClarityIcons.addIcons(...[layersIcon]); +``` + +### 3. Add the overlays and layers next to the already existing baselayers in the example-view.component.ts: ``` ngOnInit() { @@ -309,7 +298,7 @@ addLayers() { addOverlays(){ const layers: Layer[] = [ new EocLiteoverlayTile({ - visible: false, + visible: true, displayName: 'Litelables' }) ]; @@ -318,11 +307,11 @@ addOverlays(){ } ``` - For this tutorial we are using some example layers from the [EOC GeoService](https://geoservice.dlr.de/web/). -- Save and refresh your changes. You can now switch between the layers, change the layer order and adjust the opacity of individual layers in the layer control. Notice, that there is always the hierachical order overlays > layers > base layers. Also, there is only one active base layer possible at a time. If you do not need a layer category, you could delete the corresponding code in example-view.component.html. +- Save and refresh your changes. You can now switch between the layers, change the layer order and adjust the opacity of individual layers in the layer control. Notice, that there is always the hierachical order overlays > layers > baselayers. Also, there is only one active baselayer possible at a time. If you do not need a layer category, you could hide or delete the corresponding code in example-view.component.html. ## Optional adaptions We are nearly finished with our basic example application in this tutorial. In the last steps we can adjust some details in the application. -- To change the starting view of the map, paste the following changes in example-view.component.ts: +- To change the starting view of the map, add the following changes in example-view.component.ts: ``` import { MapStateService, IMapState } from '@dlr-eoc/services-map-state'; @@ -349,7 +338,7 @@ controls!: IMapControls; this.mapStateSvc.setMapState(this.startState); } ``` -- Add some controls to the map in the example-view.component.ts: +- To add some controls to the map, adjust the controls object in the example-view.component.ts: ``` constructor( public layerSvc: LayersService, From b3b95c5645e7234ea4b0bdbee9a7aab7a8ec477e Mon Sep 17 00:00:00 2001 From: lucas-angermann Date: Thu, 7 Nov 2024 14:08:32 +0100 Subject: [PATCH 2/7] docs: minor text changes --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 19b8ad23..73bc2dce 100644 --- a/README.md +++ b/README.md @@ -82,9 +82,9 @@ Then run: More detailed information about setting up a local UKIS application can be found in the [tutorial document](TUTORIALS.md). -## Team +## UKIS contributors -The UKIS team creates and adapts libraries which simplify the creation of web-based applications. Our team includes (in alphabetical order): +The UKIS core team creates and adapts libraries which simplify the creation of web-based applications. The main contributors over the years were (in alphabetical order): - Angermann, Lucas - Böck, Mathias From 5ec828570b401e6ba18fa836107e4750d72f928e Mon Sep 17 00:00:00 2001 From: lucas-angermann Date: Thu, 7 Nov 2024 14:10:05 +0100 Subject: [PATCH 3/7] docs: adaptions for map-cesium --- TUTORIALS.md | 2 + projects/map-cesium/README.md | 157 +++++++++++++++++++++------------- 2 files changed, 98 insertions(+), 61 deletions(-) diff --git a/TUTORIALS.md b/TUTORIALS.md index 952b22d6..5139d960 100644 --- a/TUTORIALS.md +++ b/TUTORIALS.md @@ -267,6 +267,7 @@ addLayers() { params: { LAYERS: 'GUF28_DLR_v1_Mosaic', STYLES: 'guf_8bit', + TRANSPARENT: true }, tileSize: 512, visible: true, @@ -283,6 +284,7 @@ addLayers() { params: { LAYERS: 'WSF_Evolution', STYLES: 'wsfevolution', + TRANSPARENT: true }, tileSize: 512, visible: false, diff --git a/projects/map-cesium/README.md b/projects/map-cesium/README.md index 1eea9cd1..0f44f346 100644 --- a/projects/map-cesium/README.md +++ b/projects/map-cesium/README.md @@ -1,5 +1,5 @@ # @dlr-eoc/map-cesium -This library enables the UKIS frontend to display content on a 3D virtual globe using [CesiumJS](https://cesium.com/platform/cesiumjs/). It uses the same toolsets as the 2D mapping libraries and adds additional 3D capabilities. In the most basic version, map-cesium is displaying 2D maps on a 3D globe without explicit 3D content. +This library enables the UKIS frontend to display content on a 3D virtual globe using [CesiumJS](https://github.com/CesiumGS/cesium). It uses the same toolsets as the 2D mapping libraries and adds additional 3D capabilities. In the most basic version, map-cesium is displaying 2D maps on a 3D globe without explicit 3D content. ### How to use this in a ukis-angular (@dlr-eoc/core-ui) project First, install and setupt UKIS core, like described in the [Tutorial](../../TUTORIALS.md#setting-up-ukis-core-ui). @@ -66,15 +66,38 @@ or in the angular config file (window as Record)['CESIUM_BASE_URL'] = 'assets/cesium/'; ``` -Now, you can display the same layers as used in the [Tutorial](https://github.com/dlr-eoc/ukis-frontend-libraries/blob/main/TUTORIALS.md#adding-layer-controll-and-layers) on the cesium 3D globe. +### Adjust some imports and objects in example-view.component.ts: +``` +... + +import { MapCesiumComponent, ICesiumControls } from '@dlr-eoc/map-cesium'; + +... +imports: [..., MapCesiumComponent], +... +controls!: ICesiumControls; +... +//for now, remove the contents of the controls object in the constructor, it is not compatible with cesium + this.controls = { }; +``` + +#### Switch the map component in example-view.component.html to map-cesium: +``` + +``` +Note: The controls object is not the same as in map-ol! The map state and layers service can be used in both map components. + +Now, you can display the same layers as used in the [Tutorial](https://github.com/dlr-eoc/ukis-frontend-libraries/blob/main/TUTORIALS.md#adding-layer-controll-and-layers) on the cesium 3D globe. + +Note: WMS layers need the parameter ```TRANSPARENT: true```, otherwise they will overlay other layers with a white background color. To make the application more interesting, let's add some global layers from the [EOC GeoService](https://geoservice.dlr.de/web/) to the layers array in example-view.component.ts: ``` - new WmsLayer({ + new RasterLayer({ type: 'wms', id: 'metopGome2Ozone', name: 'MetOp GOME-2 L2C Daily O3 Combined', - visible: false, + visible: true, opacity: 0.8, description: 'MetOp GOME-2 Total Column Ozone (O3) Composite Layer', legendImg: 'https://geoservice.dlr.de/eoc/atmosphere/wms?service=WMS&version=1.3.0&request=GetLegendGraphic&format=image%2Fpng&width=20&height=20&layer=METOP_GOME-2_L2C_P1D_COMB_O3', @@ -152,10 +175,16 @@ new VectorLayer({ ``` #### Adding 3D content -Layer with 3D content like terrain and tilesets can be added with a second instance of the layers service. 3D tilesets have to be added as 'Layers', terrain datasets as 'Baselayers'. -Change the following inside example-view.component.ts: +Layer with 3D content like terrain and tilesets can be added with a second instance of the layers service. 3D tilesets have to be added as 'Layers', terrain datasets as 'Baselayers'. +Change the following inside example-view.component.ts, adjust the new layers service name and add the missing imports: ``` +import { Cesium3DTileset, CesiumTerrainProvider, Credit, EllipsoidTerrainProvider } from '@cesium/engine'; +import { ClarityIcons, layersIcon, blockIcon} from '@cds/core/icon'; +ClarityIcons.addIcons(...[layersIcon, blockIcon]); + +... + @Component({ selector: 'app-example-view', templateUrl: './example-view.component.html', @@ -169,10 +198,10 @@ Change the following inside example-view.component.ts: ... ] }) -``` -``` -onstructor( +... + +constructor( @Inject('twoDlayerSvc') public twoDlayerSvc: LayersService, @Inject('threeDlayerSvc') public threeDlayerSvc: LayersService, public mapStateSvc: MapStateService @@ -183,58 +212,64 @@ onstructor( Then you can add 3D services, e.g. ``` -addTilelayer(){ - // Cesium 3D Tileset Datasource as Custom Layer - const tileset_layer = new CustomLayer({ - name: '3D Tileset', - displayName: '3D Tileset', - id: 'tileset_3d', - custom_layer: new Cesium3DTileset({ - url:'https://link_to_dataset/tileset.json', - show: false - }), - visible: false, - description: '3D Tileset', - type: 'custom', - opacity: 1 - }); - - const layers = [tileset_layer]; - layers.map(l => this.threeDlayerSvc.addLayer(l, 'Layers')); -} - -addTerrainlayer(){ - // Terrain Datasource as Custom Layer - const terrain_layer = new CustomLayer({ - name: 'Terain', - displayName: 'Terrain', - id: 'terrain', - custom_layer: new CesiumTerrainProvider({ - url:'https://link_to_terrain_dataset', - credit: new Credit('© Attribution') - }), - visible: false, - description: 'digital elevation modell with 5m grid resulution', - type: 'custom', - }); - - const default_ellipsoid = new CustomLayer({ - name: 'Ellipsoid', - displayName: 'Ellipsoid', - id: 'ellipsoid', - custom_layer: new EllipsoidTerrainProvider({}), - visible: true, - attribution: ``, - description: '', - type: 'custom', - }); - - - const layers = [terrain_layer, default_ellipsoid]; - layers.map(l => this.threeDlayerSvc.addLayer(l, 'Baselayers')); -} + ngOnInit(): void { + ... + + this.addTilelayer(); + this.addTerrainlayer(); + + ... + } + + async addTilelayer(){ + // Cesium 3D Tileset Datasource as Custom Layer + const tileset_layer = new CustomLayer({ + name: '3D Tileset', + displayName: '3D Tileset', + id: 'tileset_3d', + custom_layer: await Cesium3DTileset.fromUrl('https://link_to_dataset/tileset.json', { show: false }), + visible: false, + description: '3D Tileset', + type: 'custom', + opacity: 1 + }); + + const layers = [tileset_layer]; + layers.map(l => this.threeDlayerSvc.addLayer(l, 'Layers')); + } + + async addTerrainlayer(){ + // Terrain Datasource as Custom Layer + const terrain_layer = new CustomLayer({ + name: 'Terain', + displayName: 'Terrain', + id: 'terrain', + custom_layer: await CesiumTerrainProvider.fromUrl('https://link_to_terrain_dataset', + { + credit: new Credit(`© Attribution`) + }), + visible: false, + description: 'digital elevation modell with 5m grid resulution', + type: 'custom', + }); + + const default_ellipsoid = new CustomLayer({ + name: 'Ellipsoid', + displayName: 'Ellipsoid', + id: 'ellipsoid', + custom_layer: new EllipsoidTerrainProvider({}), + visible: true, + attribution: ``, + description: '', + type: 'custom', + }); + + + const layers = [terrain_layer, default_ellipsoid]; + layers.map(l => this.threeDlayerSvc.addLayer(l, 'Baselayers')); + } ``` -To be able to interact with the layers in the viewer, additional layer controls have to be added to the vertical nav in `example-view.component.html`. Note, that the 3D serve-layers instanced is used here. +To be able to interact with the layers in the viewer, additional layer controls have to be added to the vertical nav in `example-view.component.html`. Note, that the 3D service-layers instanced is used here. ``` @@ -293,7 +328,7 @@ new VectorLayer({ #### Notes - Terrain has to be attributed with a new Cesium Credit object, see the example above. - GeoJSON layer are supported, but they are always shown above imagery layers, regardless of their ordering index in the layer control. Therefore they should be added as overlays. -- As of 01/2023, WFS is not supported by Cesium yet. +- So far, WFS is not supported by Cesium yet. - KmlDataSource does not support opacity change at the moment. - The stroke-width of vector polygons in Cesium does not change on non Apple browsers. There seems to be an issue with the browser support for this feature. - When a vector layer is clamped to the ground, Cesium does not display the stroke anymore. Cesium's proposed workaround at the moment is to include the stroke as additional polyline vector layer. From 6dd55d475f8ca8f49383ef337444eb4b57e99382 Mon Sep 17 00:00:00 2001 From: lucas-angermann Date: Wed, 13 Nov 2024 15:39:39 +0100 Subject: [PATCH 4/7] docs: adding some links --- projects/demo-auth/README.md | 2 +- projects/demo-maps/README.md | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/projects/demo-auth/README.md b/projects/demo-auth/README.md index 7542a057..6a70c79b 100644 --- a/projects/demo-auth/README.md +++ b/projects/demo-auth/README.md @@ -2,7 +2,7 @@ This application was generated with `ng generate application demo-auth` and then `@dlr-eoc/core-ui:ng-add --routing=true` was applied. -- This app depends on *@dlr-eoc/user-info* +- This app depends on [*@dlr-eoc/user-info*](../user-info/README.md) - It implements an AuthGuardService to protect routes - BasicAuthService which implements IAuthService (your business logic for authentication and authorization) - HttpAuthInterceptor which uses the AuthService to add a basic token on your angular http requests diff --git a/projects/demo-maps/README.md b/projects/demo-maps/README.md index dade1511..500aa8c9 100644 --- a/projects/demo-maps/README.md +++ b/projects/demo-maps/README.md @@ -2,13 +2,15 @@ This application was generated with `ng generate application demo-maps` and then `@dlr-eoc/core-ui:ng-add --routing=true` was applied. -In the src folder you can find a few route-components which show the usage of main UKIS frontend components: +In the src folder you can find a few route-components which show the usage of main UKIS frontend components, e. g.: - [layers](src/app/route-components/route-example-layers/route-map.component.ts) - [events](src/app/route-components/route-example-events/route-map3.component.ts) - [layer style](src/app/route-components/route-example-layer-style/route-map6.component.ts) - [custom layers](src/app/route-components/route-example-custom-layers/route-map4.component.ts) - [layout](src/app/route-components/route-example-layout/route-map5.component.ts) - [map projection](src/app/route-components/route-example-projection/route-map2.component.ts) +- [3D CesiumJS map](src/app/route-components/route-example-cesium/route-example-cesium.component.ts) +- [maplibre map](src/app/route-components/route-example-maplibre/route-example-maplibre.component.ts) ## Getting started From e0cfe2fb5d367454341ee8f1e8e471c8e0469cf8 Mon Sep 17 00:00:00 2001 From: lucas-angermann Date: Wed, 13 Nov 2024 15:45:06 +0100 Subject: [PATCH 5/7] docs: updating changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1fd062d..f5b5aaab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ * **@dlr-eoc/layer-control:** - Fix direction of `@cds` icon +### Documentation +- Update `TUTORIALS.md` +- Minor changes in some libraries's `README.md` + # [14.0.0](https://github.com/dlr-eoc/ukis-frontend-libraries/tree/v14.0.0) (2024-08-05) (map-cesium, angular update, @clr and @cds update) From a1c83218323e5ba2b349ee844a985bdea2bd6bcc Mon Sep 17 00:00:00 2001 From: lucas-angermann Date: Thu, 14 Nov 2024 09:28:44 +0100 Subject: [PATCH 6/7] docs: remove optional imports --- TUTORIALS.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/TUTORIALS.md b/TUTORIALS.md index 5139d960..bc2e1c81 100644 --- a/TUTORIALS.md +++ b/TUTORIALS.md @@ -38,14 +38,9 @@ import { ApplicationConfig, importProvidersFrom, provideZoneChangeDetection } fr import { ClarityModule } from '@clr/angular'; import { provideAnimations } from '@angular/platform-browser/animations'; import { BrowserModule } from '@angular/platform-browser'; -import { provideRouter } from '@angular/router'; - -import { routes } from './app.routes'; export const appConfig: ApplicationConfig = { providers: [ - provideZoneChangeDetection({ eventCoalescing: true }), - provideRouter(routes), importProvidersFrom(BrowserModule, ClarityModule), provideAnimations() ] From b764048d307aad30f6ca05af1b35bb3c0704e3dc Mon Sep 17 00:00:00 2001 From: lucas-angermann Date: Thu, 14 Nov 2024 09:29:58 +0100 Subject: [PATCH 7/7] docs: remove not needed imports --- TUTORIALS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TUTORIALS.md b/TUTORIALS.md index bc2e1c81..3a047742 100644 --- a/TUTORIALS.md +++ b/TUTORIALS.md @@ -34,7 +34,7 @@ npm install @cds/core@ @clr/angular@ @clr/ui@ - Add the Clarity module and others to app.config.ts: ``` -import { ApplicationConfig, importProvidersFrom, provideZoneChangeDetection } from '@angular/core'; +import { ApplicationConfig, importProvidersFrom } from '@angular/core'; import { ClarityModule } from '@clr/angular'; import { provideAnimations } from '@angular/platform-browser/animations'; import { BrowserModule } from '@angular/platform-browser';