Skip to content

Commit

Permalink
Merged PR 12791: GB3-1009: Move attribtue filter to map-overlay
Browse files Browse the repository at this point in the history
On desktop mode, the map-attribute-filter is now displayed like the Legend in the map overlay. When the attribute filter is open and the legend button is clicked, the attribute filter will be closed and the legend opened.
On mobile, the behavior is still the same: Attribute filter is opened in button sheet, on close, all bottom sheets are closed.

Some components were changed to be standalone, because I added a new standalone component. All its children were modified to be standalone so I don't get cyclic dependencies with the map-module.
  • Loading branch information
TIL-EBP committed Jan 29, 2024
2 parents 07b54fc + 8bbc39a commit 9828d26
Show file tree
Hide file tree
Showing 21 changed files with 317 additions and 83 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Component, Input, OnDestroy, OnInit} from '@angular/core';
import {Store} from '@ngrx/store';
import {Subscription, filter, map, tap} from 'rxjs';
import {filter, map, Subscription, tap} from 'rxjs';
import {isActiveMapItemOfType} from '../../../../shared/type-guards/active-map-item-type.type-guard';
import {NumberUtils} from '../../../../shared/utils/number.utils';
import {ActiveMapItemActions} from '../../../../state/map/actions/active-map-item.actions';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<map-overlay
*ngIf="mapAttributeFiltersItem"
(closeEvent)="close()"
[isVisible]="isVisible"
[showPrintButton]="false"
overlayTitle="Attributfilter: {{ mapAttributeFiltersItem.title }}"
>
<map-attribute-filter></map-attribute-filter>
</map-overlay>
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {Component, OnDestroy, OnInit} from '@angular/core';
import {Subscription, tap} from 'rxjs';
import {Store} from '@ngrx/store';
import {selectIsAttributeFilterOverlayVisible} from '../../../state/map/reducers/map-ui.reducer';
import {MapAttributeFilterComponent} from '../map-attribute-filter/map-attribute-filter.component';
import {MapOverlayComponent} from '../map-overlay/map-overlay.component';
import {CommonModule} from '@angular/common';
import {Gb2WmsActiveMapItem} from '../../models/implementations/gb2-wms.model';
import {MapUiActions} from '../../../state/map/actions/map-ui.actions';
import {selectMapAttributeFiltersItem} from '../../../state/map/selectors/map-attribute-filters-item.selector';

@Component({
selector: 'map-attribute-filter-overlay',
standalone: true,
imports: [MapAttributeFilterComponent, MapOverlayComponent, CommonModule],
templateUrl: './map-attribute-filter-overlay.component.html',
styleUrl: './map-attribute-filter-overlay.component.scss',
})
export class MapAttributeFilterOverlayComponent implements OnInit, OnDestroy {
public isVisible = false;
public mapAttributeFiltersItem: Gb2WmsActiveMapItem | undefined;

private readonly attributeFilterVisibility$ = this.store.select(selectIsAttributeFilterOverlayVisible);
private readonly mapAttributeFiltersItem$ = this.store.select(selectMapAttributeFiltersItem);
private readonly subscriptions: Subscription = new Subscription();

constructor(private readonly store: Store) {}

public ngOnInit() {
this.initSubscriptions();
}

public ngOnDestroy() {
this.subscriptions.unsubscribe();
}

public close() {
this.store.dispatch(MapUiActions.setAttributeFilterVisibility({isVisible: false}));
}

private initSubscriptions() {
this.subscriptions.add(this.attributeFilterVisibility$.pipe(tap((isVisible) => (this.isVisible = isVisible))).subscribe());
this.subscriptions.add(
this.mapAttributeFiltersItem$
.pipe(
tap((mapAttributeFilterItem) => {
this.mapAttributeFiltersItem = mapAttributeFilterItem;
}),
)
.subscribe(),
);
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
<ng-container *ngIf="mapAttributeFiltersItem">
<mat-card appearance="raised" class="attribute-filter no-box-shadow" [ngClass]="{'attribute-filter--mobile': screenMode === 'mobile'}">
<mat-card-header *ngIf="screenMode !== 'mobile'">
<div class="attribute-filter__header">
<h3 class="attribute-filter__header__title" [matTooltip]="mapAttributeFiltersItem.title">
Attributfilter: {{ mapAttributeFiltersItem.title }}
</h3>
<button mat-icon-button (click)="close()">
<mat-icon>close</mat-icon>
</button>
</div>
</mat-card-header>
<div class="attribute-filter__content" [ngClass]="{'attribute-filter__content--mobile': screenMode === 'mobile'}">
<mat-card
class="no-box-shadow"
appearance="raised"
*ngFor="let filterConfiguration of mapAttributeFiltersItem.settings.filterConfigurations"
>
<mat-card class="no-box-shadow" *ngFor="let filterConfiguration of mapAttributeFiltersItem.settings.filterConfigurations">
<mat-card-header>
<mat-card-title>{{ filterConfiguration.name }}</mat-card-title>
</mat-card-header>
Expand All @@ -28,8 +14,8 @@ <h3 class="attribute-filter__header__title" [matTooltip]="mapAttributeFiltersIte
[ngClass]="{'attribute-filter__content__checkbox--unchecked': filterValue.isActive}"
[checked]="!filterValue.isActive"
(change)="updateFilter(filterConfiguration.parameter, filterValue.name, $event.checked)"
>{{ filterValue.name }}</mat-checkbox
>
>{{ filterValue.name }}
</mat-checkbox>
</ng-container>
</mat-card>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,13 @@

.attribute-filter {
max-height: inherit;
width: map-layout-variables.$map-overlay-width;
width: 100%;

&--mobile {
width: 100%;
}

.attribute-filter__header {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;

.attribute-filter__header__title {
@include mixins.single-line-text;
font-weight: bold;
margin: 0;
}
}

.attribute-filter__content {
overflow-y: scroll;

&--mobile {
overflow-y: unset;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import {Component, OnDestroy, OnInit} from '@angular/core';
import {concatLatestFrom} from '@ngrx/effects';
import {Store} from '@ngrx/store';
import {Subscription, tap} from 'rxjs';
import {ScreenMode} from 'src/app/shared/types/screen-size.type';
import {selectScreenMode} from 'src/app/state/app/reducers/app-layout.reducer';
import {isActiveMapItemOfType} from '../../../shared/type-guards/active-map-item-type.type-guard';
import {ActiveMapItemActions} from '../../../state/map/actions/active-map-item.actions';
import {MapAttributeFiltersItemActions} from '../../../state/map/actions/map-attribute-filters-item.actions';
import {selectItems} from '../../../state/map/reducers/active-map-item.reducer';
import {selectId} from '../../../state/map/reducers/map-attribute-filters-item.reducer';
import {Gb2WmsActiveMapItem} from '../../models/implementations/gb2-wms.model';
import {SharedModule} from '../../../shared/shared.module';
import {CommonModule} from '@angular/common';
import {selectMapAttributeFiltersItem} from '../../../state/map/selectors/map-attribute-filters-item.selector';

@Component({
selector: 'map-attribute-filter',
standalone: true,
templateUrl: './map-attribute-filter.component.html',
styleUrls: ['./map-attribute-filter.component.scss'],
imports: [SharedModule, CommonModule],
})
export class MapAttributeFilterComponent implements OnInit, OnDestroy {
public mapAttributeFiltersItem: Gb2WmsActiveMapItem | undefined;
public screenMode: ScreenMode = 'regular';

private readonly subscriptions: Subscription = new Subscription();
private readonly mapAttributeFiltersItem$ = this.store.select(selectId);
private readonly activeMapItems$ = this.store.select(selectItems);
private readonly mapAttributeFiltersItem$ = this.store.select(selectMapAttributeFiltersItem);
private readonly screenMode$ = this.store.select(selectScreenMode);

constructor(private readonly store: Store) {}
Expand All @@ -35,7 +35,7 @@ export class MapAttributeFilterComponent implements OnInit, OnDestroy {
this.subscriptions.unsubscribe();
}

public close() {
public clearMapAttributeFiltersItemId() {
this.store.dispatch(MapAttributeFiltersItemActions.clearMapAttributeFiltersItemId());
}

Expand All @@ -52,37 +52,15 @@ export class MapAttributeFilterComponent implements OnInit, OnDestroy {
}
}

private handleMapAttributeFiltersItemChange(mapAttributeFiltersItemId: string | undefined, activeMapItems: Gb2WmsActiveMapItem[]) {
let mapAttributeFiltersItem;
if (mapAttributeFiltersItemId !== undefined) {
mapAttributeFiltersItem = activeMapItems.find((activeMapItem) => activeMapItem.id === mapAttributeFiltersItemId);
if (mapAttributeFiltersItem === undefined) {
// the map attribute filters item ID is still set but the corresponding item is not active anymore => close this component
this.close();
}
}
this.mapAttributeFiltersItem = mapAttributeFiltersItem;
}

private initSubscriptions() {
this.subscriptions.add(
this.mapAttributeFiltersItem$
.pipe(
concatLatestFrom(() => this.activeMapItems$),
tap(([activeMapItemId, activeMapItems]) => {
const gb2WmsMapItems = activeMapItems.filter(isActiveMapItemOfType(Gb2WmsActiveMapItem));
this.handleMapAttributeFiltersItemChange(activeMapItemId, gb2WmsMapItems);
}),
)
.subscribe(),
);

this.subscriptions.add(
this.activeMapItems$
.pipe(
tap((activeMapItems) => {
const gb2WmsMapItems = activeMapItems.filter(isActiveMapItemOfType(Gb2WmsActiveMapItem));
this.handleMapAttributeFiltersItemChange(this.mapAttributeFiltersItem?.id, gb2WmsMapItems);
tap((item) => {
if (item === undefined) {
this.clearMapAttributeFiltersItemId();
}
this.mapAttributeFiltersItem = item;
}),
)
.subscribe(),
Expand Down
4 changes: 4 additions & 0 deletions src/app/map/components/map-overlay/map-overlay.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ import {Component, EventEmitter, Input, Output} from '@angular/core';
import {ResizeHandlerLocation} from '../../../shared/types/resize-handler-location.type';
import {StyleExpression} from '../../../shared/types/style-expression.type';
import {LoadingState} from '../../../shared/types/loading-state.type';
import {SharedModule} from '../../../shared/shared.module';
import {CommonModule} from '@angular/common';

@Component({
selector: 'map-overlay',
standalone: true,
templateUrl: './map-overlay.component.html',
styleUrls: ['./map-overlay.component.scss'],
imports: [SharedModule, CommonModule],
})
export class MapOverlayComponent {
@Input() public showPrintButton: boolean = true;
Expand Down
9 changes: 5 additions & 4 deletions src/app/map/map-page.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
class="map-container__legend-overlay"
[ngClass]="{'map-container__map-element--hidden': mapUiState?.hideUiElements}"
></legend-overlay>
<map-attribute-filter-overlay
*ngIf="screenMode !== 'mobile'"
class="map-container__attribute-filter-overlay"
[ngClass]="{'map-container__map-element--hidden': mapUiState?.hideUiElements}"
></map-attribute-filter-overlay>
<div class="map-container__all-map-items-container" *ngIf="screenMode !== 'mobile'">
<div class="map-container__all-map-items-container__inner-container">
<active-map-items
Expand Down Expand Up @@ -53,10 +58,6 @@
<mat-icon svgIcon="ktzh_legend"></mat-icon>
Legende
</button>
<map-attribute-filter
class="map-container__map-attribute-filter"
[ngClass]="{'map-container__map-element--hidden': mapUiState?.hideUiElements}"
></map-attribute-filter>
<feature-info-overlay
*ngIf="screenMode !== 'mobile'"
class="map-container__feature-info-overlay"
Expand Down
7 changes: 7 additions & 0 deletions src/app/map/map-page.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@
height: 100%;
}

.map-container__attribute-filter-overlay {
position: absolute;
top: 0;
left: 0;
height: 100%;
}

.map-container__all-map-items-container {
@include mixins.hide-on-small-screens;

Expand Down
8 changes: 5 additions & 3 deletions src/app/map/map.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ import {MapImportLayerListComponent} from './components/map-tools/map-import/map
import {MapImportDisplayNameComponent} from './components/map-tools/map-import/map-import-display-name/map-import-display-name.component';
import {TimeExtentToStringPipe} from './pipes/time-extent-to-string.pipe';
import {DateToStringPipe} from './pipes/date-to-string.pipe';
import {MapAttributeFilterOverlayComponent} from './components/map-attribute-filter-overlay/map-attribute-filter-overlay.component';

@NgModule({
declarations: [
Expand All @@ -92,14 +93,12 @@ import {DateToStringPipe} from './pipes/date-to-string.pipe';
LegendOverlayComponent,
LegendItemComponent,
FeatureInfoOverlayComponent,
MapOverlayComponent,
MapDataCatalogueComponent,
MapOverlayListItemComponent,
FeatureInfoItemComponent,
CoordinateScaleInputsComponent,
MapControlsComponent,
BasemapSelectorComponent,
MapAttributeFilterComponent,
SearchWindowComponent,
FavouriteCreationDialogComponent,
ApiDialogWrapperComponent,
Expand Down Expand Up @@ -172,7 +171,10 @@ import {DateToStringPipe} from './pipes/date-to-string.pipe';
MapImportDisplayNameComponent,
TimeExtentToStringPipe,
DateToStringPipe,
MapOverlayComponent,
MapAttributeFilterComponent,
MapAttributeFilterOverlayComponent,
],
exports: [LegendOverlayComponent, FeatureInfoOverlayComponent, MapContainerComponent, ZoomControlsComponent],
exports: [LegendOverlayComponent, FeatureInfoOverlayComponent, MapContainerComponent, ZoomControlsComponent, MapOverlayComponent],
})
export class MapModule {}
1 change: 1 addition & 0 deletions src/app/state/map/actions/map-ui.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const MapUiActions = createActionGroup({
'Set Elevation Profile Overlay Visibility': props<{isVisible: boolean}>(),
'Set Legend Overlay Visibility': props<{isVisible: boolean}>(),
'Set Feature Info Visibility': props<{isVisible: boolean}>(),
'Set Attribute Filter Visibility': props<{isVisible: boolean}>(),
'Show Share Link Dialog': emptyProps(),
'Show Create Favourite Dialog': emptyProps(),
'Show Delete Favourite Dialog': props<{favouriteToDelete: Favourite}>(),
Expand Down
12 changes: 11 additions & 1 deletion src/app/state/map/effects/active-map-item.effects.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ describe('ActiveMapItemEffects', () => {
});

describe('hideLegendAfterRemovingAllMapItems$', () => {
it('dispatches MapUiActions.hideLegend() if removeAllActiveMapItems action is executed', (done: DoneFn) => {
it('dispatches MapUiActions.setLegendOverlayVisibility() if removeAllActiveMapItems action is executed', (done: DoneFn) => {
actions$ = of(ActiveMapItemActions.removeAllActiveMapItems());
effects.hideLegendAfterRemovingAllMapItems$.subscribe((action) => {
expect(action).toEqual(MapUiActions.setLegendOverlayVisibility({isVisible: false}));
Expand All @@ -163,6 +163,16 @@ describe('ActiveMapItemEffects', () => {
});
});

describe('hideMapAttributeFilterAfterRemovingAllMapItems$', () => {
it('dispatches MapUiActions.setAttributeFilterVisibility() if removeAllActiveMapItems action is executed', (done: DoneFn) => {
actions$ = of(ActiveMapItemActions.removeAllActiveMapItems());
effects.hideMapAttributeFilterAfterRemovingAllMapItems$.subscribe((action) => {
expect(action).toEqual(MapUiActions.setAttributeFilterVisibility({isVisible: false}));
done();
});
});
});

describe('clearFeatureInfoContentAfterRemovingAllMapItems$', () => {
it('dispatches FeatureInfoActions.clearContent() if removeAllActiveMapItems action is executed', (done: DoneFn) => {
actions$ = of(ActiveMapItemActions.removeAllActiveMapItems());
Expand Down
9 changes: 9 additions & 0 deletions src/app/state/map/effects/active-map-item.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,15 @@ export class ActiveMapItemEffects {
);
});

public hideMapAttributeFilterAfterRemovingAllMapItems$ = createEffect(() => {
return this.actions$.pipe(
ofType(ActiveMapItemActions.removeAllActiveMapItems),
concatLatestFrom(() => this.store.select(selectScreenMode)),
filter(([_, screenMode]) => screenMode !== 'mobile'),
map(() => MapUiActions.setAttributeFilterVisibility({isVisible: false})),
);
});

public clearFeatureInfoContentAfterRemovingAllMapItems$ = createEffect(() => {
return this.actions$.pipe(
ofType(ActiveMapItemActions.removeAllActiveMapItems),
Expand Down
Loading

0 comments on commit 9828d26

Please sign in to comment.