diff --git a/package-lock.json b/package-lock.json index bde2edac2f3f2de8845c267f09d130fec0c20306..275a3c52bb3bc96470e737f34512d6d2e3aa47a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "webapp", - "version": "2.3.1", + "version": "2.3.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1418,6 +1418,7 @@ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, + "optional": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" @@ -2673,7 +2674,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "dev": true, + "optional": true }, "constants-browserify": { "version": "1.0.0", @@ -3068,7 +3070,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true + "dev": true, + "optional": true }, "depd": { "version": "1.1.2", @@ -4127,7 +4130,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -4148,12 +4152,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4168,17 +4174,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -4295,7 +4304,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -4307,6 +4317,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4321,6 +4332,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4328,12 +4340,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4352,6 +4366,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -4432,7 +4447,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -4444,6 +4460,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -4529,7 +4546,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -4565,6 +4583,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4584,6 +4603,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4627,12 +4647,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -4641,6 +4663,7 @@ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", "dev": true, + "optional": true, "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -4653,6 +4676,7 @@ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, + "optional": true, "requires": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", @@ -4669,6 +4693,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4678,6 +4703,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4717,7 +4743,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true + "dev": true, + "optional": true }, "get-stream": { "version": "3.0.0", @@ -4965,7 +4992,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true + "dev": true, + "optional": true }, "has-value": { "version": "1.0.0", @@ -6400,6 +6428,7 @@ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, + "optional": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", @@ -6412,7 +6441,8 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "dev": true, + "optional": true } } }, @@ -6683,7 +6713,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true + "dev": true, + "optional": true }, "map-visit": { "version": "1.0.0", @@ -7385,6 +7416,7 @@ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, + "optional": true, "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", @@ -8556,6 +8588,7 @@ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, + "optional": true, "requires": { "load-json-file": "^1.0.0", "normalize-package-data": "^2.3.2", @@ -8567,6 +8600,7 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, + "optional": true, "requires": { "graceful-fs": "^4.1.2", "pify": "^2.0.0", @@ -8577,7 +8611,8 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "dev": true, + "optional": true } } }, @@ -8586,6 +8621,7 @@ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, + "optional": true, "requires": { "find-up": "^1.0.0", "read-pkg": "^1.0.0" @@ -8596,6 +8632,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, + "optional": true, "requires": { "path-exists": "^2.0.0", "pinkie-promise": "^2.0.0" @@ -8606,6 +8643,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, + "optional": true, "requires": { "pinkie-promise": "^2.0.0" } @@ -11678,6 +11716,7 @@ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, + "optional": true, "requires": { "string-width": "^1.0.2 || 2" } diff --git a/src/app/core/components/main/header/header.component.ts b/src/app/core/components/main/header/header.component.ts index f7b496c205ff30be56a348c19c3bb53d4ed0c264..aadc9987a2771645fa0f2c5c9ea0a841d410d515 100644 --- a/src/app/core/components/main/header/header.component.ts +++ b/src/app/core/components/main/header/header.component.ts @@ -1,9 +1,10 @@ -import { Component, OnInit, Output, EventEmitter } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { AppRoutes } from '../../../../routes'; import { DatasetResearchService } from '../../../../geosource/services'; import { Router, NavigationEnd } from '@angular/router'; import { UserService } from '../../../../user/services'; import { AppStateService } from '../../../services'; +import { Angulartics2Piwik } from 'angulartics2/piwik'; @Component({ selector: 'app-header', @@ -23,6 +24,7 @@ export class HeaderComponent implements OnInit { private _router: Router, private _userService: UserService, private _appStateService: AppStateService, + private _angulartics2Piwik: Angulartics2Piwik, ) { } ngOnInit() { @@ -48,6 +50,7 @@ export class HeaderComponent implements OnInit { toggleBurger() { this.isBurgerActive = !this.isBurgerActive; this._appStateService.changeMenuState(this.isBurgerActive); + this._angulartics2Piwik.eventTrack('BurgerMenu', { category: 'Navigation', label: 'BurgerManu', value: 1 }); } toggleUserDropdown() { diff --git a/src/app/editorialisation/components/cms-post-detail/cms-post-detail.component.ts b/src/app/editorialisation/components/cms-post-detail/cms-post-detail.component.ts index d916926c10ba58b81eaaa7f34011cf778cc7008f..c04ec94d7b611a984a33ab7aad5785762927df71 100644 --- a/src/app/editorialisation/components/cms-post-detail/cms-post-detail.component.ts +++ b/src/app/editorialisation/components/cms-post-detail/cms-post-detail.component.ts @@ -22,6 +22,7 @@ export class CMSPostDetailComponent implements OnInit { safePostContent: SafeHtml; pageHeaderInfo: IPageHeaderInfo = { title: '', + hasCopyLinkBtn: true, }; relations: { datasetsMetadata: Metadata[]; diff --git a/src/app/editorialisation/components/home/home.component.html b/src/app/editorialisation/components/home/home.component.html index 3de2090bcf476fcf315a28c9496c0a053b1bd1e4..bdb35223402013fecfa1bedf352d1fd23211da1b 100644 --- a/src/app/editorialisation/components/home/home.component.html +++ b/src/app/editorialisation/components/home/home.component.html @@ -15,7 +15,7 @@ </div> <div class="search column is-7-desktop is-8-tablet "> <app-search-bar class="app-search-bar"></app-search-bar> - <a class="explore-link" [routerLink]="['/', AppRoutes.research.uri]"> + <a class="explore-link" [routerLink]="['/', AppRoutes.research.uri]" (click)="trackExploreButtonEvent()"> <button class="button explore-button" i18n="@@home.explore">Explore</button> </a> </div> diff --git a/src/app/editorialisation/components/home/home.component.ts b/src/app/editorialisation/components/home/home.component.ts index 15575e274fc4b5b6a3ae9435199f96d553ad56fb..8991a5659666e2003c8541f4c5ccbb567681b777 100644 --- a/src/app/editorialisation/components/home/home.component.ts +++ b/src/app/editorialisation/components/home/home.component.ts @@ -9,6 +9,7 @@ import { forkJoin } from 'rxjs/internal/observable/forkJoin'; import { NotificationService } from '../../../core/services'; import { Notification } from '../../../core/models'; import { notificationMessages } from '../../../../i18n/traductions'; +import { Angulartics2Piwik } from 'angulartics2/piwik'; @Component({ selector: 'app-home', @@ -34,6 +35,7 @@ export class HomeComponent implements OnInit { private _datasetResearchService: DatasetResearchService, private _notificationService: NotificationService, private _router: Router, + private _angulartics2Piwik: Angulartics2Piwik, ) { } ngOnInit() { @@ -100,4 +102,7 @@ export class HomeComponent implements OnInit { this._router.navigate(['/', AppRoutes.research.uri]); } + trackExploreButtonEvent() { + this._angulartics2Piwik.eventTrack('ExploreButton', { category: 'HomePage', label: 'Explore', value: 1 }); + } } diff --git a/src/app/shared/components/page-header/page-header.component.html b/src/app/shared/components/page-header/page-header.component.html index 70e7aa656831749ffd6fc9a586131a04456844d3..d88d1bc275238bafe4ea3fdc50370ca1c7ab5b52 100644 --- a/src/app/shared/components/page-header/page-header.component.html +++ b/src/app/shared/components/page-header/page-header.component.html @@ -17,4 +17,13 @@ <span>{{ pageInfo.subtitle }}</span> </div> </div> + + <button *ngIf="pageInfo.hasCopyLinkBtn" class="button copy-link-button has-tooltip-left tooltip" type="button" + (click)="copyToClipboard()" [attr.data-tooltip]="messageClipboard"> + <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" viewBox="0 0 20 20"> + <path fill="#818080" fill-rule="evenodd" + d="M1.852 7.777a2.619 2.619 0 0 1 0-3.703l2.222-2.222a2.619 2.619 0 0 1 3.704 0l2.963 2.963a2.619 2.619 0 0 1 0 3.703l-.37.37.74.741.37-.37a2.619 2.619 0 0 1 3.704 0l2.963 2.963a2.619 2.619 0 0 1 0 3.704l-2.222 2.222a2.619 2.619 0 0 1-3.704 0L9.26 15.185a2.619 2.619 0 0 1 0-3.704l.37-.37-.74-.741-.37.37a2.619 2.619 0 0 1-3.704 0L1.852 7.777zm7.037-.37l-.74-.74a1.048 1.048 0 0 0-1.482 1.48l.74.742-.37.37a.524.524 0 0 1-.74 0L3.332 6.296a.524.524 0 0 1 0-.74l2.223-2.223a.524.524 0 0 1 .74 0L9.26 6.296a.524.524 0 0 1 0 .74l-.37.371zm2.222 5.185l-.37.37a.524.524 0 0 0 0 .742l2.963 2.962a.524.524 0 0 0 .74 0l2.223-2.222a.524.524 0 0 0 0-.74l-2.963-2.963a.524.524 0 0 0-.741 0l-.37.37.74.74a1.047 1.047 0 1 1-1.481 1.482l-.74-.74z" + clip-rule="evenodd" /> + </svg> + </button> </div> \ No newline at end of file diff --git a/src/app/shared/components/page-header/page-header.component.scss b/src/app/shared/components/page-header/page-header.component.scss index 73b4cc657d1b5752a3ab56cebbc6ec36728a89cd..208fe83c15e5655296bc4d33610177359689e2db 100644 --- a/src/app/shared/components/page-header/page-header.component.scss +++ b/src/app/shared/components/page-header/page-header.component.scss @@ -96,3 +96,12 @@ line-height: 1.15; color: $brand-color; } + +.copy-link-button { + position: absolute; + top: 10px; + right: 10px; + padding: 0; + height: 2.25rem; + width: 2.25rem; +} \ No newline at end of file diff --git a/src/app/shared/components/page-header/page-header.component.ts b/src/app/shared/components/page-header/page-header.component.ts index 7f1899155f8a5646f1bbd9a7fd98b4d2ba5938a6..5e83e1bafbd1e9c92b5bd29b19c3d3a06c504dcd 100644 --- a/src/app/shared/components/page-header/page-header.component.ts +++ b/src/app/shared/components/page-header/page-header.component.ts @@ -3,6 +3,9 @@ import { Router } from '@angular/router'; import { AppRoutes } from '../../../routes'; import { NavigationHistoryService } from '../../../core/services'; import { IPageHeaderInfo } from '../../models'; +import { buttonCopyLinkToCliboardMessages } from '../../../../i18n/traductions'; +import { Angulartics2Piwik } from 'angulartics2/piwik'; + @Component({ selector: 'app-page-header', @@ -14,10 +17,12 @@ export class PageHeaderComponent implements OnInit { constructor( private _navigationHistoryService: NavigationHistoryService, private _router: Router, + private _angulartics2Piwik: Angulartics2Piwik, ) { } @Input() pageInfo: IPageHeaderInfo; @Input() customGoToPreviousPage: any; + messageClipboard: string = buttonCopyLinkToCliboardMessages.hover; ngOnInit() { } @@ -36,4 +41,32 @@ export class PageHeaderComponent implements OnInit { } } + copyToClipboard() { + const el = document.createElement('input'); // Create a <input> element + el.value = window.location.href; // Set its value to the string that you want copied + el.setAttribute('readonly', ''); // Make it readonly to be tamper-proof + el.style.position = 'absolute'; + el.style.left = '-9999px'; // Move outside the screen to make it invisible + document.body.appendChild(el); // Append the <input> element to the HTML document + const selected = + document.getSelection().rangeCount > 0 // Check if there is any content selected previously + ? document.getSelection().getRangeAt(0) // Store selection if found + : false; // Mark as false to know no selection existed before + el.select(); // Select the <input> content + document.execCommand('copy'); // Copy - only works as a result of a user action (e.g. click events) + document.body.removeChild(el); // Remove the <input> element + if (selected) { // If a selection existed before copying + document.getSelection().removeAllRanges(); // Unselect everything on the HTML document + document.getSelection().addRange(selected); // Restore the original selection + } + this.messageClipboard = buttonCopyLinkToCliboardMessages.copied; + + this._angulartics2Piwik.eventTrack('ShareArticle', { category: 'Edito', label: window.location.href, value: 1}); + + setTimeout(() => { + this.messageClipboard = buttonCopyLinkToCliboardMessages.hover; + // tslint:disable-next-line:align + }, 2000); + } + } diff --git a/src/app/shared/models/cms-page.model.ts b/src/app/shared/models/cms-page.model.ts index 9c84a9c15a4cbbff139295b5ecd6a58322f9161c..49254ac9f222b513473285c66da66562a18643a8 100644 --- a/src/app/shared/models/cms-page.model.ts +++ b/src/app/shared/models/cms-page.model.ts @@ -4,6 +4,7 @@ export interface IPageHeaderInfo { surtitle?: string; subtitle?: string; hasBetaStyle?: boolean; + hasCopyLinkBtn?: boolean } export interface ICMSPageLinks { diff --git a/src/i18n/traductions.fr.ts b/src/i18n/traductions.fr.ts index 9b158ebe03ff4188f6cfbb3ae183dc9700f74f99..c26dfe31aaee01f60e94117e334d4a1777408bec 100644 --- a/src/i18n/traductions.fr.ts +++ b/src/i18n/traductions.fr.ts @@ -308,3 +308,8 @@ export const reusesTypes = { web: 'Site web', article: 'Article', }; + +export const buttonCopyLinkToCliboardMessages = { + hover: 'Copier le lien', + copied: 'CopiƩ !' +}; diff --git a/src/i18n/traductions.ts b/src/i18n/traductions.ts index 307b72d9b26668f375ffd70bd9f51d3ab56780ee..84dfc34ca36f341b86ed34261c8c28edafeabc27 100644 --- a/src/i18n/traductions.ts +++ b/src/i18n/traductions.ts @@ -308,3 +308,8 @@ export const reusesTypes = { web: 'Website', article: 'Article', }; + +export const buttonCopyLinkToCliboardMessages = { + hover: 'Copy the link', + copied: 'Copied!' +};