Commit 16a9c233 authored by ncastejon's avatar ncastejon
Browse files

Add a meta description tag. Improve accessibility with buttons. Add rel=noopener for external <a>

parent a5eec1b9
<div class="feedback-component-container" [ngClass]="{'on-home-page': isHomePage}"
(clickOutside)="closeFeedbackFromClickOutside()">
<button tabindex="0" class="feedback-button" (click)="toogle()"
<button tabindex="0" class="feedback-button" (click)="toogle()" aria-label="Votre avis"
[ngClass]="{'expended': isExpended, 'closed': shouldAnimateClosing}">
<svg xmlns="http://www.w3.org/2000/svg" id="feedback_x5F_icon" viewBox="0 0 37.2 34">
<path
......
......@@ -4,19 +4,19 @@
<ul>
<li>
<a href="http://www.facebook.com/legrandlyon" title="Facebook (new window)" i18n-title="@@footer.facebook"
target="_blank">
target="_blank" rel="noopener">
<img class="social-network-link" src="./assets/img/icon_fb.svg" alt="Logo Facebook">
</a>
</li>
<li class="left-border">
<a href="https://twitter.com/grandlyon" title="Twitter (new window)" i18n-title="@@footer.twitter"
target="_blank">
target="_blank" rel="noopener">
<img class="social-network-link" src="./assets/img/icon_twi.svg" alt="Logo Twitter">
</a>
</li>
<li class="left-border">
<a href="https://download.data.grandlyon.com/catalogue/srv/fre/rss.search?sortBy=publicationDate&amp;georss=simplepoint&amp;data"
title="RSS Feed (new window)" i18n-title="@@footer.rss" target="_blank">
title="RSS Feed (new window)" i18n-title="@@footer.rss" target="_blank" rel="noopener">
<img class="social-network-link" src="./assets/img/icon_rss.svg" alt="Logo RSS">
</a>
</li>
......@@ -63,7 +63,7 @@
<div class="column metropole">
<ul>
<li>
<a href="https://www.grandlyon.com/" target="_blank">
<a href="https://www.grandlyon.com/" target="_blank" rel="noopener">
<img i18n-title="@@footer.metropole.site.title" title="Access the Lyon Metropolis website (new window)"
class="plus-logo" src="./assets/img/footer-plus.png" alt="">
</a>
......@@ -71,7 +71,7 @@
<li>
<a class="metropolis-website-link" i18n-title="@@footer.metropole.site.title"
title="Access the Lyon Metropolis website (new window)" href="https://www.grandlyon.com/" target="_blank"
i18n="@@footer.metropole.site">
i18n="@@footer.metropole.site" rel="noopener">
A Lyon Metropolis website
</a>
</li>
......
......@@ -23,8 +23,9 @@
<div class="navbar-header-item navbar-right-side">
<div class="connect-me">
<a [routerLink]="['/', AppRoutes.signin.uri]" *ngIf="!userIsSignedIn; else userSignedInTemplate">
<button class="button connect-button" *ngIf="isHomePage">
<a [routerLink]="['/', AppRoutes.signin.uri]" aria-label="Se connecter"
*ngIf="!userIsSignedIn; else userSignedInTemplate">
<button class="button connect-button" aria-label="Connect" *ngIf="isHomePage">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<g id="btn_x5F_connect">
<path
......
......@@ -4,7 +4,7 @@ import { ErrorHandler, Injectable } from '@angular/core';
export class ErrorsHandler implements ErrorHandler {
handleError(error: Error) {
console.log(error);
// console.log(error);
return;
}
......
......@@ -24,23 +24,23 @@ export class HttpErrorResponseInterceptor implements HttpInterceptor {
if (err instanceof HttpErrorResponse) {
switch (err.status) {
case 401:
console.log('HTTP ERROR: Unauthenticated');
// console.log('HTTP ERROR: Unauthenticated');
this._userService.resetAuth();
break;
case 403:
console.log('HTTP ERROR: Forbidden');
// console.log('HTTP ERROR: Forbidden');
break;
case 404:
console.log('HTTP ERROR: Not Found');
// console.log('HTTP ERROR: Not Found');
break;
case 500:
case 502:
case 503:
case 504:
console.log('HTTP ERROR: Server Error');
// console.log('HTTP ERROR: Server Error');
break;
default:
console.log(`HTTP ERROR: Status code ${err.status}`);
// console.log(`HTTP ERROR: Status code ${err.status}`);
}
}
}),
......
......@@ -3,7 +3,7 @@
(click)="toggleProperty(key)">
<ng-container *ngIf="isParent && isPropertyObjectOrArray(key)">
<span class="icon-chevron" *ngIf="isOpenProperties[key]">
<svg class="icon-opened" xmlns="http://www.w3.org/2000/svg" id="chevron" viewBox="0 0 15 9">
<svg class="icon-opened" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 9">
<path
d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z" />
<path
......@@ -11,7 +11,7 @@
</svg>
</span>
<span class="icon-chevron" *ngIf="!isOpenProperties[key]">
<svg xmlns="http://www.w3.org/2000/svg" id="chevron" viewBox="0 0 15 9">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 9">
<path
d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z" />
<path
......
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Meta } from '@angular/platform-browser';
import { ActivatedRoute, Router, Scroll } from '@angular/router';
import { Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';
......@@ -31,6 +32,7 @@ export class DatasetDetailComponent implements OnInit, OnDestroy {
private _router: Router,
private _scroller: ViewportScroller,
private _navigationHistoryService: NavigationHistoryService,
private _meta: Meta,
) { }
ngOnInit() {
......@@ -46,6 +48,9 @@ export class DatasetDetailComponent implements OnInit, OnDestroy {
});
this._route.params.subscribe((params) => {
// Set the title and description for the research page
this._meta.updateTag({ name: 'description', content: this.metadata.abstract });
this.isLoading = true;
this.initDatasetInfo();
});
......
......@@ -228,7 +228,8 @@
<p *ngFor="let constraint of metadata.legalConstraints">
{{ constraint }}
</p>
<a [href]="licenceUrl" target="_blank" class="button btn-blue-text btn-consult-license" *ngIf="licenceUrl"
<a [href]="licenceUrl" target="_blank" *ngIf="licenceUrl"
class="button btn-blue-text btn-consult-license" rel="noopener"
i18n="@@dataset.info.consultLicense">
Consult the license
</a>
......
<div class="format-icon" [ngClass]="'type-' + resourceType + ' is-' + size">
<svg xmlns="http://www.w3.org/2000/svg" id="format" viewBox="0 0 70 40">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70 40">
<path d="M68 3.5v32.9c0 .8-.7 1.5-1.5 1.5h-63c-.8.1-1.5-.6-1.5-1.4V14.1c0-.4.1-.7.4-1l8.9-10.6c.2-.3.7-.5 1.1-.5h54.1c.8 0 1.5.7 1.5 1.5z" class="white"/>
<path d="M66 4v32H4V14.3L12.6 4H66m.5-2H12.4c-.4 0-.8.2-1.1.5L2.4 13.1c-.2.3-.4.6-.4 1v22.4c0 .8.7 1.5 1.5 1.5h63c.8 0 1.5-.7 1.5-1.5v-33c0-.8-.7-1.5-1.5-1.5z" class="st0"/>
<path d="M12 12.1V2.4L2 14h8.1c1 0 1.9-.9 1.9-1.9z" class="st0"/>
......
......@@ -19,9 +19,9 @@
</div>
<div class="resource-download-icon">
<a [href]="link.url" target="_blank">
<a [href]="link.url" target="_blank" rel="noopener">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 23">
<g id="btn-download">
<g>
<path
d="M22 14c-.6 0-1 .4-1 1v5H3v-5c0-.6-.4-1-1-1s-1 .4-1 1v6c0 .6.4 1 1 1h20c.6 0 1-.4 1-1v-6c0-.6-.4-1-1-1z"
class="download_x002D_color" />
......
......@@ -15,7 +15,9 @@
<div class="root-url-input">
<div class="link-with-copy">
<span class="parameters-url">
<a [href]="resource.metadataLink.url" target="_blank">{{ resource.metadataLink.url }}</a>
<a [href]="resource.metadataLink.url" target="_blank" rel="noopener">
{{ resource.metadataLink.url }}
</a>
</span>
<button type="button" (click)="copyToClipboard(resource.metadataLink.url, true)"
class="button is-medium tooltip" [attr.data-tooltip]="messageClipboardRoot">
......@@ -35,7 +37,7 @@
Create a request
</span>
<span class="create-request-icon">
<svg xmlns="http://www.w3.org/2000/svg" id="chevron" viewBox="0 0 15 9">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 9">
<path
d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z"
class="brandcolor" />
......@@ -191,7 +193,7 @@
</div>
<div class="link-with-copy">
<span class="parameters-url column is-narrow-tablet">
<a [href]="queryableUrl" target="_blank" [ngClass]="{'is-disabled': isAllFeaturesChecked}"
<a [href]="queryableUrl" target="_blank" rel="noopener" [ngClass]="{'is-disabled': isAllFeaturesChecked}"
[innerHtml]="queryableUrlToDisplay">
</a>
</span>
......@@ -206,7 +208,7 @@
<div class="resource-download-icon" (click)="saveFile(queryableUrl)">
<a>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 23">
<g id="btn-download">
<g>
<path
d="M22 14c-.6 0-1 .4-1 1v5H3v-5c0-.6-.4-1-1-1s-1 .4-1 1v6c0 .6.4 1 1 1h20c.6 0 1-.4 1-1v-6c0-.6-.4-1-1-1z"
class="download_x002D_color" />
......
......@@ -19,7 +19,7 @@
<i class="fas fa-exclamation-triangle fa-lg"></i>
</span>
<div class="resource-icon">
<svg xmlns="http://www.w3.org/2000/svg" id="chevron" viewBox="0 0 15 9">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 9">
<path
d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z"
class="brandcolor" />
......
......@@ -9,7 +9,7 @@
(clickOutside)="closeColumsMenu()">
<div class="dropdown-trigger">
<button class="button button-with-icon" aria-haspopup="true" aria-controls="dropdown-menu"
(click)="toogleColumsMenu()">
(click)="toogleColumsMenu()" aria-label="Afficher les propriétés">
</button>
</div>
<div class="dropdown-menu" id="dropdown-menu" role="menu">
......@@ -28,6 +28,7 @@
<div class="field has-addons has-addons-centered is-centered">
<div class="control research-input" [ngClass]="{'has-icons-right': searchInput.value}">
<input type="text" class="input" [formControl]="searchInput" placeholder="Filter records"
aria-label="Filtrer les données"
i18n-placeholder="@@dataset.data.filterReccordPlaceholder" (keydown.enter)="searchChanged()" />
<span class="icon is-small is-right reset-research-icon" *ngIf="searchInput.value"
(click)="resetResearch()">
......@@ -71,7 +72,7 @@
</button>
<button class="button button-with-icon"
[ngClass]="{'btn-exit-fullscreen': fullscreen, 'btn-fullscreen': !fullscreen}" type="button"
(click)="toogleFullscreen()">
(click)="toogleFullscreen()" aria-label="Mode plein écran">
</button>
</div>
</div>
......@@ -109,6 +110,7 @@
<div class="field has-addons has-addons-centered is-centered">
<div class="control research-input" [ngClass]="{'has-icons-right': searchInput.value}">
<input type="text" class="input" [formControl]="searchInput" placeholder="Filter records"
aria-label="Filtrer les données"
i18n-placeholder="@@dataset.data.filterReccordPlaceholder" (keydown.enter)="searchChanged()" />
<span class="icon is-small is-right reset-research-icon" *ngIf="searchInput.value"
(click)="resetResearch()">
......@@ -131,7 +133,7 @@
<button class="button button-with-icon"
[ngClass]="{'btn-exit-fullscreen': fullscreen, 'btn-fullscreen': !fullscreen}" type="button"
(click)="toogleFullscreen()">
(click)="toogleFullscreen()" aria-label="Mode plein écran">
</button>
</div>
<div *ngIf="hasTable && hasMap" class="table-map-switch-button">
......
......@@ -7,7 +7,7 @@
</div>
<div class="arrows" [ngClass]="{'is-displayed': displayFilters === true}">
<svg xmlns="http://www.w3.org/2000/svg" id="chevron" viewBox="0 0 15 9">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 9">
<path
d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z"
class="brandcolor" />
......
import { DatePipe, ViewportScroller } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Meta } from '@angular/platform-browser';
import { Subscription } from 'rxjs';
import { metaDescription } from '../../../../i18n/traductions';
import { Notification } from '../../../core/models';
import { NotificationService } from '../../../core/services';
import { MatomoService } from '../../../core/services/matomo.service';
......@@ -39,9 +41,13 @@ export class ResultsComponent implements OnInit, OnDestroy {
private _datePipe: DatePipe,
private _matomoService: MatomoService,
private _viewportScroller: ViewportScroller,
private _meta: Meta,
) { }
ngOnInit() {
// Set the title and description for the research page
this._meta.updateTag({ name: 'description', content: metaDescription.research });
this.countResults = [];
this.paginator = {
pageIndex: this._datasetResearchService.pageIndex + 1,
......
......@@ -18,7 +18,7 @@
</div>
</div>
<div class="control button-research">
<button class="button is-medium" (click)="searchChanged()">
<button class="button is-medium" (click)="searchChanged()" aria-label="Rechercher">
<span class="icon">
<i class="fas fa-search" *ngIf="!isLoading;else spinner"></i>
<ng-template #spinner>
......
......@@ -8,7 +8,7 @@
</span>
</span>
<span class="icon is-small">
<svg xmlns="http://www.w3.org/2000/svg" id="chevron" viewBox="0 0 15 9">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 9">
<path
d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z"
class="brandcolor" />
......
import { Component, OnInit } from '@angular/core';
import { DomSanitizer, Meta, SafeHtml } from '@angular/platform-browser';
import { ActivatedRoute, Router } from '@angular/router';
import { EditorialisationService } from '../../services';
import { environment } from '../../../../environments/environment';
import { SafeHtml, DomSanitizer } from '@angular/platform-browser';
import { AppRoutes } from '../../../routes';
import { IPageHeaderInfo } from '../../../shared/models';
import { CMSContent } from '../../models';
import { AppRoutes } from '../../../routes';
import { ICMSPageLinks } from '../../../shared/models/cms-page.model';
import { EditorialisationService } from '../../services';
@Component({
selector: 'app-cms-page',
......@@ -25,6 +24,7 @@ export class CMSPageComponent implements OnInit {
private _editorialisationService: EditorialisationService,
private sanitizer: DomSanitizer,
private _router: Router,
private _meta: Meta,
) {
}
......@@ -36,8 +36,13 @@ export class CMSPageComponent implements OnInit {
if (page === undefined) {
page = '';
}
this._editorialisationService.getPage(page).subscribe((page) => {
this.page = page;
// Set the title and description for a CMS page
this._meta.updateTag({ name: 'description', content: this.page.content.excerpt });
if (!(this.page instanceof CMSContent)) {
this._router.navigate(['/', AppRoutes.page404.uri]);
} else {
......@@ -47,5 +52,4 @@ export class CMSPageComponent implements OnInit {
});
});
}
}
import { DatePipe } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { DomSanitizer, Meta, SafeHtml } from '@angular/platform-browser';
import { ActivatedRoute, Router } from '@angular/router';
import { notificationMessages } from '../../../../i18n/traductions';
import { ElasticsearchService } from '../../../elasticsearch/services/elasticsearch.service';
......@@ -32,6 +32,7 @@ export class CMSPostDetailComponent implements OnInit {
private _datePipe: DatePipe,
private _sanitizer: DomSanitizer,
private _elasticSearchService: ElasticsearchService,
private _meta: Meta,
) {
}
......@@ -39,6 +40,10 @@ export class CMSPostDetailComponent implements OnInit {
this.post = this._route.snapshot.data['post'];
if (this.post) {
// Set the title and description for a CMS post
this._meta.updateTag({ name: 'description', content: this.post.content.excerpt });
this.safePostContent = this._sanitizer.bypassSecurityTrustHtml(this.post.content.html);
// Construct header informations: (Date + tags) and title
......
import { Component, OnInit } from '@angular/core';
import { Meta } from '@angular/platform-browser';
import { Router } from '@angular/router';
import { Angulartics2Piwik } from 'angulartics2/piwik';
import { forkJoin } from 'rxjs/internal/observable/forkJoin';
import { environment } from '../../../../environments/environment';
import { notificationMessages } from '../../../../i18n/traductions';
import { metaDescription, notificationMessages } from '../../../../i18n/traductions';
import { Notification } from '../../../core/models';
import { NotificationService } from '../../../core/services';
import { DatasetResearchService } from '../../../datasets/services';
......@@ -37,9 +38,13 @@ export class HomeComponent implements OnInit {
private _notificationService: NotificationService,
private _router: Router,
private _angulartics2Piwik: Angulartics2Piwik,
private _meta: Meta,
) { }
ngOnInit() {
// Set the title and description for the home page
this._meta.updateTag({ name: 'description', content: metaDescription.home });
this._datasetResearchService.resetResearch(false);
this.latestPosts = [];
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment