Просмотр исходного кода

Merge pull request #554 from sharelatex/afc-metrics-spike

Add new dependencies & styles for the new metrics app
Alberto Fernández-Capel 8 лет назад
Родитель
Сommit
d6313cbc68

Разница между файлами не показана из-за своего большого размера
+ 293 - 339
services/web/npm-shrinkwrap.json


+ 7 - 0
services/web/package.json

@@ -27,6 +27,7 @@
   "dependencies": {
     "archiver": "0.9.0",
     "async": "0.6.2",
+    "backbone": "^1.3.3",
     "base64-stream": "^0.1.2",
     "basic-auth-connect": "^1.0.0",
     "bcrypt": "1.0.1",
@@ -37,16 +38,20 @@
     "cookie": "^0.2.3",
     "cookie-parser": "1.3.5",
     "csurf": "^1.8.3",
+    "d3": "^3.5.16",
     "dateformat": "1.0.4-1.2.3",
+    "daterangepicker": "^2.1.27",
     "express": "4.13.0",
     "express-http-proxy": "^1.1.0",
     "express-session": "^1.14.2",
     "fs-extra": "^4.0.2",
     "fuse.js": "^3.0.0",
+    "handlebars": "^4.0.11",
     "heapdump": "^0.3.7",
     "helmet": "^3.8.1",
     "http-proxy": "^1.8.1",
     "jade": "~1.3.1",
+    "jquery": "^1.11.1",
     "jsonwebtoken": "^8.0.1",
     "ldapjs": "^0.7.1",
     "lodash": "^4.13.1",
@@ -65,6 +70,7 @@
     "nodemailer-mandrill-transport": "^1.2.0",
     "nodemailer-sendgrid-transport": "^0.2.0",
     "nodemailer-ses-transport": "^1.3.0",
+    "nvd3": "^1.8.6",
     "optimist": "0.6.1",
     "passport": "^0.3.2",
     "passport-ldapauth": "^0.6.0",
@@ -134,6 +140,7 @@
     "grunt-postcss": "^0.8.0",
     "grunt-sed": "^0.1.1",
     "grunt-shell": "^2.1.0",
+    "handlebars-loader": "^1.7.0",
     "karma": "^2.0.0",
     "karma-chai-sinon": "^0.1.5",
     "karma-chrome-launcher": "^2.2.0",

+ 2 - 0
services/web/public/stylesheets/_style_includes.less

@@ -47,6 +47,7 @@
 @import "components/tooltip.less";
 @import "components/popovers.less";
 @import "components/carousel.less";
+@import "components/daterange-picker";
 
 // ngTagsInput
 @import "components/tags-input.less";
@@ -79,6 +80,7 @@
 @import "app/review-features-page.less";
 @import "app/error-pages.less";
 @import "app/v1-badge.less";
+@import "app/metrics.less";
 
 // Vendor CSS
 @import	"../js/libs/pdfListView/TextLayer.css";

+ 177 - 0
services/web/public/stylesheets/app/metrics.less

@@ -0,0 +1,177 @@
+#metrics {
+  max-width: none;
+  padding: 0 30px;
+  width: auto;
+
+  svg.nvd3-svg {
+    width: 100%;
+  }
+
+  .overbox {
+    margin: 0;
+    padding: 40px 20px;
+    background: #fff;
+    border: 1px solid #DFDFDF;
+    .box {
+      padding-bottom: 30px;
+      overflow: hidden;
+      margin-bottom: 40px;
+      border-bottom: 1px solid rgb(216, 216, 216);
+
+      .header {
+        margin-bottom: 20px;
+
+        h4 {
+          font-size: 19px;
+          margin: 0;
+        }
+      }
+    }
+  }
+
+  .print-button {
+    margin-right: 10px;
+    font-size: 20px;
+  }
+
+  .title-button {
+    margin-right: 5px;
+    font-size: 20px;
+  }
+
+  .metric-col {
+    padding: 15px;
+  }
+
+  .metric-header-container {
+    h4 {
+      margin-bottom: 0;
+    }
+  }
+
+  svg {
+    display: block;
+    height: 250px;
+    text {
+      font-family: "Open Sans", sans-serif;
+    }
+    &:not(:root) {
+      overflow: visible
+    }
+
+    &.hidden-legend-margin-fix {
+      margin-top: 15px;
+      height: 235px;
+    }
+
+    &.no-fill-opacity {
+      .nvd3 {
+        .nv-area {
+          fill-opacity: 1;
+        }
+      }
+    }
+  }
+
+  .nvtooltip {
+    z-index: 10;
+  }
+
+  .tooltip {
+    width: 150px;
+  }
+
+  // BEGIN: Metrics header
+  .metric-header-container {
+    > h4 {
+      margin-top: 0;
+      margin-bottom: 0;
+    }
+  }
+  // END: Metrics header
+
+  // BEGIN: Metrics footer
+  .metric-footer-container {
+    text-align: center;
+  }
+  // END: Metrics footer
+
+  // BEGIN: Metrics overlays
+  .metric-overlay-loading,
+  .metric-overlay-error,
+  .metric-overlay-backdrop {
+    position: absolute;
+    top: 0;
+    left: 0;
+    height: 100%;
+    width: 100%;
+    padding: 16px; /* 15px of .metric-col padding + 1px border */
+    padding-top: 56px; /* Same as above + 30px for title + 10px overbox padding*/
+  }
+
+  .metric-overlay-loading {
+    padding: 175px 20%;
+  }
+
+  .metric-overlay-error {
+    display: none;
+    text-align: center;
+    padding-top: 175px;
+  }
+
+  .metric-overlay-backdrop {
+    opacity: 0.5;
+  }
+
+  .metric-overlay-backdrop-inner {
+    background-color: #fff;
+    width: 100%;
+    height: 100%;
+  }
+  // END: Metrics overlays
+}
+
+#metrics-header {
+  @media (min-width: 1200px) {
+    margin-bottom: 30px;
+  }
+
+  .section_header {
+    margin-bottom: 0;
+  }
+
+  #filters-container {
+    text-align: right;
+
+    .by {
+      color: #989898;
+      font-style: italic;
+    }
+  }
+
+  #lags-container {
+    .dropdown-menu {
+      min-width: 0;
+    }
+  }
+
+  #dates-container {
+    display: inline-block;
+    .daterangepicker {
+      margin-right: 15px;
+    }
+  }
+}
+
+#metrics-footer {
+  margin-top: 30px;
+  text-align: center;
+}
+
+body.print-loading {
+  #metrics {
+    .metric-col {
+      opacity: 0.5;
+    }
+  }
+}

+ 610 - 0
services/web/public/stylesheets/components/daterange-picker.less

@@ -0,0 +1,610 @@
+//
+// A stylesheet for use with Bootstrap 3.x
+// @author: Dan Grossman http://www.dangrossman.info/
+// @copyright: Copyright (c) 2012-2015 Dan Grossman. All rights reserved.
+// @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php
+// @website: https://www.improvely.com/
+//
+
+//
+// VARIABLES
+//
+
+//
+// Settings
+
+// The class name to contain everything within.
+@arrow-size:     7px;
+
+//
+// Colors
+@daterangepicker-color:                      @brand-primary;
+@daterangepicker-bg-color:                   #fff;
+
+@daterangepicker-cell-color:                 @daterangepicker-color;
+@daterangepicker-cell-border-color:          transparent;
+@daterangepicker-cell-bg-color:              @daterangepicker-bg-color;
+
+@daterangepicker-cell-hover-color:           @daterangepicker-color;
+@daterangepicker-cell-hover-border-color:    @daterangepicker-cell-border-color;
+@daterangepicker-cell-hover-bg-color:        #eee;
+
+@daterangepicker-in-range-color:             #000;
+@daterangepicker-in-range-border-color:      transparent;
+@daterangepicker-in-range-bg-color:          #ebf4f8;
+
+@daterangepicker-active-color:               #fff;
+@daterangepicker-active-bg-color:            #a93529;
+@daterangepicker-active-border-color:        transparent;
+
+@daterangepicker-unselected-color:           #999;
+@daterangepicker-unselected-border-color:    transparent;
+@daterangepicker-unselected-bg-color:        #fff;
+
+//
+// daterangepicker
+@daterangepicker-width:          278px;
+@daterangepicker-padding:        4px;
+@daterangepicker-z-index:        3000;
+
+@daterangepicker-border-size:    1px;
+@daterangepicker-border-color:   #ccc;
+@daterangepicker-border-radius:  4px;
+
+
+//
+// Calendar
+@daterangepicker-calendar-margin:              @daterangepicker-padding;
+@daterangepicker-calendar-bg-color:            @daterangepicker-bg-color;
+
+@daterangepicker-calendar-border-size:         1px;
+@daterangepicker-calendar-border-color:        @daterangepicker-bg-color;
+@daterangepicker-calendar-border-radius:       @daterangepicker-border-radius;
+
+//
+// Calendar Cells
+@daterangepicker-cell-size:           20px;
+@daterangepicker-cell-width:          @daterangepicker-cell-size;
+@daterangepicker-cell-height:         @daterangepicker-cell-size;
+
+@daterangepicker-cell-border-radius:  @daterangepicker-calendar-border-radius;
+@daterangepicker-cell-border-size:    1px;
+
+//
+// Dropdowns
+@daterangepicker-dropdown-z-index: @daterangepicker-z-index + 1;
+
+//
+// Controls
+@daterangepicker-control-height:               30px;
+@daterangepicker-control-line-height:          @daterangepicker-control-height;
+@daterangepicker-control-color:                #555;
+
+@daterangepicker-control-border-size:          1px;
+@daterangepicker-control-border-color:         #ccc;
+@daterangepicker-control-border-radius:        4px;
+
+@daterangepicker-control-active-border-size:   1px;
+@daterangepicker-control-active-border-color:  @brand-primary;
+@daterangepicker-control-active-border-radius: @daterangepicker-control-border-radius;
+
+@daterangepicker-control-disabled-color:       #ccc;
+
+//
+// Ranges
+@daterangepicker-ranges-color:                @brand-primary;
+@daterangepicker-ranges-bg-color:             daterangepicker-ranges-color;
+
+@daterangepicker-ranges-border-size:          1px;
+@daterangepicker-ranges-border-color:         @daterangepicker-ranges-bg-color;
+@daterangepicker-ranges-border-radius:        @daterangepicker-border-radius;
+
+@daterangepicker-ranges-hover-color:          #fff;
+@daterangepicker-ranges-hover-bg-color:       @daterangepicker-ranges-color;
+@daterangepicker-ranges-hover-border-size:    @daterangepicker-ranges-border-size;
+@daterangepicker-ranges-hover-border-color:   @daterangepicker-ranges-hover-bg-color;
+@daterangepicker-ranges-hover-border-radius:  @daterangepicker-border-radius;
+
+@daterangepicker-ranges-active-border-size:   @daterangepicker-ranges-border-size;
+@daterangepicker-ranges-active-border-color:  @daterangepicker-ranges-bg-color;
+@daterangepicker-ranges-active-border-radius: @daterangepicker-border-radius;
+
+//
+// STYLESHEETS
+//
+.daterangepicker {
+  position: absolute;
+  color: @daterangepicker-color;
+  background-color: @daterangepicker-bg-color;
+  border-radius: @daterangepicker-border-radius;
+  width: @daterangepicker-width;
+  padding: @daterangepicker-padding;
+  margin-top: @daterangepicker-border-size;
+
+  // TODO: Should these be parameterized??
+  // top: 100px;
+  // left: 20px;
+
+  @arrow-prefix-size: @arrow-size;
+  @arrow-suffix-size: (@arrow-size - @daterangepicker-border-size);
+
+  &:before, &:after {
+    position: absolute;
+    display: inline-block;
+
+    border-bottom-color: rgba(0, 0, 0, 0.2);
+    content: '';
+  }
+
+  &:before {
+    top: -@arrow-prefix-size;
+
+    border-right: @arrow-prefix-size solid transparent;
+    border-left: @arrow-prefix-size solid transparent;
+    border-bottom: @arrow-prefix-size solid @daterangepicker-border-color;
+  }
+
+  &:after {
+    top: -@arrow-suffix-size;
+
+    border-right: @arrow-suffix-size solid transparent;
+    border-bottom: @arrow-suffix-size solid @daterangepicker-bg-color;
+    border-left: @arrow-suffix-size solid transparent;
+  }
+
+  &.opensleft {
+    &:before {
+      // TODO: Make this relative to prefix size.
+      right: @arrow-prefix-size + 2px;
+    }
+
+    &:after {
+      // TODO: Make this relative to suffix size.
+      right: @arrow-suffix-size + 4px;
+    }
+  }
+
+  &.openscenter {
+    &:before {
+      left: 0;
+      right: 0;
+      width: 0;
+      margin-left: auto;
+      margin-right: auto;
+    }
+
+    &:after {
+      left: 0;
+      right: 0;
+      width: 0;
+      margin-left: auto;
+      margin-right: auto;
+    }
+  }
+
+  &.opensright {
+    &:before {
+      // TODO: Make this relative to prefix size.
+      left: @arrow-prefix-size + 2px;
+    }
+
+    &:after {
+      // TODO: Make this relative to suffix size.
+      left: @arrow-suffix-size + 4px;
+    }
+  }
+
+  &.dropup {
+    margin-top: -5px;
+
+    // NOTE: Note sure why these are special-cased.
+    &:before {
+      top: initial;
+      bottom: -@arrow-prefix-size;
+      border-bottom: initial;
+      border-top: @arrow-prefix-size solid @daterangepicker-border-color;
+    }
+
+    &:after {
+      top: initial;
+      bottom:-@arrow-suffix-size;
+      border-bottom: initial;
+      border-top: @arrow-suffix-size solid @daterangepicker-bg-color;
+    }
+  }
+
+  &.dropdown-menu {
+    max-width: none;
+    z-index: @daterangepicker-dropdown-z-index;
+  }
+
+  &.single {
+    .ranges, .calendar {
+      float: none;
+    }
+  }
+
+  /* Calendars */
+  &.show-calendar {
+    .calendar {
+      display: block;
+    }
+  }
+
+  .calendar {
+    display: none;
+    max-width: @daterangepicker-width - (@daterangepicker-calendar-margin * 2);
+    margin: @daterangepicker-calendar-margin;
+
+    &.single {
+      .calendar-table {
+        border: none;
+      }
+    }
+
+    th, td {
+      white-space: nowrap;
+      text-align: center;
+
+      // TODO: Should this actually be hard-coded?
+      min-width: 32px;
+    }
+  }
+
+  .calendar-table {
+    border: @daterangepicker-calendar-border-size solid @daterangepicker-calendar-border-color;
+    padding: @daterangepicker-calendar-margin;
+    border-radius: @daterangepicker-calendar-border-radius;
+    background-color: @daterangepicker-calendar-bg-color;
+  }
+
+  table {
+    width: 100%;
+    margin: 0;
+  }
+
+  td, th {
+    text-align: center;
+    width: @daterangepicker-cell-width;
+    height: @daterangepicker-cell-height;
+    border-radius: @daterangepicker-cell-border-radius;
+    border: @daterangepicker-cell-border-size solid @daterangepicker-cell-border-color;
+    white-space: nowrap;
+    cursor: pointer;
+
+    &.available {
+      &:hover {
+        background-color: @daterangepicker-cell-hover-bg-color;
+        border-color: @daterangepicker-cell-hover-border-color;
+        color: @daterangepicker-cell-hover-color;
+      }
+    }
+
+    &.week {
+      font-size: 80%;
+      color: #ccc;
+    }
+  }
+
+  td {
+    &.off {
+      &, &.in-range, &.start-date, &.end-date {
+        background-color: @daterangepicker-unselected-bg-color;
+        border-color: @daterangepicker-unselected-border-color;
+        color: @daterangepicker-unselected-color;
+      }
+    }
+
+    //
+    // Date Range
+    &.in-range {
+      background-color: @daterangepicker-in-range-bg-color;
+      border-color: @daterangepicker-in-range-border-color;
+      color: @daterangepicker-in-range-color;
+
+      // TODO: Should this be static or should it be parameterized?
+      border-radius: 0;
+    }
+
+    &.start-date {
+      border-radius: @daterangepicker-cell-border-radius 0 0 @daterangepicker-cell-border-radius;
+    }
+
+    &.end-date {
+      border-radius: 0 @daterangepicker-cell-border-radius @daterangepicker-cell-border-radius 0;
+    }
+
+    &.start-date.end-date {
+      border-radius: @daterangepicker-cell-border-radius;
+    }
+
+    &.active {
+      &, &:hover {
+        background-color: @daterangepicker-active-bg-color;
+        border-color: @daterangepicker-active-border-color;
+        color: @daterangepicker-active-color;
+      }
+    }
+  }
+
+  th {
+    &.month {
+      width: auto;
+    }
+  }
+
+  //
+  // Disabled Controls
+  //
+  td, option {
+    &.disabled {
+      color: #999;
+      cursor: not-allowed;
+      text-decoration: line-through;
+    }
+  }
+
+  select {
+    &.monthselect, &.yearselect {
+      font-size: 12px;
+      padding: 1px;
+      height: auto;
+      margin: 0;
+      cursor: default;
+    }
+
+    &.monthselect {
+      margin-right: 2%;
+      width: 56%;
+    }
+
+    &.yearselect {
+      width: 40%;
+    }
+
+    &.hourselect, &.minuteselect, &.secondselect, &.ampmselect {
+      width: 50px;
+      margin-bottom: 0;
+    }
+  }
+
+  //
+  // Text Input Controls (above calendar)
+  //
+  .input-mini {
+    border: @daterangepicker-control-border-size solid @daterangepicker-control-border-color;
+    border-radius: @daterangepicker-control-border-radius;
+    color: @daterangepicker-control-color;
+    height: @daterangepicker-control-line-height;
+    line-height: @daterangepicker-control-height;
+    display: block;
+    vertical-align: middle;
+
+    // TODO: Should these all be static, too??
+    margin: 0 0 5px 0;
+    padding: 0 6px 0 28px;
+    width: 100%;
+
+    &.active {
+      border: @daterangepicker-control-active-border-size solid @daterangepicker-control-active-border-color;
+      border-radius: @daterangepicker-control-active-border-radius;
+    }
+  }
+
+  .daterangepicker_input {
+    position: relative;
+
+    i {
+      position: absolute;
+
+      // NOTE: These appear to be eyeballed to me...
+      left: 8px;
+      top: 8px;
+    }
+  }
+  &.rtl {
+    .input-mini {
+      padding-right: 28px;
+      padding-left: 6px;
+    }
+    .daterangepicker_input i {
+      left: auto;
+      right: 8px;
+    }
+  }
+
+  //
+  // Time Picker
+  //
+  .calendar-time {
+    text-align: center;
+    margin: 5px auto;
+    line-height: @daterangepicker-control-line-height;
+    position: relative;
+    padding-left: 28px;
+
+    select {
+      &.disabled {
+        color: @daterangepicker-control-disabled-color;
+        cursor: not-allowed;
+      }
+    }
+  }
+}
+
+//
+// Predefined Ranges
+//
+
+.ranges {
+  font-size: 11px;
+  float: none;
+  margin: 4px;
+  text-align: left;
+
+  ul {
+    list-style: none;
+    margin: 0 auto;
+    padding: 0;
+    width: 100%;
+  }
+
+  li {
+    font-size: 13px;
+    background-color: @daterangepicker-ranges-bg-color;
+    border: @daterangepicker-ranges-border-size solid @daterangepicker-ranges-border-color;
+    border-radius: @daterangepicker-ranges-border-radius;
+    color: @daterangepicker-ranges-color;
+    padding: 3px 12px;
+    margin-bottom: 8px;
+    cursor: pointer;
+
+    &:hover {
+      background-color: @daterangepicker-ranges-hover-bg-color;
+      border: @daterangepicker-ranges-hover-border-size solid @daterangepicker-ranges-hover-border-color;
+      color: @daterangepicker-ranges-hover-color;
+    }
+
+    &.active {
+      background-color: @daterangepicker-ranges-hover-bg-color;
+      border: @daterangepicker-ranges-hover-border-size solid @daterangepicker-ranges-hover-border-color;
+      color: @daterangepicker-ranges-hover-color;
+    }
+  }
+}
+
+/*  Larger Screen Styling */
+@media (min-width: 564px) {
+  .daterangepicker {
+    width: auto;
+
+    .ranges {
+      ul {
+        width: 160px;
+      }
+    }
+
+    &.single {
+      .ranges {
+        ul {
+          width: 100%;
+        }
+      }
+
+      .calendar.left {
+        clear: none;
+      }
+
+      &.ltr {
+        .ranges, .calendar {
+          float:left;
+        }
+      }
+      &.rtl {
+        .ranges, .calendar {
+          float:right;
+        }
+      }
+    }
+
+    &.ltr {
+      direction: ltr;
+      text-align: left;
+      .calendar{
+        &.left {
+          clear: left;
+          margin-right: 0;
+
+          .calendar-table {
+            border-right: none;
+            border-top-right-radius: 0;
+            border-bottom-right-radius: 0;
+          }
+        }
+
+        &.right {
+          margin-left: 0;
+
+          .calendar-table {
+            border-left: none;
+            border-top-left-radius: 0;
+            border-bottom-left-radius: 0;
+          }
+        }
+      }
+
+      .left .daterangepicker_input {
+        padding-right: 12px;
+      }
+
+      .calendar.left .calendar-table {
+        padding-right: 12px;
+      }
+
+      .ranges, .calendar {
+        float: left;
+      }
+    }
+    &.rtl {
+      direction: rtl;
+      text-align: right;
+      .calendar{
+        &.left {
+          clear: right;
+          margin-left: 0;
+
+          .calendar-table {
+            border-left: none;
+            border-top-left-radius: 0;
+            border-bottom-left-radius: 0;
+          }
+        }
+
+        &.right {
+          margin-right: 0;
+
+          .calendar-table {
+            border-right: none;
+            border-top-right-radius: 0;
+            border-bottom-right-radius: 0;
+          }
+        }
+      }
+
+      .left .daterangepicker_input {
+        padding-left: 12px;
+      }
+
+      .calendar.left .calendar-table {
+        padding-left: 12px;
+      }
+
+      .ranges, .calendar {
+        text-align: right;
+        float: right;
+      }
+    }
+  }
+}
+
+@media (min-width: 730px) {
+  .daterangepicker {
+    .ranges {
+      width: auto;
+    }
+    &.ltr {
+      .ranges {
+        float: left;
+      }
+    }
+    &.rtl {
+      .ranges {
+        float: right;
+      }
+    }
+
+    .calendar.left {
+      clear: none !important;
+    }
+  }
+}

+ 18 - 2
services/web/webpack.config.js

@@ -62,9 +62,26 @@ module.exports = {
 					cacheDirectory: true
 				}
 			}]
+		},
+		{
+			// These options are necesary for handlebars to have access to helper
+			// methods
+			test: /\.handlebars$/,
+			loader: "handlebars-loader",
+			options: {
+				compat: true,
+				knownHelpersOnly: false,
+				runtimePath: 'handlebars/runtime',
+			}
 		}]
 	},
-
+	resolve: {
+		alias: {
+			// makes handlerbars globally accessible to backbone
+			handlebars: 'handlebars/dist/handlebars.min.js',
+			jquery: path.join(__dirname, 'node_modules/jquery/dist/jquery'),
+		}
+	},
 	plugins: [
 		new webpack.DefinePlugin({
 			// Swaps out checks for NODE_ENV with the env. This is used by various
@@ -77,4 +94,3 @@ module.exports = {
 		})
 	]
 }
-

Некоторые файлы не были показаны из-за большого количества измененных файлов