Commit 0cd33442 authored by Matthieu BENOIST's avatar Matthieu BENOIST
Browse files

Merge branch 'DOS63936' into 'master'

Dos63936 - Major version updates and security fixes

See merge request !117
parents 58f0230d 38d602e4
Pipeline #10156 passed with stage
in 7 minutes and 44 seconds
......@@ -19,6 +19,7 @@ code_analysis:
- build
only:
- master
- development
before_script:
- export PATH=$PATH:/usr/local/bin/sonar-scanner-4.2.0.1873-linux/bin/
- export NODE_PATH=$NODE_PATH:`npm root -g`
......
# Stage 0, based on Node.js, to build and compile Angular
FROM node:12.13.0 as builder
FROM node:14.15.1 as builder
WORKDIR /app
......
......@@ -4,6 +4,15 @@
"newProjectRoot": "projects",
"projects": {
"webapp": {
"i18n": {
"locales": {
"fr": {
"translation": "src/i18n/messages.fr.xlf",
"baseHref": ""
},
"en": "src/i18n/messages.en.xlf"
}
},
"root": "",
"sourceRoot": "src",
"projectType": "application",
......@@ -11,6 +20,7 @@
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"aot": true,
"outputPath": "dist",
"index": "src/index.html",
"main": "src/main.ts",
......@@ -28,6 +38,15 @@
},
"configurations": {
"aot-fr": {
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
],
"localize": [
"fr"
],
"optimization": false,
"outputHashing": "all",
"sourceMap": true,
......@@ -37,15 +56,21 @@
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": false,
"i18nFile": "src/i18n/messages.fr.xlf",
"i18nFormat": "xlf",
"i18nLocale": "fr",
"fileReplacements": [{
"replace": "src/i18n/traductions.ts",
"with": "src/i18n/traductions.fr.ts"
}]
},
"aot-en": {
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "26kb"
}
],
"localize": [
"en"
],
"optimization": false,
"outputHashing": "all",
"sourceMap": true,
......@@ -54,12 +79,18 @@
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": false,
"i18nFile": "src/i18n/messages.en.xlf",
"i18nFormat": "xlf",
"i18nLocale": "en"
"buildOptimizer": false
},
"development-en": {
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "10kb"
}
],
"localize": [
"en"
],
"optimization": false,
"outputHashing": "all",
"sourceMap": true,
......@@ -70,13 +101,18 @@
"vendorChunk": false,
"buildOptimizer": false,
"fileReplacements": [],
"outputPath": "dist/en",
"i18nFile": "src/i18n/messages.en.xlf",
"i18nFormat": "xlf",
"i18nLocale": "en",
"baseHref": "/en/"
"outputPath": "dist"
},
"development-fr": {
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
],
"localize": [
"fr"
],
"optimization": false,
"outputHashing": "all",
"sourceMap": true,
......@@ -90,12 +126,18 @@
"replace": "src/i18n/traductions.ts",
"with": "src/i18n/traductions.fr.ts"
}],
"outputPath": "dist/fr",
"i18nFile": "src/i18n/messages.fr.xlf",
"i18nFormat": "xlf",
"i18nLocale": "fr"
"outputPath": "dist"
},
"production-en": {
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
],
"localize": [
"en"
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
......@@ -109,13 +151,18 @@
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.production.ts"
}],
"outputPath": "dist/en",
"i18nFile": "src/i18n/messages.en.xlf",
"i18nFormat": "xlf",
"i18nLocale": "en",
"baseHref": "/en/"
"outputPath": "dist"
},
"production-fr": {
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
],
"localize": [
"fr"
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
......@@ -134,10 +181,7 @@
"with": "src/i18n/traductions.fr.ts"
}
],
"outputPath": "dist/fr",
"i18nFile": "src/i18n/messages.fr.xlf",
"i18nFormat": "xlf",
"i18nLocale": "fr"
"outputPath": "dist"
}
}
},
......@@ -226,10 +270,10 @@
"schematics": {
"@schematics/angular:component": {
"prefix": "app",
"styleext": "scss"
"style": "scss"
},
"@schematics/angular:directive": {
"prefix": "app"
}
}
}
\ No newline at end of file
}
This diff is collapsed.
{
"name": "webapp",
"version": "2.6.16",
"version": "2.7.0",
"license": "GNU Affero General Public License v3.0",
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json",
"start-aot-fr": "ng serve --configuration=aot-fr",
"start-aot-en": "ng serve --configuration=aot-en",
"build-i18n:dev": "for lang in en fr; do node --max_old_space_size=4096 ./node_modules/@angular/cli/bin/ng build --configuration=development-$lang; done",
"build-i18n:prod": "for lang in en fr; do node --max_old_space_size=4096 ./node_modules/@angular/cli/bin/ng build --configuration=production-$lang; done",
"win-build-i18n:fr": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng build --configuration=development-fr",
"win-build-i18n:en": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng build --configuration=development-en",
"build-i18n:dev": "for lang in en fr; do node --max_old_space_size=4096 ./node_modules/@angular/cli/bin/ng build --configuration=development-$lang --delete-output-path false; done",
"build-i18n:prod": "for lang in en fr; do node --max_old_space_size=4096 ./node_modules/@angular/cli/bin/ng build --configuration=production-$lang --delete-output-path false; done",
"win-build-i18n:fr": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng build --configuration=development-fr --delete-output-path false",
"win-build-i18n:en": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng build --configuration=development-en --delete-output-path false",
"win-build-i18n": "npm run win-build-i18n:en && npm run win-build-i18n:fr",
"test": "ng test --browsers=Chrome --code-coverage=true",
"test:ci": "ng test --browsers=ChromeHeadlessCI --code-coverage=true --watch=false",
......@@ -21,21 +21,22 @@
},
"private": true,
"dependencies": {
"@angular/animations": "8.2.14",
"@angular/cdk": "^7.3.1",
"@angular/common": "8.2.14",
"@angular/compiler": "8.2.14",
"@angular/core": "8.2.14",
"@angular/forms": "8.2.14",
"@angular/platform-browser": "8.2.14",
"@angular/platform-browser-dynamic": "8.2.14",
"@angular/router": "8.2.14",
"@angular/animations": "9.1.12",
"@angular/cdk": "^9.0.0",
"@angular/common": "9.1.12",
"@angular/compiler": "9.1.12",
"@angular/core": "9.1.12",
"@angular/forms": "9.1.12",
"@angular/localize": "~9.1.12",
"@angular/platform-browser": "9.1.12",
"@angular/platform-browser-dynamic": "9.1.12",
"@angular/router": "9.1.12",
"@babel/compat-data": "^7.8.0",
"@turf/centroid": "^5.1.5",
"@turf/helpers": "^6.1.4",
"@turf/projection": "^6.0.1",
"@turf/turf": "^5.1.6",
"angulartics2": "^7.5.2",
"angulartics2": "^9.1.0",
"bulma": "^0.7.5",
"bulma-checkradio": "^2.1.0",
"bulma-slider": "^2.0.4",
......@@ -51,42 +52,41 @@
"ng-inline-svg": "^8.2.1",
"ng-lazyload-image": "^5.1.2",
"ngx-cookie-service": "^2.2.0",
"ngx-infinite-scroll": "^6.0.1",
"ngx-infinite-scroll": "^10.0.0",
"node-rsa": "^1.0.3",
"rxjs": "^6.5.4",
"tslib": "^1.10.0",
"xml2js": "^0.4.19",
"zone.js": "~0.9.1"
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.803.25",
"@angular/cli": "^8.3.23",
"@angular/compiler-cli": "8.2.14",
"@angular/language-service": "8.2.14",
"@angular-devkit/build-angular": "~0.901.12",
"@angular/cli": "^9.1.12",
"@angular/compiler-cli": "9.1.12",
"@angular/language-service": "9.1.12",
"@types/jasmine": "^2.8.12",
"@types/jasminewd2": "^2.0.6",
"@types/jwt-decode": "^2.2.1",
"@types/lodash.clonedeep": "^4.5.6",
"@types/mapbox-gl": "^1.7.0",
"@types/node": "^6.14.2",
"codelyzer": "^5.0.1",
"@types/node": "^12.11.1",
"codelyzer": "^5.1.2",
"jasmine-core": "~2.8.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "^4.0.0",
"karma": "^5.2.3",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "^1.4.3",
"karma-htmlfile-reporter": "^0.3.7",
"karma-jasmine": "^1.1.2",
"karma-jasmine-html-reporter": "^0.2.2",
"ng2-mock-component": "0.0.6",
"protractor": "^5.4.1",
"protractor": "^7.0.0",
"rxjs-tslint": "^0.1.8",
"sass-recursive-map-merge": "^1.0.1",
"stylelint-config-recommended": "^2.2.0",
"stylelint-config-standard": "^18.3.0",
"ts-node": "~4.1.0",
"tslint": "^5.12.1",
"tslint-config-airbnb": "^5.11.1",
"typescript": "3.5.3",
"typescript": "3.8.3",
"webpack-bundle-analyzer": "^3.1.0"
}
}
......@@ -36,10 +36,10 @@
(keyup)="toUppercase('lastname')"
[ngClass]="{'has-error': fieldIsInvalid('lastname'), 'is-valid': fieldIsValid('lastname')}">
<span class="icon is-small is-right is-icon-success" *ngIf="fieldIsValid('lastname')">
<i class="fas fa-check-circle"></i>
<span class="fas fa-check-circle"></span>
</span>
<span class="icon is-small is-right is-icon-warning" *ngIf="fieldIsInvalid('lastname')">
<i class="fas fa-exclamation-circle"></i>
<span class="fas fa-exclamation-circle"></span>
</span>
</p>
......@@ -61,10 +61,10 @@
formControlName="firstname" [attr.autocomplete]="'given-name'"
[ngClass]="{'has-error': fieldIsInvalid('firstname'), 'is-valid': fieldIsValid('firstname')}">
<span class="icon is-small is-right is-icon-success" *ngIf="fieldIsValid('firstname')">
<i class="fas fa-check-circle"></i>
<span class="fas fa-check-circle"></span>
</span>
<span class="icon is-small is-right is-icon-warning" *ngIf="fieldIsInvalid('firstname')">
<i class="fas fa-exclamation-circle"></i>
<span class="fas fa-exclamation-circle"></span>
</span>
</p>
......@@ -86,10 +86,10 @@
<input id="email" class="input" type="email" formControlName="email" [attr.autocomplete]="'email'"
[ngClass]="{'has-error': fieldIsInvalid('email'), 'is-valid': fieldIsValid('email')}">
<span class="icon is-small is-right is-icon-success" *ngIf="fieldIsValid('email')">
<i class="fas fa-check-circle"></i>
<span class="fas fa-check-circle"></span>
</span>
<span class="icon is-small is-right is-icon-warning" *ngIf="fieldIsInvalid('email')">
<i class="fas fa-exclamation-circle"></i>
<span class="fas fa-exclamation-circle"></span>
</span>
</p>
......@@ -113,11 +113,11 @@
[ngClass]="{'has-error': emailConfirmationError || fieldIsInvalid('emailConfirmation'), 'is-valid': !emailConfirmationError && fieldIsValid('emailConfirmation')}">
<span class="icon is-small is-right is-icon-success"
*ngIf="!emailConfirmationError && fieldIsValid('emailConfirmation')">
<i class="fas fa-check-circle"></i>
<span class="fas fa-check-circle"></span>
</span>
<span class="icon is-small is-right is-icon-warning"
*ngIf="emailConfirmationError || fieldIsInvalid('emailConfirmation')">
<i class="fas fa-exclamation-circle"></i>
<span class="fas fa-exclamation-circle"></span>
</span>
</p>
......@@ -161,7 +161,7 @@
aria-controls="dropdown-menu" [disabled]="formDisabled">
<span>{{ selectedSubject !== null && selectedSubject.value !== null ? selectedSubject.value : contactTrad.subjectPlaceholder }}</span>
<span class="icon is-small">
<i class="fas fa-angle-down" aria-hidden="true"></i>
<span class="fas fa-angle-down" aria-hidden="true"></span>
</span>
</button>
</div>
......@@ -178,10 +178,10 @@
<input id="subjectInput" class="input" type="text" formControlName="subject"
[ngClass]="{'has-error': fieldIsInvalid('subject'), 'is-valid': fieldIsValid('subject')}">
<span class="icon is-small is-right is-icon-success" *ngIf="fieldIsValid('subject')">
<i class="fas fa-check-circle"></i>
<span class="fas fa-check-circle"></span>
</span>
<span class="icon is-small is-right is-icon-warning" *ngIf="fieldIsInvalid('subject')">
<i class="fas fa-exclamation-circle"></i>
<span class="fas fa-exclamation-circle"></span>
</span>
</p>
......@@ -199,10 +199,10 @@
<textarea id="text" class="textarea has-fixed-size" type="textarea" formControlName="text"
[ngClass]="{'has-error': fieldIsInvalid('text'), 'is-valid': fieldIsValid('text')}" rows=6></textarea>
<span class="icon is-small is-right is-icon-success" *ngIf="fieldIsValid('text')">
<i class="fas fa-check-circle"></i>
<span class="fas fa-check-circle"></span>
</span>
<span class="icon is-small is-right is-icon-warning" *ngIf="fieldIsInvalid('text')">
<i class="fas fa-exclamation-circle"></i>
<span class="fas fa-exclamation-circle"></span>
</span>
</p>
......
......@@ -4,19 +4,19 @@
<ul>
<li>
<a href="http://www.facebook.com/legrandlyon" title="Facebook (new window)" i18n-title="@@footer.facebook"
target="_blank" rel="noopener">
target="_blank" rel="noopener noreferrer">
<img class="social-network-link" src="./assets/img/icon_fb.svg" i18n-alt="@@footer.facebook" alt="Facebook (new window)">
</a>
</li>
<li class="left-border">
<a href="https://twitter.com/grandlyon" title="Twitter (new window)" i18n-title="@@footer.twitter"
target="_blank" rel="noopener">
target="_blank" rel="noopener noreferrer">
<img class="social-network-link" src="./assets/img/icon_twi.svg" i18n-alt="@@footer.twitter" alt="Twitter (new window)">
</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" rel="noopener">
title="RSS Feed (new window)" i18n-title="@@footer.rss" target="_blank" rel="noopener noreferrer">
<img class="social-network-link" src="./assets/img/icon_rss.svg" i18n-alt="@@footer.rss" alt="RSS Feed (new window)">
</a>
</li>
......@@ -67,7 +67,7 @@
<div class="column metropole">
<ul>
<li>
<a href="https://www.grandlyon.com/" class="metropolis-website-link" target="_blank" rel="noopener">
<a href="https://www.grandlyon.com/" class="metropolis-website-link" target="_blank" rel="noopener noreferrer">
<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="">
<span i18n="@@footer.metropole.site">A Lyon Metropolis website</span>
......
......@@ -25,25 +25,17 @@ header {
order: 1
}
;
.navbar-header-item:nth-of-type(2) {
order: 2
}
;
.navbar-header-item:nth-of-type(3) {
order: 4
}
;
.navbar-header-item:nth-of-type(4) {
order: 3
}
;
}
}
......
......@@ -109,7 +109,6 @@
</li>
</ul>
</nav>
th
<div class="bottom-menu-section">
<span class="version-item">Version {{ env.version }}</span>
<span class="language-fr language" [ngClass]="{'is-active': currentLanguage() === env.angularAppHost.fr}"
......
......@@ -16,6 +16,6 @@
</div>
</ng-container>
<p class="app-notification-content">{{ notification.message }}</p>
<button class="close-button" (click)="hide(i)"><i class="fas fa-times"></i></button>
<button class="close-button" (click)="hide(i)"><span class="fas fa-times"></span></button>
</div>
</div>
import { Injectable } from '../../../../node_modules/@angular/core';
import { Injectable as Injectable_1 } from "@angular/core";
@Injectable_1()
@Injectable()
export class NavigationHistoryService {
history: string[] = [];
......
......@@ -21,7 +21,7 @@
<span>{{ resource.name }} </span>
<span class="icon tooltip is-tooltip-multiline pirate-alert"
[attr.data-tooltip]="getMessageWarning(resource)" *ngIf="getMessageWarning(resource)">
<i class="fas fa-exclamation-triangle fa-lg"></i>
<span class="fas fa-exclamation-triangle fa-lg"></span>
</span>
</div>
<div class="description-and-formats is-hidden-mobile">
......
......@@ -56,7 +56,7 @@
<ng-template #other_ressources>
<ng-container *ngIf="otherResources">
<div class="resource-other" *ngFor="let other of otherResources">
<div class="resource-other-title">
<div class="resource-other-title" *ngIf="other.name !== 'null' ">
<span>{{ other.name }}</span>
</div>
<div class="resource-other-link">
......
......@@ -4,7 +4,7 @@
</span>
<div class="partner" *ngFor="let producer of producers">
<div class="content">
<div *ngIf="producer.logo && producer.logo != 'null'"><img aria-hidden="true" [src]="producer.logo"></div>
<div *ngIf="producer.logo && producer.logo != 'null'"><img aria-hidden="true" [src]="producer.logo" alt=""></div>
<p>{{producer.organisationName}}</p>
</div>
<p *ngIf="producer.individualName && producer.individualName !== 'null'">
......
......@@ -119,7 +119,6 @@
box-shadow: 0px 6px 12px rgba(49, 110, 180, 0.35);
a {
display: block;
height: 100%;
width: 100%;
display: flex;
......@@ -149,7 +148,7 @@
.text {
text-decoration: none;
}
}
......@@ -226,7 +225,7 @@
.post-description {
flex-grow: 1;
background-color: #ffff;
border-radius: 0 0 8pw 8px;
border-radius: 0 0 8px 8px;
padding: 1rem;
.post-description-date {
......
......@@ -32,7 +32,7 @@
i18n-placeholder="@@dataset.data.filterReccordPlaceholder" (keydown.enter)="searchChanged()" />
<span class="icon is-small is-right reset-research-icon" *ngIf="searchInput.value"
(click)="resetResearch()">
<i class="fas fa-times-circle"></i>
<span class="fas fa-times-circle"></span>
</span>
</div>
<div class="control button-research">
......@@ -40,7 +40,7 @@
<span class="icon">
<img src="./assets/img/picto_search.svg" i18n-alt="@@dataset.data.filterReccordPlaceholder" alt="Filter records" *ngIf="!isLoading; else spinner">
<ng-template #spinner>
<i class="fas fa-spinner fa-spin"></i>
<span class="fas fa-spinner fa-spin"></span>
</ng-template>
</span>
</button>
......@@ -114,7 +114,7 @@
i18n-placeholder="@@dataset.data.filterReccordPlaceholder" (keydown.enter)="searchChanged()" />
<span class="icon is-small is-right reset-research-icon" *ngIf="searchInput.value"
(click)="resetResearch()">
<i class="fas fa-times-circle"></i>
<span class="fas fa-times-circle"></span>
</span>
</div>
<div class="control button-research">
......@@ -122,7 +122,7 @@
<span class="icon">
<img src="./assets/img/picto_search.svg" alt="Picto search" *ngIf="!isLoading; else spinner">
<ng-template #spinner>
<i class="fas fa-spinner fa-spin"></i>
<span class="fas fa-spinner fa-spin"></span>
</ng-template>
</span>
</button>
......
......@@ -6,10 +6,10 @@
(keydown.enter)="sortBy(key)" [tabindex]="isDisplayed ? 0 : -1" [attr.role]="'columnheader'">
<span class="sort-icons">
<span class="icon">
<i class="fas fa-sort-up" [ngClass]="{'icon-red': sortValue.includes(key) && sortOrder === 'desc'}"></i>
<span class="fas fa-sort-up" [ngClass]="{'icon-red': sortValue === key && sortOrder === 'desc'}"></span >
</span>
<span class="icon">
<i class="fas fa-sort-down" [ngClass]="{'icon-red': sortValue.includes(key) && sortOrder === 'asc'}"></i>
<span class="fas fa-sort-down" [ngClass]="{'icon-red': sortValue === key && sortOrder === 'asc'}"></span >
</span>
</span>
<span class="column-title" [ngClass]="{'active': sortValue === key}">{{ key }}</span>
......