diff --git a/Gruntfile.js b/Gruntfile.js index d21c2cb..1f0ad14 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -12,26 +12,29 @@ module.exports = function(grunt) { font: { icons: { - src: ['app/public/fonts/svg-icons/*.svg'], - destCss: 'app/public/styles/less/icons.less', - destFonts: 'app/public/fonts/icons.woff', + src: ['front/src/fonts/svg-icons/*.svg'], + destCss: 'front/src/less/icons.less', + destFonts: 'front/src/fonts/icons.woff', // Optional: Custom routing of font filepaths for CSS cssRouter: function (fontpath) { var pathArray = fontpath.split('/'); var fileName = pathArray[pathArray.length - 1]; - return '/public/fonts/' + fileName; + return '/front/fonts/' + fileName; } } }, less: { all: { - files: { - 'app/public/styles/main.css': [ 'app/public/styles/less/main.less' ], - 'app/public/styles/index.css': [ 'app/public/styles/less/index.less' ], - 'app/public/styles/launchTest.css': [ 'app/public/styles/less/launchTest.less' ], - 'app/public/styles/results.css': [ 'app/public/styles/less/results.less' ] - } + files: [ + { + expand: true, + cwd: 'front/src/less/', + src: ['**/*.less'], + dest: 'front/src/css/', + ext: '.css' + } + ] } }, jshint: { @@ -51,6 +54,9 @@ module.exports = function(grunt) { icons: { src: ['tmp'] }, + dev: { + src: ['front/src/css'] + }, coverage: { src: ['coverage/'] } @@ -166,7 +172,8 @@ module.exports = function(grunt) { ]); grunt.registerTask('dev', [ - 'express:dev' + 'clean:dev', + 'less' ]); grunt.registerTask('test', [ diff --git a/app/public/scripts/app.js b/app/public/scripts/app.js index 3b54686..ec4f9b9 100644 --- a/app/public/scripts/app.js +++ b/app/public/scripts/app.js @@ -1,5 +1,6 @@ angular.module('YellowLabTools', [ 'Results', + 'Runs', 'ngModal', 'ShowOffendersDirective' ]); diff --git a/front/src/css/dashboard.css b/front/src/css/dashboard.css new file mode 100644 index 0000000..8992c43 --- /dev/null +++ b/front/src/css/dashboard.css @@ -0,0 +1,479 @@ +/* Timeline colors, related to Window Performances */ +.resultsMenu { + margin-top: 2em; +} +.resultsMenu .menuItem { + display: inline-block; + margin: 1em; + width: 8em; + height: 7em; + color: #fff; + border: 3px solid #fff; + border-radius: 0.5em; + cursor: pointer; + text-decoration: none; +} +.resultsMenu .back { + color: #5e2846; + border-color: #5e2846; +} +.resultsMenu .menuItem div { + padding-top: 0.5em; + font-size: 3em; +} +.resultsMenu .active, +.resultsMenu .menuItem.active:hover { + color: #ffa319; + border-color: #ffa319; +} +.resultsMenu .menuItem:hover { + color: #ffa319; +} +.resultsMenu span { + position: relative; + top: 0.5em; +} +.testedUrl { + color: inherit; +} +h4 { + margin-bottom: 0.5em; +} +.summary, +.metrics, +.execution { + margin-top: 2em; + padding: 1em; + background: #fff; + color: #000; + border-radius: 0.5em; + text-align: left; +} +.notations { + display: table; + width: 90%; + margin: 0 10%; + border-spacing: 1em; +} +.notations > div { + display: table-row; +} +.notations > div > div { + display: table-cell; + height: 2.5em; + vertical-align: middle; +} +.notations .notation { + font-weight: bold; + text-align: center; +} +.notations .criteria { + font-weight: normal; +} +.notations .A, +.notations .B, +.notations .C, +.notations .D, +.notations .E, +.notations .F, +.notations .NA { + width: 2.5em; + font-size: 2em; + text-align: center; + border-radius: 0.5em; + font-weight: bold; +} +.notations .grade .A, +.notations .grade .B, +.notations .grade .C, +.notations .grade .D, +.notations .grade .E, +.notations .grade .F, +.notations .grade .NA { + width: 1em; + height: 1em; + font-size: 1em; + color: transparent; + position: relative; + top: 0.15em; +} +.notations .A { + /* green */ + background: #00DB61; +} +.notations .B { + /* green */ + background: #CAD600; +} +.notations .C { + /* yellow */ + background: #FFD119; +} +.notations .D { + /* orange */ + background: #FFA319; +} +.notations .E { + /* red */ + background: #FF6600; +} +.notations .F { + /* red */ + background: #FF1919; +} +.notations .NA { + /* Non applicable */ + background: #CCC; +} +.notations .icon-eye { + color: #9c4274; + cursor: pointer; +} +.notations .criteria .table { + width: 75%; +} +.notations .criteria .label { + width: 70%; +} +.notations .criteria .result { + width: 20%; + font-weight: bold; + white-space: nowrap; + text-align: center; +} +.notations .warning .label, +.notations .warning .result { + color: #FF1919; +} +.notations .criteria .info { + width: 10%; + text-align: center; +} +.notations .criteria .icon-question { + color: #f1c40f; + cursor: pointer; +} +.timeline { + margin: 2em 0 5em; +} +.timeline .chart { + position: relative; + width: 100%; + border-bottom: 1px solid #000; +} +.timeline .startTime, +.timeline .endTime { + position: absolute; + bottom: 0.5em; + font-size: 0.8em; +} +.timeline .startTime { + left: 0em; +} +.timeline .endTime { + right: 0em; +} +.timeline .chartPoints { + display: table; + height: 100px; + width: 99%; + margin: 0 auto; +} +.timeline .interval { + display: table-cell; + position: relative; + height: 100px; + width: 0.5%; +} +.timeline .interval .color { + position: absolute; + bottom: 0; + width: 100%; +} +.timeline div.interval:hover { + background: #9C4274; +} +.timeline .interval:hover .color { + background: #F04DA7; +} +.timeline .domComplete.interval { + background: #ede3ff; +} +.timeline .domComplete .color { + background: #c2a3ff; +} +.timeline .domContentLoadedEnd.interval { + background: #d8f0f0; +} +.timeline .domContentLoadedEnd .color { + background: #7ecccc; +} +.timeline .domContentLoaded.interval { + background: #e0ffd1; +} +.timeline .domContentLoaded .color { + background: #a7e846; +} +.timeline .domInteractive.interval { + background: #fffccc; +} +.timeline .domInteractive .color { + background: #ffe433; +} +.timeline .domCreation.interval { + background: #ffe0cc; +} +.timeline .domCreation .color { + background: #ff6600; +} +.timeline .tooltip.detailsOverlay { + position: absolute; + display: none; + width: auto; + padding: 0.5em 1em; + top: -1.5em; + right: 1em; +} +.timeline .interval:hover .tooltip { + display: block; +} +.timeline .legend { + display: table; + width: 100%; + margin-top: 1em; +} +.timeline .legend > div { + display: table-row; +} +.timeline .legend > div > div { + position: relative; + display: table-cell; + margin-top: 1em; +} +.timeline .titles { + font-weight: bold; +} +.timeline .titles > div { + padding: 0 1em 0 2em; +} +.timeline .tips { + font-size: 0.7em; +} +.timeline .tips > div { + padding: 1em 1em 0 0; +} +.timeline .legend .color { + display: block; + position: absolute; + left: 0; + height: 1.5em; + width: 1.5em; + border-radius: 0.2em; +} +.metrics h4 { + padding-left: 2em; +} +.metrics .module { + padding-left: 4em; + padding-top: 0.5em; +} +.metrics .legend { + font-style: italic; + color: #aaa; +} +.metrics .offenders { + padding-left: 0em; + font-size: 0.8em; +} +.metrics .offenders div { + cursor: pointer; +} +.metrics .offenders ul { + margin-top: 0.5em; +} +.filters { + margin: 1em 0; + padding: 0.5em; + border: 1px dotted #aaa; +} +.slowRequestsLimit { + width: 3em; + font-size: 1em; + text-align: right; + border: 1px solid #aaa; +} +input.textFilter { + box-shadow: none; + font-size: 1em; + padding: 0 0.2em; + border: 1px solid #aaa; + border-radius: none; + width: 15em; +} +.table { + display: table; + width: 100%; + border-spacing: 0.25em; +} +.table > div { + display: table-row; +} +.table > .headers > div { + font-weight: bold; + padding: 0.5em 1em; +} +.table > div > div { + padding: 0.1em 1em; + background: #f2f2f2; + display: table-cell; + text-align: left; +} +.table > div.jsError > .type, +.table > div.jsError > .value { + color: #e74c3c; + font-weight: bold; +} +.table > div.windowPerformance > div, +.table > div.windowPerformance > div.startTime { + background: #EBD8E2; +} +.table > div.showingDetails > div { + background: #f1c40f; +} +.table > div > .index { + color: #bbb; +} +.table > div > .type { + white-space: nowrap; +} +.table > div > .value { + width: 70%; + word-break: break-all; +} +.table > div > .details { + position: relative; +} +.table .details .icon-question { + color: #f1c40f; + cursor: pointer; +} +.table .details .icon-warning { + cursor: pointer; +} +.detailsOverlay { + position: absolute; + right: 3em; + top: -3em; + width: 45em; + min-height: 1em; + padding: 0 1em 1em; + background: #fff; + border: 2px solid #f1c40f; + border-radius: 0.5em; + z-index: 1; +} +@media screen and (max-width: 1024px) { + .detailsOverlay { + width: 25em; + } +} +.detailsOverlay .closeBtn { + position: absolute; + top: 0.5em; + right: 0.5em; + color: #f1c40f; + cursor: pointer; +} +.detailsOverlay .advice { + color: #e74c3c; + font-weight: bold; +} +.detailsOverlay .trace { + word-break: break-all; +} +.table > div > .duration, +.table > div > .startTime { + text-align: center; + white-space: nowrap; +} +.table > div > .startTime.domComplete { + background: #ede3ff; +} +.table > div > .startTime.domContentLoadedEnd { + background: #d8f0f0; +} +.table > div > .startTime.domContentLoaded { + background: #e0ffd1; +} +.table > div > .startTime.domInteractive { + background: #fffccc; +} +.table > div > .startTime.domCreation { + background: #ffe0cc; +} +.table .icon-warning { + color: #e74c3c; +} +/**** NgModal popin (have a look inside bower_components) ****/ +.ng-modal { + position: fixed; + z-index: 9999; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-align: left; +} +.ng-modal-overlay { + position: absolute; + z-index: 9999; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: #000; + opacity: 0.5; +} +.ng-modal-dialog { + z-index: 10000; + position: absolute; + top: 50%; + left: 50%; + width: 50%; + transform: translate(-50%, -50%); + -webkit-transform: translate(-50%, -50%); + background-color: #fff; + padding: 10px; + border: 3px solid #f1c40f; + border-radius: 0.5em; + color: #000; +} +.ng-modal-dialog-content { + overflow-x: hidden; + overflow-y: scroll; + word-wrap: break-word; + max-height: 20em; + font-weight: normal; + white-space: normal; +} +.ng-modal-close { + position: absolute; + top: 3px; + right: 5px; + cursor: pointer; + font-size: 120%; + padding: 5px; + display: inline-block; +} +.ng-modal-close-x { + font-weight: bold; + font-family: Arial, sans-serif; +} +.ng-modal-title { + font-weight: bold; + font-size: 1.5em; + display: block; + margin-bottom: 10px; + padding-bottom: 7px; + border-bottom: solid 1px #999; +} diff --git a/front/src/css/icons.css b/front/src/css/icons.css new file mode 100644 index 0000000..6ebf26b --- /dev/null +++ b/front/src/css/icons.css @@ -0,0 +1,6 @@ +@font-face { + font-family: "fontsmith-icons"; + src: url("/front/fonts/icons.woff") format("woff"); + font-weight: normal; + font-style: normal; +} diff --git a/front/src/css/index.css b/front/src/css/index.css new file mode 100644 index 0000000..d22b867 --- /dev/null +++ b/front/src/css/index.css @@ -0,0 +1,36 @@ +.promess { + padding: 0em 2em 3em; + font-weight: normal; + font-size: 1.2em; +} +.url { + width: 50%; +} +.launchBtn { + background: #e74c3c; + color: #fff; +} +.launchBtn.disabled { + background: #deaca6; +} +input[type=submit], +input.url { + padding: 0 0.5em; + margin: 0.5em; + font-size: 1.2em; + height: 2em; + border: 0 solid; + border-radius: 0.5em; + box-shadow: 0.1em 0.2em 0 0 #5e2846; + outline: none; +} +input[type=submit]:hover { + color: #ddd; +} +input[type=submit].clicked { + color: #ddd; + position: relative; + left: 0.1em; + top: 0.2em; + box-shadow: none; +} diff --git a/front/src/css/main.css b/front/src/css/main.css new file mode 100644 index 0000000..1ef1db3 --- /dev/null +++ b/front/src/css/main.css @@ -0,0 +1,139 @@ +@font-face { + font-family: "fontsmith-icons"; + src: url("/front/fonts/icons.woff") format("woff"); + font-weight: normal; + font-style: normal; +} +html { + margin: 100px 50px; +} +body { + margin: 0 auto; + max-width: 1280px; + background: #9c4274; + color: #fff; + font-size: 16px; + text-align: center; +} +body, +input[type=submit], +input[type=text], +input[type=url], +input[type=number], +button { + font-family: 'Century Gothic', helvetica, arial, sans-serif; +} +input[type=submit] { + cursor: pointer; +} +h1 span { + display: inline-block; + height: 1em; + width: 1em; + color: #ffa319; +} +.footer { + padding: 3em; + color: #4e1836; +} +.footer a { + color: inherit; +} +.footer .star { + font-weight: bold; +} +.footer .star span { + font-size: 1.2em; +} +/* Icons */ +.icon-lab { + font-family: "fontsmith-icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-lab:before { + content: "\e003"; +} +.icon-question { + font-family: "fontsmith-icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-question:before { + content: "\e001"; +} +.icon-warning { + font-family: "fontsmith-icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-warning:before { + content: "\e000"; +} +.icon-back { + font-family: "fontsmith-icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-back:before { + content: "\e006"; +} +.icon-summary { + font-family: "fontsmith-icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-summary:before { + content: "\e002"; +} +.icon-spaghetti { + font-family: "fontsmith-icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-spaghetti:before { + content: "\e005"; +} +.icon-eye { + font-family: "fontsmith-icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-eye:before { + content: "\e004"; +} diff --git a/front/src/css/queue.css b/front/src/css/queue.css new file mode 100644 index 0000000..76161b3 --- /dev/null +++ b/front/src/css/queue.css @@ -0,0 +1,25 @@ +.status { + margin-top: 2em; + font-size: 2.5em; +} +@-webkit-keyframes rotating { + from { + -webkit-transform: rotate(0deg); + } + to { + -webkit-transform: rotate(360deg); + } +} +@keyframes rotating { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} +.waiting .icon-lab { + -webkit-animation: rotating 3s linear 0s infinite; + -webkit-transform: translateZ(0); + animation: rotating 3s linear 0s infinite; +} diff --git a/front/src/fonts/icons.woff b/front/src/fonts/icons.woff new file mode 100644 index 0000000..dd8c0bd Binary files /dev/null and b/front/src/fonts/icons.woff differ diff --git a/front/src/fonts/svg-icons/arrow-left3.svg b/front/src/fonts/svg-icons/arrow-left3.svg new file mode 100644 index 0000000..d96cc70 --- /dev/null +++ b/front/src/fonts/svg-icons/arrow-left3.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front/src/fonts/svg-icons/bars.svg b/front/src/fonts/svg-icons/bars.svg new file mode 100644 index 0000000..2e7adca --- /dev/null +++ b/front/src/fonts/svg-icons/bars.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front/src/fonts/svg-icons/eye.svg b/front/src/fonts/svg-icons/eye.svg new file mode 100644 index 0000000..59ff3c2 --- /dev/null +++ b/front/src/fonts/svg-icons/eye.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front/src/fonts/svg-icons/lab.svg b/front/src/fonts/svg-icons/lab.svg new file mode 100644 index 0000000..28b3aa8 --- /dev/null +++ b/front/src/fonts/svg-icons/lab.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front/src/fonts/svg-icons/list.svg b/front/src/fonts/svg-icons/list.svg new file mode 100644 index 0000000..403a80a --- /dev/null +++ b/front/src/fonts/svg-icons/list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front/src/fonts/svg-icons/question.svg b/front/src/fonts/svg-icons/question.svg new file mode 100644 index 0000000..49e9fc3 --- /dev/null +++ b/front/src/fonts/svg-icons/question.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front/src/fonts/svg-icons/warning.svg b/front/src/fonts/svg-icons/warning.svg new file mode 100644 index 0000000..85f8300 --- /dev/null +++ b/front/src/fonts/svg-icons/warning.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/front/src/js/app.js b/front/src/js/app.js index aaea1b7..47c3210 100644 --- a/front/src/js/app.js +++ b/front/src/js/app.js @@ -2,7 +2,11 @@ var yltApp = angular.module('YellowLabTools', [ 'ngRoute', 'indexCtrl', 'aboutCtrl', - 'dashboardCtrl' + 'dashboardCtrl', + 'queueCtrl', + 'runsFactory', + 'resultsFactory', + 'gradeDirective' ]); yltApp.config(['$routeProvider', '$locationProvider', @@ -12,11 +16,15 @@ yltApp.config(['$routeProvider', '$locationProvider', templateUrl: 'front/views/index.html', controller: 'IndexCtrl' }). + when('/queue/:runId', { + templateUrl: 'front/views/queue.html', + controller: 'QueueCtrl' + }). when('/about', { templateUrl: 'front/views/about.html', controller: 'AboutCtrl' }). - when('/results/:runId', { + when('/result/:runId', { templateUrl: 'front/views/dashboard.html', controller: 'DashboardCtrl' }). diff --git a/front/src/js/controllers/indexCtrl.js b/front/src/js/controllers/indexCtrl.js index d308850..2d8f650 100644 --- a/front/src/js/controllers/indexCtrl.js +++ b/front/src/js/controllers/indexCtrl.js @@ -1,5 +1,16 @@ var indexCtrl = angular.module('indexCtrl', []); -indexCtrl.controller('IndexCtrl', ['$scope', function($scope) { - $scope.toto = "Achraf"; +indexCtrl.controller('IndexCtrl', ['$scope', '$location', 'Runs', function($scope, $location, Runs) { + $scope.launchTest = function() { + if ($scope.url) { + Runs.save({ + url: $scope.url, + waitForResponse: false + }, function(data) { + console.log(data); + $location.path('/queue/' + data.runId); + }); + + } + }; }]); \ No newline at end of file diff --git a/front/src/js/controllers/queueCtrl.js b/front/src/js/controllers/queueCtrl.js new file mode 100644 index 0000000..45b8bd4 --- /dev/null +++ b/front/src/js/controllers/queueCtrl.js @@ -0,0 +1,23 @@ +var queueCtrl = angular.module('queueCtrl', ['runsFactory']); + +queueCtrl.controller('QueueCtrl', ['$scope', '$routeParams', '$location', 'Runs', function($scope, $routeParams, $location, Runs) { + $scope.runId = $routeParams.runId; + + function getRunStatus () { + Runs.get({runId: $scope.runId}, function(data) { + $scope.status = data.status; + if (data.status.statusCode === 'running' || data.status.statusCode === 'awaiting') { + // Retrying in 2 seconds + setTimeout(getRunStatus, 2000); + } else if (data.status.statusCode === 'complete') { + $location.path('/result/' + $scope.runId); + } else { + // Handled by the view + } + }); + } + + getRunStatus(); +}]); + + \ No newline at end of file diff --git a/front/src/js/directives/gradeDirective.js b/front/src/js/directives/gradeDirective.js new file mode 100644 index 0000000..785ba17 --- /dev/null +++ b/front/src/js/directives/gradeDirective.js @@ -0,0 +1,34 @@ +var gradeDirective = angular.module('gradeDirective', []); + +gradeDirective.directive('grade', function() { + + return { + restrict: 'E', + scope: { + score: '=score' + }, + template: '
(This is a BETA, your feedback is more than welcome)
\ No newline at end of file diff --git a/front/src/views/queue.html b/front/src/views/queue.html new file mode 100644 index 0000000..dcd631b --- /dev/null +++ b/front/src/views/queue.html @@ -0,0 +1,8 @@ +They can be Flash, XML, music or any unknown format.
", "isOkThreshold": 5, "isBadThreshold": 20, diff --git a/lib/metadata/scoreProfileGeneric.json b/lib/metadata/scoreProfileGeneric.json index 15bf1e0..3b11c0d 100644 --- a/lib/metadata/scoreProfileGeneric.json +++ b/lib/metadata/scoreProfileGeneric.json @@ -69,7 +69,7 @@ "requests": { "label": "Requests number", "policies": { - "request": 5, + "requests": 5, "htmlCount": 0, "jsCount": 1, "cssCount": 1, diff --git a/lib/server/controllers/frontController.js b/lib/server/controllers/frontController.js index d13ea6d..25b84cc 100644 --- a/lib/server/controllers/frontController.js +++ b/lib/server/controllers/frontController.js @@ -3,17 +3,13 @@ var express = require('express'); var FrontController = function(app) { 'use strict'; - - app.get('/', function(req, res) { - res.sendFile(path.join(__dirname, '../../../front/src/main.html')); - }); - app.get('/about', function(req, res) { - res.sendFile(path.join(__dirname, '../../../front/src/main.html')); - }); + var routes = ['/', '/about', '/result/:runId', '/queue/:runId']; - app.get('/results/:runId', function(req, res) { - res.sendFile(path.join(__dirname, '../../../front/src/main.html')); + routes.forEach(function(route) { + app.get(route, function(req, res) { + res.sendFile(path.join(__dirname, '../../../front/src/main.html')); + }); }); app.use('/front', express.static(path.join(__dirname, '../../../front/src'))); diff --git a/src b/src new file mode 100644 index 0000000..36a8a55 --- /dev/null +++ b/src @@ -0,0 +1,672 @@ +/* Timeline colors, related to Window Performances */ +.resultsMenu { + margin-top: 2em; +} +.resultsMenu .menuItem { + display: inline-block; + margin: 1em; + width: 8em; + height: 7em; + color: #fff; + border: 3px solid #fff; + border-radius: 0.5em; + cursor: pointer; + text-decoration: none; +} +.resultsMenu .back { + color: #5e2846; + border-color: #5e2846; +} +.resultsMenu .menuItem div { + padding-top: 0.5em; + font-size: 3em; +} +.resultsMenu .active, +.resultsMenu .menuItem.active:hover { + color: #ffa319; + border-color: #ffa319; +} +.resultsMenu .menuItem:hover { + color: #ffa319; +} +.resultsMenu span { + position: relative; + top: 0.5em; +} +.testedUrl { + color: inherit; +} +h4 { + margin-bottom: 0.5em; +} +.summary, +.metrics, +.execution { + margin-top: 2em; + padding: 1em; + background: #fff; + color: #000; + border-radius: 0.5em; + text-align: left; +} +.notations { + display: table; + width: 90%; + margin: 0 10%; + border-spacing: 1em; +} +.notations > div { + display: table-row; +} +.notations > div > div { + display: table-cell; + height: 2.5em; + vertical-align: middle; +} +.notations .notation { + font-weight: bold; + text-align: center; +} +.notations .criteria { + font-weight: normal; +} +.notations .A, +.notations .B, +.notations .C, +.notations .D, +.notations .E, +.notations .F, +.notations .NA { + width: 2.5em; + font-size: 2em; + text-align: center; + border-radius: 0.5em; + font-weight: bold; +} +.notations .A { + /* green */ + background: #00DB61; +} +.notations .B { + /* green */ + background: #CAD63D; +} +.notations .C { + /* yellow */ + background: #FFD119; +} +.notations .D { + /* orange */ + background: #FFA319; +} +.notations .E { + /* red */ + background: #FF6600; +} +.notations .F { + /* red */ + background: #FF1919; +} +.notations .NA { + /* Non applicable */ + background: #CCC; +} +.notations .icon-eye { + color: #9c4274; + cursor: pointer; +} +.notations .criteria .table { + width: 75%; +} +.notations .criteria .label { + width: 70%; +} +.notations .criteria .result { + width: 20%; + font-weight: bold; + white-space: nowrap; + text-align: center; +} +.notations .warning .label, +.notations .warning .result { + color: #FF1919; +} +.notations .criteria .info { + width: 10%; + text-align: center; +} +.notations .criteria .icon-question { + color: #f1c40f; + cursor: pointer; +} +.timeline { + margin: 2em 0 5em; +} +.timeline .chart { + position: relative; + width: 100%; + border-bottom: 1px solid #000; +} +.timeline .startTime, +.timeline .endTime { + position: absolute; + bottom: 0.5em; + font-size: 0.8em; +} +.timeline .startTime { + left: 0em; +} +.timeline .endTime { + right: 0em; +} +.timeline .chartPoints { + display: table; + height: 100px; + width: 99%; + margin: 0 auto; +} +.timeline .interval { + display: table-cell; + position: relative; + height: 100px; + width: 0.5%; +} +.timeline .interval .color { + position: absolute; + bottom: 0; + width: 100%; +} +.timeline div.interval:hover { + background: #9C4274; +} +.timeline .interval:hover .color { + background: #F04DA7; +} +.timeline .domComplete.interval { + background: #ede3ff; +} +.timeline .domComplete .color { + background: #c2a3ff; +} +.timeline .domContentLoadedEnd.interval { + background: #d8f0f0; +} +.timeline .domContentLoadedEnd .color { + background: #7ecccc; +} +.timeline .domContentLoaded.interval { + background: #e0ffd1; +} +.timeline .domContentLoaded .color { + background: #a7e846; +} +.timeline .domInteractive.interval { + background: #fffccc; +} +.timeline .domInteractive .color { + background: #ffe433; +} +.timeline .domCreation.interval { + background: #ffe0cc; +} +.timeline .domCreation .color { + background: #ff6600; +} +.timeline .tooltip.detailsOverlay { + position: absolute; + display: none; + width: auto; + padding: 0.5em 1em; + top: -1.5em; + right: 1em; +} +.timeline .interval:hover .tooltip { + display: block; +} +.timeline .legend { + display: table; + width: 100%; + margin-top: 1em; +} +.timeline .legend > div { + display: table-row; +} +.timeline .legend > div > div { + position: relative; + display: table-cell; + margin-top: 1em; +} +.timeline .titles { + font-weight: bold; +} +.timeline .titles > div { + padding: 0 1em 0 2em; +} +.timeline .tips { + font-size: 0.7em; +} +.timeline .tips > div { + padding: 1em 1em 0 0; +} +.timeline .legend .color { + display: block; + position: absolute; + left: 0; + height: 1.5em; + width: 1.5em; + border-radius: 0.2em; +} +.metrics h4 { + padding-left: 2em; +} +.metrics .module { + padding-left: 4em; + padding-top: 0.5em; +} +.metrics .legend { + font-style: italic; + color: #aaa; +} +.metrics .offenders { + padding-left: 0em; + font-size: 0.8em; +} +.metrics .offenders div { + cursor: pointer; +} +.metrics .offenders ul { + margin-top: 0.5em; +} +.filters { + margin: 1em 0; + padding: 0.5em; + border: 1px dotted #aaa; +} +.slowRequestsLimit { + width: 3em; + font-size: 1em; + text-align: right; + border: 1px solid #aaa; +} +input.textFilter { + box-shadow: none; + font-size: 1em; + padding: 0 0.2em; + border: 1px solid #aaa; + border-radius: none; + width: 15em; +} +.table { + display: table; + width: 100%; + border-spacing: 0.25em; +} +.table > div { + display: table-row; +} +.table > .headers > div { + font-weight: bold; + padding: 0.5em 1em; +} +.table > div > div { + padding: 0.1em 1em; + background: #f2f2f2; + display: table-cell; + text-align: left; +} +.table > div.jsError > .type, +.table > div.jsError > .value { + color: #e74c3c; + font-weight: bold; +} +.table > div.windowPerformance > div, +.table > div.windowPerformance > div.startTime { + background: #EBD8E2; +} +.table > div.showingDetails > div { + background: #f1c40f; +} +.table > div > .index { + color: #bbb; +} +.table > div > .type { + white-space: nowrap; +} +.table > div > .value { + width: 70%; + word-break: break-all; +} +.table > div > .details { + position: relative; +} +.table .details .icon-question { + color: #f1c40f; + cursor: pointer; +} +.table .details .icon-warning { + cursor: pointer; +} +.detailsOverlay { + position: absolute; + right: 3em; + top: -3em; + width: 45em; + min-height: 1em; + padding: 0 1em 1em; + background: #fff; + border: 2px solid #f1c40f; + border-radius: 0.5em; + z-index: 1; +} +@media screen and (max-width: 1024px) { + .detailsOverlay { + width: 25em; + } +} +.detailsOverlay .closeBtn { + position: absolute; + top: 0.5em; + right: 0.5em; + color: #f1c40f; + cursor: pointer; +} +.detailsOverlay .advice { + color: #e74c3c; + font-weight: bold; +} +.detailsOverlay .trace { + word-break: break-all; +} +.table > div > .duration, +.table > div > .startTime { + text-align: center; + white-space: nowrap; +} +.table > div > .startTime.domComplete { + background: #ede3ff; +} +.table > div > .startTime.domContentLoadedEnd { + background: #d8f0f0; +} +.table > div > .startTime.domContentLoaded { + background: #e0ffd1; +} +.table > div > .startTime.domInteractive { + background: #fffccc; +} +.table > div > .startTime.domCreation { + background: #ffe0cc; +} +.table .icon-warning { + color: #e74c3c; +} +/**** NgModal popin (have a look inside bower_components) ****/ +.ng-modal { + position: fixed; + z-index: 9999; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-align: left; +} +.ng-modal-overlay { + position: absolute; + z-index: 9999; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: #000; + opacity: 0.5; +} +.ng-modal-dialog { + z-index: 10000; + position: absolute; + top: 50%; + left: 50%; + width: 50%; + transform: translate(-50%, -50%); + -webkit-transform: translate(-50%, -50%); + background-color: #fff; + padding: 10px; + border: 3px solid #f1c40f; + border-radius: 0.5em; + color: #000; +} +.ng-modal-dialog-content { + overflow-x: hidden; + overflow-y: scroll; + word-wrap: break-word; + max-height: 20em; + font-weight: normal; + white-space: normal; +} +.ng-modal-close { + position: absolute; + top: 3px; + right: 5px; + cursor: pointer; + font-size: 120%; + padding: 5px; + display: inline-block; +} +.ng-modal-close-x { + font-weight: bold; + font-family: Arial, sans-serif; +} +.ng-modal-title { + font-weight: bold; + font-size: 1.5em; + display: block; + margin-bottom: 10px; + padding-bottom: 7px; + border-bottom: solid 1px #999; +} + +@font-face { + font-family: "fontsmith-icons"; + src: url("/public/fonts/icons.woff") format("woff"); + font-weight: normal; + font-style: normal; +} + +.promess { + padding: 0em 2em 3em; + font-weight: normal; + font-size: 1.2em; +} +.url { + width: 50%; +} +.launchBtn { + background: #e74c3c; + color: #fff; +} +input[type=submit], +input.url { + padding: 0 0.5em; + margin: 0.5em; + font-size: 1.2em; + height: 2em; + border: 0 solid; + border-radius: 0.5em; + box-shadow: 0.1em 0.2em 0 0 #5e2846; + outline: none; +} +input[type=submit]:hover { + color: #ddd; +} +input[type=submit].clicked { + color: #ddd; + position: relative; + left: 0.1em; + top: 0.2em; + box-shadow: none; +} + +#status { + margin-top: 2em; + font-size: 2.5em; +} +@-webkit-keyframes rotating { + from { + -webkit-transform: rotate(0deg); + } + to { + -webkit-transform: rotate(360deg); + } +} +@keyframes rotating { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} +.waiting .icon-lab { + -webkit-animation: rotating 3s linear 0s infinite; + -webkit-transform: translateZ(0); + animation: rotating 3s linear 0s infinite; +} + +@font-face { + font-family: "fontsmith-icons"; + src: url("/public/fonts/icons.woff") format("woff"); + font-weight: normal; + font-style: normal; +} +html { + margin: 100px 50px; +} +body { + margin: 0 auto; + max-width: 1280px; + background: #9c4274; + color: #fff; + font-size: 16px; + text-align: center; +} +body, +input[type=submit], +input[type=text], +input[type=url], +input[type=number], +button { + font-family: 'Century Gothic', helvetica, arial, sans-serif; +} +input[type=submit] { + cursor: pointer; +} +h1 span { + display: inline-block; + height: 1em; + width: 1em; + color: #ffa319; +} +.footer { + padding: 3em; + color: #4e1836; +} +.footer a { + color: inherit; +} +.footer .star { + font-weight: bold; +} +.footer .star span { + font-size: 1.2em; +} +/* Icons */ +.icon-lab { + font-family: "fontsmith-icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-lab:before { + content: "\e003"; +} +.icon-question { + font-family: "fontsmith-icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-question:before { + content: "\e001"; +} +.icon-warning { + font-family: "fontsmith-icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-warning:before { + content: "\e000"; +} +.icon-back { + font-family: "fontsmith-icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-back:before { + content: "\e006"; +} +.icon-summary { + font-family: "fontsmith-icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-summary:before { + content: "\e002"; +} +.icon-spaghetti { + font-family: "fontsmith-icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-spaghetti:before { + content: "\e005"; +} +.icon-eye { + font-family: "fontsmith-icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-eye:before { + content: "\e004"; +}