Skip to content

Commit

Permalink
Merged PR 14725: Release
Browse files Browse the repository at this point in the history
- GB3-1623: AX: Bilder Alt Text
- GB3-1626: Add custom page title to each page
- GB3-1593: Bugfix: Wrong update of dpi settings upon format change
- Gb3-1640: Close basemap selection list on selection change
- GB3-1656 Keep url params on search error
- GB3-1645: add aria labels to the navigation
- GB3-1647: Add CNAME file to deployment step
- GB3-1628: Add skip links to all pages except map page
- GB3-1669 fix data-download input
- GB3-1665: Show error for invalid inital maps
- Gb3-1666: Zoom To Coordinate Input
- GB3-1665: Slight refactoring
- GB3-1658: Renovate adjustments
  • Loading branch information
TIL-EBP committed Sep 17, 2024
2 parents 88ba519 + b03d9fa commit e77f556
Show file tree
Hide file tree
Showing 48 changed files with 842 additions and 371 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/node-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ jobs:
npm ci
npm run build-dev-ebp
- name: Create CNAME file for custom domain
run: echo 'dev.geo.zh.ch' > ./dist/browser/CNAME

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
Expand Down
538 changes: 254 additions & 284 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
"eslint-plugin-rxjs": "^5.0.2",
"eslint-plugin-rxjs-angular": "^2.0.0",
"husky": "^9.0.0",
"jasmine-core": "~5.2.0",
"jasmine-core": "~5.3.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
Expand All @@ -93,6 +93,6 @@
"lint-staged": "^15.0.0",
"prettier": "^3.3.3",
"puppeteer": "^23.0.0",
"typescript": "~5.4.5"
"typescript": "~5.5.0"
}
}
8 changes: 8 additions & 0 deletions renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@
"groupName": "eslint",
"matchPackagePrefixes": ["eslint", "@angular-eslint", "@ngrx/eslint", "@typescript-eslint"]
},
{
"matchManagers": ["npm"],
"matchPackageNames": ["zone.js"],
"matchUpdateTypes": ["minor"],
"automerge": false,
"autoApprove": false,
"description": "There are breaking changes for zone.js with updates on minor level. Therefore, this rule prevents automerge and autoApprove for this update type."
},
{
"matchManagers": ["npm"],
"matchPackageNames": ["prettier"],
Expand Down
43 changes: 33 additions & 10 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,52 @@ import {NotFoundErrorPageComponent} from './error-handling/components/not-found-
import {FatalErrorPageComponent} from './error-handling/components/fatal-error-page/fatal-error-page.component';
import {fatalErrorMapGuard} from './embedded-page/guards/fatal-error-page.guard';

const siteOperator = 'Geoportal Kanton Zürich';
const routes: Routes = [
{
path: '',
children: [
{path: MainPage.Auth, loadChildren: () => import('./auth/auth.module').then((m) => m.AuthModule)},
{path: MainPage.Maps, loadChildren: () => import('./map/map.module').then((m) => m.MapModule)},
{path: MainPage.Data, loadChildren: () => import('./data-catalogue/data-catalogue.module').then((m) => m.DataCatalogueModule)},
{path: MainPage.Support, loadChildren: () => import('./support-page/support-page.module').then((m) => m.SupportPageModule)},
{path: MainPage.Privacy, loadChildren: () => import('./privacy/privacy.module').then((m) => m.PrivacyModule)},
{path: MainPage.TermsOfUse, loadChildren: () => import('./terms-of-use/terms-of-use.module').then((m) => m.TermsOfUseModule)},
{path: MainPage.Start, loadChildren: () => import('./start-page/start-page.module').then((m) => m.StartPageModule)},
{path: MainPage.Auth, loadChildren: () => import('./auth/auth.module').then((m) => m.AuthModule), title: `Login ${siteOperator}`},
{path: MainPage.Maps, loadChildren: () => import('./map/map.module').then((m) => m.MapModule), title: `GIS-Browser ${siteOperator}`},
{
path: MainPage.Data,
loadChildren: () => import('./data-catalogue/data-catalogue.module').then((m) => m.DataCatalogueModule),
title: `Geodatenkatalog ${siteOperator}`,
},
{
path: MainPage.Support,
loadChildren: () => import('./support-page/support-page.module').then((m) => m.SupportPageModule),
title: `Hilfe & Support ${siteOperator}`,
},
{
path: MainPage.Privacy,
loadChildren: () => import('./privacy/privacy.module').then((m) => m.PrivacyModule),
title: `Datenschutz ${siteOperator}`,
},
{
path: MainPage.TermsOfUse,
loadChildren: () => import('./terms-of-use/terms-of-use.module').then((m) => m.TermsOfUseModule),
title: `Nutzungshinweise ${siteOperator}`,
},
{
path: MainPage.Start,
loadChildren: () => import('./start-page/start-page.module').then((m) => m.StartPageModule),
title: `${siteOperator}`,
},
{
path: MainPage.ShareLink,
loadChildren: () => import('./share-link/share-link.module').then((m) => m.ShareLinkModule),
title: `Link teilen ${siteOperator}`,
},
{
path: MainPage.Embedded,
loadChildren: () => import('./embedded-page/embedded-map-page.module').then((m) => m.EmbeddedMapPageModule),
title: `GIS-Browser ${siteOperator}`,
},

{path: MainPage.Error, component: FatalErrorPageComponent, canDeactivate: [fatalErrorMapGuard]},
{path: MainPage.NotFound, component: NotFoundErrorPageComponent},
{path: '**', component: NotFoundErrorPageComponent},
{path: MainPage.Error, component: FatalErrorPageComponent, canDeactivate: [fatalErrorMapGuard], title: `Fehler ${siteOperator}`},
{path: MainPage.NotFound, component: NotFoundErrorPageComponent, title: `Seite nicht gefunden ${siteOperator}`},
{path: '**', component: NotFoundErrorPageComponent, title: `Seite nicht gefunden ${siteOperator}`},
],
},
];
Expand Down
24 changes: 18 additions & 6 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
<main class="app">
<navbar-mobile *ngIf="screenMode === 'mobile' && !isHeadlessPage && !mapUiState?.hideUiElements"></navbar-mobile>
<navbar *ngIf="!isHeadlessPage && screenMode !== 'mobile'" class="app__navbar" [isSimplifiedPage]="isSimplifiedPage"></navbar>
<dev-mode-banner *ngIf="isDevModeActive" class="app__dev-mode-banner"></dev-mode-banner>
@if (!isHeadlessPage && !isSimplifiedPage) {
<skip-link [skipLinks]="skipLinks" (skipToLocationEvent)="skipToDomElement($event)"></skip-link>
}
@if (screenMode === 'mobile' && !isHeadlessPage && !mapUiState?.hideUiElements) {
<navbar-mobile #navigation [id]="templateVariable.Navigation"></navbar-mobile>
} @else if (!isHeadlessPage && screenMode !== 'mobile') {
<navbar class="app__navbar" [isSimplifiedPage]="isSimplifiedPage" #navigation [id]="templateVariable.Navigation"></navbar>
}
@if (isDevModeActive) {
<dev-mode-banner class="app__dev-mode-banner"></dev-mode-banner>
}
<article [ngClass]="{'app__headless-page': isHeadlessPage}">
<router-outlet></router-outlet>
<main-footer *ngIf="!isSimplifiedPage && !isHeadlessPage"></main-footer>
<router-outlet #mainContent [id]="templateVariable.MainContent"></router-outlet>
@if (!isHeadlessPage && !isSimplifiedPage) {
<main-footer #footer [id]="templateVariable.Footer"></main-footer>
}
</article>
<scrollbar-width-calculation class="app__scrollbar-width-calculation" *ngIf="scrollbarWidth === undefined"></scrollbar-width-calculation>
@if (scrollbarWidth === undefined) {
<scrollbar-width-calculation class="app__scrollbar-width-calculation"></scrollbar-width-calculation>
}
</main>
30 changes: 23 additions & 7 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {BreakpointObserver} from '@angular/cdk/layout';
import {Component, HostListener, OnDestroy, OnInit} from '@angular/core';
import {Component, ElementRef, HostListener, OnDestroy, OnInit, QueryList, Renderer2, ViewChildren} from '@angular/core';
import {MatSnackBar, MatSnackBarRef} from '@angular/material/snack-bar';
import {Store} from '@ngrx/store';
import {filter, Subscription, take, tap} from 'rxjs';
Expand All @@ -18,19 +18,26 @@ import {selectUrlState} from './state/app/reducers/url.reducer';
import {selectMapUiState} from './state/map/reducers/map-ui.reducer';
import {MapUiState} from './state/map/states/map-ui.state';
import {selectDevMode} from './state/app/reducers/app.reducer';
import {SkipLink} from './shared/types/skip-link.type';
import {SkipLinkConstants} from './shared/constants/skip-link.constants';
import {SkipLinkTemplateVariable} from './shared/enums/skip-link-template-variable.enum';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit, OnDestroy {
public screenMode: ScreenMode = 'regular';
public mapUiState?: MapUiState;
public isHeadlessPage: boolean = false;
public isSimplifiedPage: boolean = false;
public scrollbarWidth?: number;
public isDevModeActive: boolean = false;
@ViewChildren(Object.values(SkipLinkTemplateVariable).join(', '), {read: ElementRef}) private readonly elements!: QueryList<ElementRef>;

protected screenMode: ScreenMode = 'regular';
protected mapUiState?: MapUiState;
protected isHeadlessPage: boolean = false;
protected isSimplifiedPage: boolean = false;
protected scrollbarWidth?: number;
protected isDevModeActive: boolean = false;
protected readonly skipLinks: SkipLink[] = SkipLinkConstants.skipLinks;
protected readonly templateVariable = SkipLinkTemplateVariable;

private snackBarRef?: MatSnackBarRef<PageNotificationComponent>;
private readonly urlState$ = this.store.select(selectUrlState);
Expand All @@ -47,6 +54,7 @@ export class AppComponent implements OnInit, OnDestroy {
private readonly pageNotificationService: PageNotificationService,
private readonly store: Store,
private readonly iconsService: IconsService,
private readonly renderer: Renderer2,
) {
this.iconsService.initIcons();
}
Expand All @@ -59,6 +67,14 @@ export class AppComponent implements OnInit, OnDestroy {
this.subscriptions.unsubscribe();
}

public skipToDomElement(elementId: string): void {
const element = this.elements.find((el) => el.nativeElement.id === elementId);
if (element) {
this.renderer.setAttribute(element.nativeElement, 'tabindex', '-1');
element.nativeElement.focus();
}
}

@HostListener('document:click', ['$event'])
private onDocumentClick(event: PointerEvent) {
this.documentService.documentClicked$.next(event);
Expand Down
2 changes: 2 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {effectErrorHandler} from './state/app/effects/effects-error-handler.effe
import {EsriMapLoaderService} from './map/services/esri-services/esri-map-loader.service';
import {MapLoaderService} from './map/interfaces/map-loader.service';
import {DevModeBannerComponent} from './shared/components/dev-mode-banner/dev-mode-banner.component';
import {SkipLinkComponent} from './shared/components/skip-link/skip-link.component';

// necessary for the locale 'de-CH' to work
// see https://stackoverflow.com/questions/46419026/missing-locale-data-for-the-locale-xxx-with-angular
Expand All @@ -55,6 +56,7 @@ export const GRAV_CMS_SERVICE = new InjectionToken<GravCmsService>('GravCmsServi
ErrorHandlingModule,
StoreRouterConnectingModule.forRoot(),
DevModeBannerComponent,
SkipLinkComponent,
],
providers: [
{provide: ErrorHandler, deps: [Router, ErrorHandlerService, EmbeddedErrorHandlerService], useFactory: errorHandlerServiceFactory},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Component, OnDestroy, OnInit} from '@angular/core';
import {Component, EventEmitter, OnDestroy, OnInit, Output} from '@angular/core';
import {Store} from '@ngrx/store';
import {Subscription, tap} from 'rxjs';
import {ScreenMode} from 'src/app/shared/types/screen-size.type';
Expand All @@ -14,6 +14,8 @@ import {BasemapConfigService} from '../../../../services/basemap-config.service'
styleUrls: ['./basemap-selection-list.component.scss'],
})
export class BasemapSelectionListComponent implements OnInit, OnDestroy {
@Output() public readonly basemapChangedEvent = new EventEmitter();

public activeBasemap?: Basemap;
public availableBasemaps: Basemap[] = [];
public screenMode: ScreenMode = 'regular';
Expand All @@ -39,6 +41,7 @@ export class BasemapSelectionListComponent implements OnInit, OnDestroy {

public switchBasemap(toId: string) {
this.store.dispatch(MapConfigActions.setBasemap({activeBasemapId: toId}));
this.basemapChangedEvent.emit();
}

private initSubscriptions() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
<div class="basemap-selector" #basemapSelector typedTourAnchor="map.background">
<button
#basemapSelectorButton
mat-flat-button
(click)="toggleSelection()"
class="basemap-selector__active"
[ngStyle]="{'background-image': 'url(' + (activeBasemap?.id | basemapImageLink) + ')'}"
></button>
<basemap-selection-list *ngIf="isSelectionOpen"></basemap-selection-list>
<basemap-selection-list
*ngIf="isSelectionOpen"
(basemapChangedEvent)="toggleSelectionAndFocusBasemapSelectorButton()"
></basemap-selection-list>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {BasemapConfigService} from '../../../services/basemap-config.service';
})
export class BasemapSelectorComponent implements OnInit, OnDestroy, AfterViewInit {
@ViewChild('basemapSelector', {read: ElementRef, static: false}) private basemapSelectorRef!: ElementRef;
@ViewChild('basemapSelectorButton', {read: ElementRef}) private basemapSelectorButtonRef!: ElementRef;

public activeBasemap?: Basemap;
public isSelectionOpen: boolean = false;
Expand Down Expand Up @@ -50,6 +51,11 @@ export class BasemapSelectorComponent implements OnInit, OnDestroy, AfterViewIni
);
}

public toggleSelectionAndFocusBasemapSelectorButton() {
this.toggleSelection();
this.basemapSelectorButtonRef.nativeElement.focus();
}

public toggleSelection() {
this.isSelectionOpen = !this.isSelectionOpen;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
<map-rotation-button [rotation]="rotation"></map-rotation-button>
<div class="coordinate-scale-inputs__coordinate">
<data-input>
<input (change)="setMapCenter($event)" [(ngModel)]="mapCenterInput" class="coordinate-scale-inputs__input" type="text" />
<input
(change)="setMapCenterAndDrawHighlight($event)"
[(ngModel)]="mapCenterInput"
class="coordinate-scale-inputs__input"
type="text"
/>
</data-input>
</div>
<div class="coordinate-scale-inputs__scale">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ export class CoordinateScaleInputsComponent implements OnInit, OnDestroy {
}
}

public setMapCenter(event: Event) {
public setMapCenterAndDrawHighlight(event: Event) {
const input = event.target as HTMLInputElement;
const center = this.coordinateParserService.parse(input.value);

if (center) {
this.store.dispatch(MapConfigActions.setMapCenter({center}));
this.store.dispatch(MapConfigActions.setMapCenterAndDrawHighlight({center}));
} else {
input.value = this.mapCenter;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ <h1 class="data-download-dialog__header__title">Datenbezug</h1>
</button>
</div>
<div class="data-download-dialog__content" *ngIf="order">
<search
class="data-download-dialog__content__search"
placeholderText="Nach Geodaten filtern"
(changeSearchTermEvent)="setFilterTerm($event)"
(clearSearchTermEvent)="clearFilterTerm()"
(openFilterEvent)="openFilterWindow()"
[disabled]="savingState === 'loading'"
[isAnyFilterActive]="activeDataDownloadFiltersPerCategory.length > 0"
></search>
<div>
<search
class="data-download-dialog__content__search"
placeholderText="Nach Geodaten filtern"
(changeSearchTermEvent)="setFilterTerm($event)"
(clearSearchTermEvent)="clearFilterTerm()"
(openFilterEvent)="openFilterWindow()"
[disabled]="savingState === 'loading'"
[isAnyFilterActive]="activeDataDownloadFiltersPerCategory.length > 0"
></search>
</div>

<div class="data-download-dialog__content__products">
<expandable-list-item
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,12 @@ export class PrintDialogComponent implements OnInit, OnDestroy {
} else {
this.formGroup.controls.dpi.enable();
}
this.formGroup.controls.dpi.setValue(this.availableDpiSettings[0]);
const isSelectedDpiSettingAllowed = this.availableDpiSettings.some(
(availableDpiSetting) => availableDpiSetting === this.formGroup.controls.dpi.value,
);
if (!isSelectedDpiSettingAllowed) {
this.formGroup.controls.dpi.setValue(this.availableDpiSettings[0]);
}
}

private updateFileTypeValueOnValueChange() {
Expand All @@ -391,6 +396,11 @@ export class PrintDialogComponent implements OnInit, OnDestroy {
} else {
this.formGroup.controls.fileFormat.enable();
}
this.formGroup.controls.fileFormat.setValue(this.availableFileFormats[0]);
const isSelectedFileFormatAllowed = this.availableFileFormats.some(
(availableFileFormat) => availableFileFormat === this.formGroup.controls.fileFormat.value,
);
if (!isSelectedFileFormatAllowed) {
this.formGroup.controls.fileFormat.setValue(this.availableFileFormats[0]);
}
}
}
3 changes: 2 additions & 1 deletion src/app/shared/components/navbar/navbar.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<mat-toolbar class="navbar" color="primary">
<mat-toolbar aria-label="Hauptnavigation" class="navbar" color="primary" role="navigation">
<span class="navbar__item">
<img
[ngStyle]="{display: !this.isSimplifiedPage ? 'none' : 'inline'}"
Expand Down Expand Up @@ -60,6 +60,7 @@
</button>
</mat-menu>
</ng-template>

<div class="navbar__underline-container" *ngIf="!isSimplifiedPage">
<div class="navbar__underline-container__content-container">
<span></span>
Expand Down
5 changes: 5 additions & 0 deletions src/app/shared/components/skip-link/skip-link.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@for (skipLink of skipLinks; track skipLink.id) {
<a class="skip-link" tabindex="0" (keydown.enter)="skipToLocation(skipLink.id)" (click)="skipToLocation(skipLink.id)">
{{ skipLink.label }}
</a>
}
18 changes: 18 additions & 0 deletions src/app/shared/components/skip-link/skip-link.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@use 'variables/ktzh-design-variables' as ktzh-variables;

.skip-link {
position: absolute;
left: max(24px, calc((100% - #{ktzh-variables.$zh-layout-max-content-width}) / 2));
top: -100px;
padding: 24px 12px;
background-color: white;
font-weight: bold;
font-size: 16px;
pointer-events: none;
}

.skip-link:focus {
top: 0;
z-index: 1000;
pointer-events: all;
}
Loading

0 comments on commit e77f556

Please sign in to comment.