diff --git a/css/font-awesome.min.css b/css/font-awesome.min.css
index 3d920fc8..d0603cb4 100644
--- a/css/font-awesome.min.css
+++ b/css/font-awesome.min.css
@@ -1,4 +1,4 @@
/*!
- * Font Awesome 4.1.0 by @davegandy - http://fontawesome.io - @fontawesome
+ * Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
- */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.1.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.1.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.1.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-square:before,.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}
\ No newline at end of file
+ */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.5.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.5.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.5.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.5.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}
diff --git a/css/homer.css b/css/homer.css
index 54002384..5112b1f5 100644
--- a/css/homer.css
+++ b/css/homer.css
@@ -2526,7 +2526,7 @@ span.navText {
left: 20%;
padding: 5px;
height: 523px;
- width: 33%;
+ width: 43%;
z-index: 100002;
min-height: 300px;
min-width: 200px;
diff --git a/css/report-style.css b/css/report-style.css
index 0eb1e205..83fbaf13 100644
--- a/css/report-style.css
+++ b/css/report-style.css
@@ -4,10 +4,11 @@
.white-bg {
background: #fff;
- margin-bottom: 20px;
+ margin-bottom: 5px;
+ margin-top: 5px;
}
-.begining span, .end span, .from-to span {
+.begining span, .end span, .from-to span, .to-from span {
font-weight: 700;
}
@@ -15,6 +16,7 @@
display: inline-block;
// margin-left: 20px;
padding-top: 11px;
+ padding-left: 10px;
display: inline-block;
width: 50%;
float:left;
@@ -84,7 +86,7 @@
background: #F6F6F6;
margin-top: 10px;
padding: 5px;
- font-size: 12px;
+ font-size: 10px;
}
.chart-general li input {
@@ -124,43 +126,82 @@
font-weight: 700;
}
+.S-text {
+ font-size: 12px;
+ font-weight: 800;
+ margin-left: 5px;
+ margin-right: 5px;
+}
+.XS-text {
+ font-size: 10px;
+ font-weight: 400;
+ margin-left: 5px;
+ margin-right: 5px;
+}
+
.L-text {
- font-size: 25px;
+ font-size: 22px;
font-weight: 700;
}
.XL-text {
- font-size: 45px;
+ font-size: 35px;
font-weight: 700;
line-height: 60px;
}
+.light-grey {
+ background: #c3c3c3;
+ margin-top: 10px;
+ padding-top: 8px;
+ border-radius: 5px;
+}
+
.light-orange {
background: #e6e6e6;
margin-top: 10px;
padding-top: 10px;
+ border-radius: 5px;
}
.light-blue {
background: #ccd8db;
margin-top: 10px;
padding-top: 10px;
+ border-radius: 5px;
+}
+
+.light-silver {
+ background: rgb(241, 241, 241);
+ margin-top: 10px;
+ padding-top: 10px;
+ border-radius: 5px;
}
.light-green {
background: #d3e5d8;
margin-top: 10px;
padding-top: 10px;
+ border-radius: 5px;
}
.light-green .L-text, .light-blue .L-text, .light-orange .L-text {
-line-height: 40px;
+line-height: 20px;
}
.center-text {
text-align: center;
-padding: 15px;
-min-height: 140px;
+padding: 10px;
+ // min-height: 140px;
+}
+
+.xrtp-block {
+ text-align: center;
+ padding: 10px;
+ width: auto;
+ margin-right: 4px;
+ background: #e6e6e6;
+ border-radius: 10px;
}
.green-full, .grey-full {
@@ -240,6 +281,16 @@ min-height: 140px;
float: right;
}
+.box-codec {
+ display: inline-block;
+ padding: 3px;
+ font-size: 11px;
+ color: #fff;
+ margin: 1px;
+ // float:left;
+ border-radius: 3px;
+}
+
.box-small {
padding: 15px;
font-size: 18px;
@@ -248,6 +299,15 @@ min-height: 140px;
text-align: center;
}
+.box-metrics {
+ display: inline-block;
+ padding: 0px 5px 0px 5px;
+ font-size: 11px;
+ color: #fff;
+ margin: 1px;
+ border-radius: 3px;
+}
+
.blue {
background: #003D4C;
@@ -280,7 +340,7 @@ min-height: 140px;
.padding-top {
-padding-top: 25px;
+padding-top: 5px;
}
.report-panel-body svg#Layer_1 {
@@ -325,10 +385,10 @@ padding-top: 25px;
}
-@media (max-width: 1424px) {
+@media (max-width: 2499px) {
.container {
- width: 95%;
+ width: 100%;
}
.col-lg-1, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-md-1, .col-md-10, .col-md-11, .col-md-12, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-sm-1, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-xs-1, .col-xs-10, .col-xs-11, .col-xs-12, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9 {
@@ -343,11 +403,11 @@ padding-top: 25px;
}
.L-text {
- font-size: 30px;
+ font-size: 18px;
}
.XL-text {
- font-size: 50px;
+ font-size: 35px;
line-height: 42px;
}
@@ -373,3 +433,16 @@ padding-top: 25px;
}
+.highcharts-container {
+ height: 250px;
+}
+
+.full-screen-modal {
+ top: 0;
+ left: 0;
+ width: 100%;
+}
+
+.short-p {
+ margin: 0 0 2px 0;
+}
diff --git a/fonts/fontawesome-webfont.eot b/fonts/fontawesome-webfont.eot
index 6cfd5660..9b6afaed 100755
Binary files a/fonts/fontawesome-webfont.eot and b/fonts/fontawesome-webfont.eot differ
diff --git a/fonts/fontawesome-webfont.svg b/fonts/fontawesome-webfont.svg
index a9f84695..d05688e9 100755
--- a/fonts/fontawesome-webfont.svg
+++ b/fonts/fontawesome-webfont.svg
@@ -32,473 +32,624 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/fonts/fontawesome-webfont.ttf b/fonts/fontawesome-webfont.ttf
index 5cd6cff6..26dea795 100755
Binary files a/fonts/fontawesome-webfont.ttf and b/fonts/fontawesome-webfont.ttf differ
diff --git a/fonts/fontawesome-webfont.woff b/fonts/fontawesome-webfont.woff
index 9eaecb37..dc35ce3c 100755
Binary files a/fonts/fontawesome-webfont.woff and b/fonts/fontawesome-webfont.woff differ
diff --git a/fonts/fontawesome-webfont.woff2 b/fonts/fontawesome-webfont.woff2
new file mode 100644
index 00000000..500e5172
Binary files /dev/null and b/fonts/fontawesome-webfont.woff2 differ
diff --git a/index.html b/index.html
index 16bd8996..1c18b570 100644
--- a/index.html
+++ b/index.html
@@ -3,7 +3,7 @@
- HOMER 5.0.4
+ HOMER 5.0.5
diff --git a/js/controller.js b/js/controller.js
index 6fb6ffbb..8720664e 100644
--- a/js/controller.js
+++ b/js/controller.js
@@ -116,8 +116,7 @@
eventbus.broadcast(homer.modules.pages.events.resetGridState, "1");
$location.path(homer.modules.pages.routes.home);
};
-
-
+
eventbus.subscribe(homer.modules.auth.events.userLoggedIn, function(event, args) {
if (!$scope.templateSet) {
diff --git a/js/modules/core/directives/directives.js b/js/modules/core/directives/directives.js
index df3e4073..8b734d8d 100644
--- a/js/modules/core/directives/directives.js
+++ b/js/modules/core/directives/directives.js
@@ -77,4 +77,4 @@
]);
}(angular, homer));
-
\ No newline at end of file
+
diff --git a/js/modules/core/services/search.js b/js/modules/core/services/search.js
index d9fc088d..0b4b9117 100644
--- a/js/modules/core/services/search.js
+++ b/js/modules/core/services/search.js
@@ -183,6 +183,29 @@
return defer.promise;
};
+
+ var searchQOSReport = function (data) {
+
+ var defer = $q.defer();
+
+ $http.post('api/v1/report/qos', data, {handleStatus:[403,503]}).then(
+ /* good response */
+ function (results) {
+ if(results.data.auth == "false") {
+ defer.reject('user not authorized');
+ }
+ else {
+ defer.resolve(results.data.data);
+ }
+ },
+ /* bad response */
+ function (results) {
+ defer.reject('bad response combination');
+ }
+ );
+
+ return defer.promise;
+ };
var searchLogReport = function (data) {
@@ -365,6 +388,7 @@
setSearchValue: setSearchValue,
searchValue: searchValue,
searchRTCPReport: searchRTCPReport,
+ searchQOSReport: searchQOSReport,
searchLogReport: searchLogReport,
searchQualityReport: searchQualityReport,
loadNode: loadNode
diff --git a/js/modules/pages/controllers/dialogCtrl.js b/js/modules/pages/controllers/dialogCtrl.js
index dd1a7312..108a6e9b 100644
--- a/js/modules/pages/controllers/dialogCtrl.js
+++ b/js/modules/pages/controllers/dialogCtrl.js
@@ -5,571 +5,733 @@
* Copyright (C) 2011-2015 Lorenzo Mangani QXIP B.V.
* License AGPL-3.0 http://opensource.org/licenses/AGPL-3.0
*
-*/
+ */
-(function (angular, homer) {
+(function(angular, homer) {
'use strict';
angular.module(homer.modules.pages.name)
- .controller('drawCtrl',function($scope, $uibModalInstance){
-
- console.log("OPEN DATA");
+ .controller('drawCtrl', function($scope, $uibModalInstance) {
- $scope.ok = function () {
- $uibModalInstance.close("11");
- };
+ console.log("OPEN DATA");
+
+ $scope.ok = function() {
+ $uibModalInstance.close("11");
+ };
- $scope.close = function () {
- $uibModalInstance.dismiss('cancel');
- };
+ $scope.close = function() {
+ $uibModalInstance.dismiss('cancel');
+ };
})
.controller('messageCtrl', [
- '$scope',
- homer.modules.core.services.search,
- '$homerModal',
- '$timeout',
- '$homerModalParams',
- '$sce',
- homer.modules.core.services.profile,
- function($scope, search, $homerModal, $timeout, $homerModalParams, $sce, userProfile) {
-
- var data = $homerModalParams.params;
-
- var timezone = userProfile.getProfile("timezone");
- $scope.dataLoading = true;
- $scope.showSipMessage = true;
- $scope.showSipDetails = false;
- $scope.msgOffset = timezone.offset;
-
- $scope.clickSipDetails = function() {
- console.log("details");
- };
-
+ '$scope',
+ homer.modules.core.services.search,
+ '$homerModal',
+ '$timeout',
+ '$homerModalParams',
+ '$sce',
+ homer.modules.core.services.profile,
+ function($scope, search, $homerModal, $timeout, $homerModalParams, $sce, userProfile) {
+
+ var data = $homerModalParams.params;
+
+ var timezone = userProfile.getProfile("timezone");
+ $scope.dataLoading = true;
+ $scope.showSipMessage = true;
+ $scope.showSipDetails = false;
+ $scope.msgOffset = timezone.offset;
+
+ $scope.clickSipDetails = function() {
+ console.log("details");
+ };
+
+
+ search.searchMethod(data).then(function(sdata) {
+
+ var swapText = function(text) {
+ var swpA, swpB;
- search.searchMethod(data).then( function (sdata) {
-
- var swapText = function(text){
- var swpA, swpB;
-
- text = text.split('<').join('<');
-
- swpA = sdata[0].method;
- swpB = ''+swpA+'';
- text = text.split(swpA).join(swpB);
-
- swpA = sdata[0].callid;
- swpB = ''+swpA+'';
- text = text.split(swpA).join(swpB);
-
- swpA = sdata[0].from_tag;
- swpB = ''+swpA+'';
- text = text.split(swpA).join(swpB);
-
- swpA = sdata[0].via_1_branch;
- swpB = ''+swpA+'';
- text = text.split(swpA).join(swpB);
-
-
- return $sce.trustAsHtml(text);
- };
-
- $scope.msgId = sdata[0].id;
- $scope.msgCallId = sdata[0].callid;
- //$scope.msgDate = sdata[0].date;
- $scope.msgDate = sdata[0].micro_ts/1000;
- $scope.sipPath = sdata[0].source_ip+":"+sdata[0].source_port+ " -> "+sdata[0].destination_ip+":"+sdata[0].destination_port;
- $scope.sipMessage = swapText(sdata[0].msg); //.replace(/' + sdata[0][p].split('<').join('<')+'
');
- tabjson.push(''+p +''+ ' | ' + sdata[0][p].split('<').join('<')+' |
');
- }
- } tabjson.push();
- // $scope.sipDetails = ""+tabjson.join('')+"
";
- $scope.sipDetails = "";
- $scope.trustedHtmlDetails = $sce.trustAsHtml($scope.sipDetails);
- },
- function(sdata) {
- console.log(sdata);
+ text = text.split('<').join('<');
+
+ swpA = sdata[0].method;
+ swpB = '' + swpA + '';
+ text = text.split(swpA).join(swpB);
+
+ swpA = sdata[0].callid;
+ swpB = '' + swpA + '';
+ text = text.split(swpA).join(swpB);
+
+ swpA = sdata[0].from_tag;
+ swpB = '' + swpA + '';
+ text = text.split(swpA).join(swpB);
+
+ swpA = sdata[0].via_1_branch;
+ swpB = '' + swpA + '';
+ text = text.split(swpA).join(swpB);
+
+
+ return $sce.trustAsHtml(text);
+ };
+
+ $scope.msgId = sdata[0].id;
+ $scope.msgCallId = sdata[0].callid;
+ //$scope.msgDate = sdata[0].date;
+ $scope.msgDate = sdata[0].micro_ts / 1000;
+ $scope.sipPath = sdata[0].source_ip + ":" + sdata[0].source_port + " -> " + sdata[0].destination_ip + ":" + sdata[0].destination_port;
+ $scope.sipMessage = swapText(sdata[0].msg); //.replace(/' + sdata[0][p].split('<').join('<')+'
');
+ tabjson.push('' + p + '' + ' | ' + sdata[0][p].split('<').join('<') + ' |
');
+ }
+ }
+ tabjson.push();
+ // $scope.sipDetails = ""+tabjson.join('')+"
";
+ $scope.sipDetails = "";
+ $scope.trustedHtmlDetails = $sce.trustAsHtml($scope.sipDetails);
+ },
+ function(sdata) {
return;
- }).finally(function(){
- $scope.dataLoading = false;
- //$scope.$apply();
+ }).finally(function() {
+ $scope.dataLoading = false;
+ //$scope.$apply();
});
-
+
$timeout(function() {
- if($homerModal.getOpenedModals().indexOf('tempModal') !== -1) {
+ if ($homerModal.getOpenedModals().indexOf('tempModal') !== -1) {
$homerModal.close('tempModal', 'var a', 'var b');
- }
+ }
}, 5000);
- }
- ])
- .controller('transactionCtrl', [
- '$scope',
- homer.modules.core.services.search,
- '$homerModal',
- '$homerCflow',
- '$timeout',
- '$homerModalParams',
- '$sce',
- function($scope, search, $homerModal, $homerCflow, $timeout, $homerModalParams, $sce) {
+ }
+ ])
+ .controller('transactionCtrl', [
+ '$scope',
+ homer.modules.core.services.search,
+ '$homerModal',
+ '$homerCflow',
+ '$timeout',
+ '$homerModalParams',
+ '$sce',
+ function($scope, search, $homerModal, $homerCflow, $timeout, $homerModalParams, $sce) {
var test;
-
- var data = $homerModalParams.params;
- $scope.data = data;
-
- $scope.dataLoading = true;
- $scope.showSipMessage = true;
- $scope.showSipDetails = false;
+
+ var data = $homerModalParams.params;
+ $scope.data = data;
+
+ $scope.dataLoading = true;
+ $scope.showSipMessage = true;
+ $scope.showSipDetails = false;
+
+ $scope.clickSipDetails = function() {
+ console.log("details");
+ };
+
+ $scope.expandModal = function(id) {
+ console.log("expand", id);
+ var modal = document.getElementById(id);
- $scope.clickSipDetails = function() {
- console.log("details");
+ if (!modal.style.extop) {
+ modal.style.extop = modal.style.top;
+ modal.style.exleft = modal.style.left;
+ modal.style.top = '0px';
+ modal.style.left = '0px';
+ } else {
+ modal.style.top = modal.style.extop;
+ modal.style.left = modal.style.exleft;
+ modal.style.left = (window.innerWidth - modal.style.width) /2 + 'px';
+ modal.style.extop = undefined;
+ }
+
+ modal.classList.toggle('full-screen-modal');
+ $scope.drawCanvas($scope.id, $scope.transaction);
+
+ };
+
+ $scope.id = $homerModalParams.id;
+ $scope.transaction = [];
+ $scope.clickArea = [];
+ $scope.msgCallId = $homerModalParams.params.param.search.callid[0];
+ $scope.collapsed = [];
+ $scope.enableQualityReport = false;
+ $scope.enableRTCPReport = false;
+ $scope.enableLogReport = false;
+ $scope.enableXRTPReport = false;
+ $scope.enableQOSChart = false;
+
+ $scope.colorsChart = ['aqua', 'black', 'blue', 'fuchsia', 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple', 'red', 'silver', 'teal', 'white', 'yellow'];
+
+ /* convertor */
+ $scope.XRTP2value = function(prop){
+ var res = prop;
+ switch(prop) {
+ case 'CD':
+ res = 'SEC';
+ break;
+ case 'JI':
+ res = 'JITTER';
+ break;
+ case 'PR':
+ res = 'RCVD';
+ break;
+ case 'PS':
+ res = 'SENT';
+ break;
+ case 'PL':
+ res = 'LOST';
+ break;
+ case 'PD':
+ res = 'DELAY';
+ break;
+ case 'IP':
+ res = 'MEDIA IP:PORT';
+ break;
+ default:
+ break;
+ }
+ return res;
};
- $scope.id = $homerModalParams.id;
- $scope.transaction = [];
- $scope.clickArea = [];
- $scope.msgCallId = $homerModalParams.params.param.search.callid[0];
- $scope.collapsed = [];
- $scope.enableQualityReport = false;
- $scope.enableRTCPReport = false;
- $scope.enableLogReport = false;
- $scope.enableXRTPReport = false;
-
- var getCallFileName = function() {
- var fileNameTemplete = defineExportTemplate();
- var callFileName = fileNameTemplete ;
- var ts_hms = new Date($scope.transaction.calldata[0].milli_ts);
- var fileNameTime = (ts_hms.getMonth() + 1) + "/" + ts_hms.getDate() + "/" + ts_hms.getFullYear() + " " +
- ts_hms.getHours() + ":" + ts_hms.getMinutes() + ":" + ts_hms.getSeconds() ;
-
- callFileName = callFileName.replace("#{date}",fileNameTime );
- callFileName = $.tmpl(callFileName, $scope.transaction.calldata[0]);
- return callFileName;
+ /* new param */
+ $scope.beginRTCPDataDisplay = new Date();
+ $scope.endRTCPDataDisplay = new Date();
+ $scope.beginRTCPDataIsSet = false;
+ $scope.TimeOffSetMs = (new Date($scope.beginRTCPDataDisplay)).getTimezoneOffset() * 60 * 1000;
+ $scope.calc_report = {
+ list: [],
+ from: 0,
+ to: 0,
+ totalRtcpMessages: 0,
+ totalPacketLost: 0,
+ averagePacketLost: 0,
+ maxPacketLost: 0,
+ totalPackets: 0,
+ averageJitterMsec: 0,
+ maxJitterMsec: 0
+ };
+
+ $scope.jittersFilterAll = true;
+ $scope.packetsLostFilterAll = true;
+ /* jitter */
+
+ var getCallFileName = function() {
+ var fileNameTemplete = defineExportTemplate();
+ var callFileName = fileNameTemplete;
+ var ts_hms = new Date($scope.transaction.calldata[0].milli_ts);
+ var fileNameTime = (ts_hms.getMonth() + 1) + "/" + ts_hms.getDate() + "/" + ts_hms.getFullYear() + " " +
+ ts_hms.getHours() + ":" + ts_hms.getMinutes() + ":" + ts_hms.getSeconds();
+
+ callFileName = callFileName.replace("#{date}", fileNameTime);
+ callFileName = $.tmpl(callFileName, $scope.transaction.calldata[0]);
+ return callFileName;
};
$scope.exportCanvas = function() {
- var myEl = angular.element(document.querySelectorAll("#"+$homerModalParams.id));
- var canvas = $(myEl).find('#cflowcanv');
- var a = document.createElement("a");
- a.download = getCallFileName()+".png";
- a.href = canvas[0].toDataURL("image/png");
- a.click();
- };
-
- $scope.exportPCAP = function() {
- $scope.isPcapBusy = true;
- makePcapText(this.data, 0, $scope.msgCallId);
- };
-
- $scope.exportTEXT = function() {
- $scope.isTextBusy = true;
- makePcapText(this.data, 1, $scope.msgCallId);
- };
-
- $scope.exportCloud = function() {
- $scope.isCloudBusy = true;
- makePcapText(this.data, 2, $scope.msgCallId);
- };
-
- $scope.exportShare = function() {
- //makePcapText(this.data, false, $scope.msgCallId);
- $scope.sharelink = "";
- search.createShareLink(data).then( function (msg) {
- if (msg) {
- $scope.sharelink = msg[0];
- }
- },
- function(sdata) {
- return;
- }).finally(function(){
-
- });
- };
+ var myEl = angular.element(document.querySelectorAll("#" + $homerModalParams.id));
+ var canvas = $(myEl).find('#cflowcanv');
+ var a = document.createElement("a");
+ a.download = getCallFileName() + ".png";
+ a.href = canvas[0].toDataURL("image/png");
+ a.click();
+ };
- $scope.toggleTree = function (id) {
- $scope.collapsed[id] =! $scope.collapsed[id];
- };
+ $scope.exportPCAP = function() {
+ $scope.isPcapBusy = true;
+ makePcapText(this.data, 0, $scope.msgCallId);
+ };
- $scope.drawCanvas = function (id, mydata) {
-
- $scope.clickArea = $homerCflow.setContext(id, mydata);
+ $scope.exportTEXT = function() {
+ $scope.isTextBusy = true;
+ makePcapText(this.data, 1, $scope.msgCallId);
};
-
-
- $scope.showMessage = function(data, event) {
- var search_data = {
+ $scope.exportCloud = function() {
+ $scope.isCloudBusy = true;
+ makePcapText(this.data, 2, $scope.msgCallId);
+ };
- timestamp: {
- from: parseInt(data.micro_ts/1000),
- to: parseInt(data.micro_ts/1000)
+ $scope.exportShare = function() {
+ //makePcapText(this.data, false, $scope.msgCallId);
+ $scope.sharelink = "";
+ search.createShareLink(data).then(function(msg) {
+ if (msg) {
+ $scope.sharelink = msg[0];
+ }
+ },
+ function(sdata) {
+ return;
+ }).finally(function() {
+
+ });
+ };
+
+ $scope.toggleTree = function(id) {
+ $scope.collapsed[id] = !$scope.collapsed[id];
+ };
+
+ $scope.drawCanvas = function(id, mydata) {
+
+ $scope.clickArea = $homerCflow.setContext(id, mydata);
+ };
+
+
+ $scope.showMessage = function(data, event) {
+
+ var search_data = {
+
+ timestamp: {
+ from: parseInt(data.micro_ts / 1000),
+ to: parseInt(data.micro_ts / 1000)
+ },
+ param: {
+ search: {
+ id: parseInt(data.id),
+ callid: data.callid
},
- param: {
- search: {
- id: parseInt(data.id),
- callid: data.callid
- },
- location: {
- node: data.dbnode
- },
- transaction: {
- call: false,
- registration: false,
- rest: false
- }
+ location: {
+ node: data.dbnode
+ },
+ transaction: {
+ call: false,
+ registration: false,
+ rest: false
}
+ }
};
search_data['param']['transaction'][data.trans] = true;
- var messagewindowId = ""+data.id+"_"+data.trans;
+ var messagewindowId = "" + data.id + "_" + data.trans;
$homerModal.open({
url: 'templates/dialogs/message.html',
cls: 'homer-modal-message',
- id: "message"+messagewindowId.hashCode(),
- divLeft: event.clientX.toString()+'px',
- divTop: event.clientY.toString()+'px',
+ id: "message" + messagewindowId.hashCode(),
+ divLeft: event.clientX.toString() + 'px',
+ divTop: event.clientY.toString() + 'px',
params: search_data,
onOpen: function() {
- console.log('modal1 message opened from url '+this.id);
+ console.log('modal1 message opened from url ' + this.id);
},
controller: 'messageCtrl'
});
- };
-
- $scope.checkMousePosition = function (event) {
-
- var ret = false;
- var x = event.offsetX==null?event.originalEvent.layerX-event.target.offsetLeft:event.offsetX;
- var y = event.offsetY==null?event.originalEvent.layerY-event.target.offsetTop:event.offsetY;
-
- angular.forEach($scope.clickArea, function(ca) {
- if(ca.x1 < x && ca.x2 > x && ca.y1 < y && ca.y2 > y) {
- ret = true;
- return;
- }
- });
-
- return ret;
};
-
-
- $scope.clickMousePosition = function (event) {
-
- var ret = false;
- var obj = {};
- var x = event.offsetX==null?event.originalEvent.layerX-event.target.offsetLeft:event.offsetX;
- var y = event.offsetY==null?event.originalEvent.layerY-event.target.offsetTop:event.offsetY;
-
- angular.forEach($scope.clickArea, function(ca) {
- if(ca.x1 < x && ca.x2 > x && ca.y1 < y && ca.y2 > y) {
- ret = true;
- obj = ca;
- return;
- }
- });
-
- if(ret) {
- if(obj.type == 'host') {
- console.log('clicked on host');
- }
- else if(obj.type == 'message') {
- $scope.showMessage(obj.data, event);
- }
- }
-
- return ret;
+
+ $scope.checkMousePosition = function(event) {
+
+ var ret = false;
+ var x = event.offsetX == null ? event.originalEvent.layerX - event.target.offsetLeft : event.offsetX;
+ var y = event.offsetY == null ? event.originalEvent.layerY - event.target.offsetTop : event.offsetY;
+
+ angular.forEach($scope.clickArea, function(ca) {
+ if (ca.x1 < x && ca.x2 > x && ca.y1 < y && ca.y2 > y) {
+ ret = true;
+ return;
+ }
+ });
+
+ return ret;
};
-
- $scope.reDrawCanvas = function () {
- $scope.drawCanvas($scope.id, $scope.transaction);
- $(window).resize();
+
+
+ $scope.clickMousePosition = function(event) {
+
+ var ret = false;
+ var obj = {};
+ var x = event.offsetX == null ? event.originalEvent.layerX - event.target.offsetLeft : event.offsetX;
+ var y = event.offsetY == null ? event.originalEvent.layerY - event.target.offsetTop : event.offsetY;
+
+ angular.forEach($scope.clickArea, function(ca) {
+ if (ca.x1 < x && ca.x2 > x && ca.y1 < y && ca.y2 > y) {
+ ret = true;
+ obj = ca;
+ return;
+ }
+ });
+
+ if (ret) {
+ if (obj.type == 'host') {
+ console.log('clicked on host');
+ } else if (obj.type == 'message') {
+ $scope.showMessage(obj.data, event);
+ }
+ }
+
+ return ret;
};
-
- search.searchTransaction(data).then( function (msg) {
-
- if (msg) {
- $scope.transaction = msg;
- $scope.drawCanvas($homerModalParams.id, msg);
- if(msg.rtpinfo.length > 0) {
- $scope.enableXRTPReport = true;
- $scope.xrtpreport = msg.rtpinfo;
- }
-
- // calc session duration
- if (msg.calldata) {
- console.log('Get call duration....');
- var dates = [];
- for(var i=0; i 0) {
- console.log("RTCP", msg);
- $scope.enableRTCPReport = true;
- $scope.rtcpreport = msg;
- }
- },
- function(sdata) { return;}).finally(function(){
- $scope.dataLoading = false;
- });
- };
-
- $scope.showLogReport = function(rdata) {
-
- search.searchLogReport(rdata).then( function (msg) {
-
- if (msg.length > 0) {
- $scope.enableLogReport = true;
- $scope.logreport = msg;
- }
- },
- function(sdata) { return;}).finally(function(){
- $scope.dataLoading = false;
- });
- };
-
- $scope.showQualityReport = function(rdata) {
-
- /* only rtcp-xr = 1 , nvoice = 2 and so on... */
- //report_data['param']['search']['type'] = 1;
- var type = "short";
+ $scope.addRemoveStreamSerie = function(stream, subeb) {
+
+ if(subeb == 1)
+ {
+ angular.forEach(stream["sub"], function(v, k) {
+ console.log("ZZ");
+ });
+ }
- search.searchQualityReport(type, rdata).then( function (msg) {
-
- if (msg.length > 0) {
- $scope.enableQualityReport = true;
- $scope.qualityreport = msg;
-
- // VQ Stats
- $scope.vq_mos = [];
- $scope.vq_jit = [];
- $scope.vq_loss = [];
- $scope.vq_dates = [];
- for (var key in msg) {
- if (msg.hasOwnProperty(key)) {
- // console.log(msg[key] );
- var tmpstr = JSON.stringify(msg[key].msg).split("},").join("},
");
- $scope.vq_mos.push( [ tmpstr, parseFloat(msg[key].msg.QualityEst.MOSCQ) ] );
- $scope.vq_loss.push( parseFloat(msg[key].msg.PacketLoss.NLR) );
- $scope.vq_jit.push( parseFloat(msg[key].msg.Delay.IAJ) );
- $scope.vq_dates.push( msg[key].date.split(" ")[1] );
- }
- }
- // MOS Avg
- var sum_mos = 0;
- for( var i = 0; i < $scope.vq_mos.length; i++ ){
- sum_mos = parseFloat(sum_mos) + parseFloat($scope.vq_mos[i][1]);
- }
- var avg_mos = sum_mos/$scope.vq_mos.length;
- $scope.vq_avg_mos = avg_mos.toFixed(1);
- // LOSS Total
- var sum_loss = 0;
- for( var i = 0; i < $scope.vq_loss.length; i++ ){
- sum_loss = parseInt(sum_loss) + parseInt($scope.vq_loss[i]);
- }
- // $scope.vq_avg_loss = sum_loss/$scope.vq_loss.length;
- $scope.vq_avg_loss = sum_loss;
- // JITTER Avg
- var sum_jit = 0;
- for( var i = 0; i < $scope.vq_jit.length; i++ ){
- sum_jit = parseFloat(sum_jit) + parseFloat($scope.vq_jit[i]);
- }
- var avg_jit = sum_jit/$scope.vq_jit.length;
- $scope.vq_avg_jit = avg_jit.toFixed(1);
-
-
- $scope.chartConfig = {
- chart: {
- polar: true,
- type: 'bar',
- backgroundColor:'rgba(255, 255, 255, 0.1)'
- },
- yAxis: [
- {
- title: {
- text: 'MOS'
- }
- }, {
- title: {
- text: 'Packet Loss'
- },
- opposite:true
- }, {
- labels: {
- formatter: function () {
- return this.value + 'ms';
- },
- style: {
- color: '#89A54E'
- }
- },
- title: {
- text: 'Jitter',
- style: {
- color: '#89A54E'
- }
- },
- opposite: true
- }],
- xAxis: {
- type: 'datetime',
- categories: $scope.vq_dates
- },
- series: [
- { data: $scope.vq_jit, "name": "Jitter", "type": "spline", yAxis: 2 },
- { data: $scope.vq_loss, "name": "Packet Loss", "type": "column", yAxis: 1 },
- { data: $scope.vq_mos, "name": "MOS", "type": "column", yAxis: 0 }
- ],
- title: {
- text: ''
- },
- size: { height: '250' },
- loading: false
- };
-
- /*
- $scope.reflow = function () {
- $scope.$broadcast('highchartsng.reflow');
- };
-
- $timeout(function() {
- $scope.$broadcast('highchartsng.reflow');
- });
- */
- }
- },
- function(sdata) { return;}).finally(function(){
- $scope.dataLoading = false;
- });
- };
-
-
- $scope.showRTCPReport(data);
- $scope.showLogReport(data);
- $scope.showQualityReport(data);
- var makePcapText = function(fdata, type, callid)
- {
- search.makePcapTextforTransaction(fdata, type).then( function (msg) {
-
- $scope.isPcapBusy = false;
- $scope.isTextBusy = false;
- $scope.isCloudBusy = false;
-
- var filename = getCallFileName()+".pcap";
- var content_type = "application/pcap";
-
- if(type == 1) {
- filename = getCallFileName()+".txt";
- content_type = "attacment/text;charset=utf-8";
- }
- else if(type == 2) {
- if(msg.data && msg.data.hasOwnProperty("url")) {
- window.sweetAlert({ title: "Export Done!", text: "Your PCAP can be accessed here", html: true });
- }
- else {
- var error = "Please check your settings";
- if(msg.data && msg.data.hasOwnProperty("exceptions")) error = msg.data.exceptions;
- window.sweetAlert({ title: "Error", type: "error", text: "Your PCAP couldn't be uploaded!
"+error, html: true });
- }
- return;
- }
-
- var blob = new Blob([msg], {type: content_type});
- saveAs(blob, filename);
-
- },
- function(sdata) {
- return;
- }).finally(function(){
- });
- };
+ var selData = $scope.presetQOSChartData();
+ $scope.showQOSChart(selData);
+ };
+
+
+ $scope.presetQOSChartData = function() {
+
+ var seriesData = [];
+ var chartData = $scope.chartData;
+ $scope.selectedColorsChart = [];
+ angular.forEach(chartData, function(count, key) {
+
+ if($scope.streamsChart && $scope.streamsChart[key] && $scope.streamsChart[key]["enable"] == false)
+ return;
+
+ var localData = chartData[key];
+ angular.forEach(localData, function(das, kes) {
+
+ /* skip it */
+
+ if($scope.streamsChart[key]["sub"][kes]["enable"] == false) return;
+
+ var sar = {};
+ sar["name"] = kes;
+ sar["type"] = "line";
+ sar["color"] = $scope.streamsChart[key]["sub"][kes]["color"];
+
+ var lDas = [];
+ angular.forEach(das, function(v, k) { lDas.push([v[0],v[1]]);});
+
+ lDas.sort(function(a, b) {
+ return a[0] - b[0];
+ });
+ sar["data"] = lDas;
+ seriesData.push(sar);
+ });
+ });
+ return seriesData;
+ };
+
+
+ $scope.showQOSChart = function(seriesData) {
+
+ $scope.enableQOSChart = true;
+
+ $scope.chartConfig = {
+ chart: {
+ type: 'line'
+ },
+ title: {
+ text: "TEST",
+ style: {
+ display: "none"
+ }
+ },
+ xAxis: {
+ title: {
+ text: null
+ },
+ type: "datetime"
+ },
+ yAxis: {
+ title: {
+ text: null
+ },
+ min: 0
+ },
+ plotOptions: {
+ column: {}
+ },
+ tooltip: {},
+ legend: {
+ enabled: false,
+ borderWidth: 0
+ },
+ series: seriesData,
+ func: function(chart) {
+ $scope.$evalAsync(function () {
+ chart.reflow();
+ });
+ }
+ };
+
+ $scope.chartConfig.chart["zoomType"] = "x";
+ $scope.chartConfig.tooltip["crosshairs"] = true;
+ $scope.chartConfig.tooltip["shared"] = true;
+ };
+ $scope.refreshChart = function() {
+ $timeout(function() {
+ $scope.$broadcast('highchartsng.reflow');
+ }, 30);
+ };
+
+ $scope.showLogReport = function(rdata) {
+
+ search.searchLogReport(rdata).then(function(msg) {
+
+ if (msg.length > 0) {
+ $scope.enableLogReport = true;
+ $scope.logreport = msg;
+ }
+ },
+ function(sdata) {
+ return;
+ }).finally(function() {
+ $scope.dataLoading = false;
+ });
+ };
+
+ $scope.setRtcpMembers = function() {
+ $scope.rtcpMembers = [];
+ var tmp = {};
+ $scope.rtcpreport.forEach(function(rtcpData) {
+ var currentName = rtcpData.source_ip + " -> " + rtcpData.destination_ip;
+ if (tmp[currentName] == undefined) {
+ $scope.rtcpMembers.push({
+ name: currentName,
+ isShowJitter: true,
+ isShowPacketLost: true,
+ isShowStream: true
+ });
+ tmp[currentName] = currentName;
+ }
+ });
+ console.log("$scope.rtcpMembers: ", $scope.rtcpMembers);
+ }
+
+
+ // console.log(data);
+ $scope.showQOSReport(data);
+ $scope.showLogReport(data);
+ var makePcapText = function(fdata, type, callid) {
+ search.makePcapTextforTransaction(fdata, type).then(function(msg) {
+
+ $scope.isPcapBusy = false;
+ $scope.isTextBusy = false;
+ $scope.isCloudBusy = false;
+
+ var filename = getCallFileName() + ".pcap";
+ var content_type = "application/pcap";
+
+ if (type == 1) {
+ filename = getCallFileName() + ".txt";
+ content_type = "attacment/text;charset=utf-8";
+ } else if (type == 2) {
+ if (msg.data && msg.data.hasOwnProperty("url")) {
+ window.sweetAlert({
+ title: "Export Done!",
+ text: "Your PCAP can be accessed here",
+ html: true
+ });
+ } else {
+ var error = "Please check your settings";
+ if (msg.data && msg.data.hasOwnProperty("exceptions")) error = msg.data.exceptions;
+ window.sweetAlert({
+ title: "Error",
+ type: "error",
+ text: "Your PCAP couldn't be uploaded!
" + error,
+ html: true
+ });
+ }
+ return;
+ }
+
+ var blob = new Blob([msg], {
+ type: content_type
+ });
+ saveAs(blob, filename);
+
+ },
+ function(sdata) {
+ return;
+ }).finally(function() {});
+ };
+
$timeout(function() {
- if($homerModal.getOpenedModals().indexOf('tempModal') !== -1) {
+ if ($homerModal.getOpenedModals().indexOf('tempModal') !== -1) {
$homerModal.close('tempModal', 'var a', 'var b');
- }
+ }
}, 5000);
-
-
-
+
+
+
$scope.treedata2 = [{
- "id": 1,
- "title": "node1",
- "nodes": [
- {
- "id": 11,
- "title": "node1.1",
- "nodes": [
- {
- "id": 111,
- "title": "node1.1.1",
- "nodes": []
- }
- ]
- },
- {
- "id": 12,
- "title": "node1.2",
- "nodes": []
- }
- ]
- }, {
- "id": 2,
- "title": "node2",
- "nodes": [
- {
- "id": 21,
- "title": "node2.1",
- "nodes": []
- },
- {
- "id": 22,
- "title": "node2.2",
- "nodes": []
- }
- ]
- }, {
- "id": 3,
- "title": "node3",
- "nodes": [
- {
- "id": 31,
- "title": "node3.1",
- "nodes": []
- }
- ]
- }];
-
- }
- ]);
+ "id": 1,
+ "title": "node1",
+ "nodes": [{
+ "id": 11,
+ "title": "node1.1",
+ "nodes": [{
+ "id": 111,
+ "title": "node1.1.1",
+ "nodes": []
+ }]
+ }, {
+ "id": 12,
+ "title": "node1.2",
+ "nodes": []
+ }]
+ }, {
+ "id": 2,
+ "title": "node2",
+ "nodes": [{
+ "id": 21,
+ "title": "node2.1",
+ "nodes": []
+ }, {
+ "id": 22,
+ "title": "node2.2",
+ "nodes": []
+ }]
+ }, {
+ "id": 3,
+ "title": "node3",
+ "nodes": [{
+ "id": 31,
+ "title": "node3.1",
+ "nodes": []
+ }]
+ }];
+
+ }
+ ]);
}(angular, homer));
diff --git a/js/widgets/sipcapture/sipcapture.js b/js/widgets/sipcapture/sipcapture.js
index 96c74af0..ab9f75d4 100644
--- a/js/widgets/sipcapture/sipcapture.js
+++ b/js/widgets/sipcapture/sipcapture.js
@@ -215,7 +215,7 @@ angular.module("homer.widgets.sipcapture", [ "adf.provider", "highcharts-ng", "a
$scope.chartHighchart = true;
var seriesData = checkData(sipdata);
-
+
if (config.chart.type["value"] == "pie") {
$scope.chartConfig = {
chart: {
@@ -1250,6 +1250,7 @@ sipcaptureWdgt.flot.stackedAreaChart.prepare = function($scope, animate, data) {
}
}
+ console.log(data);
$scope.flotData = data;
return 1;
diff --git a/lib/highcharts/highcharts-ng.js b/lib/highcharts/highcharts-ng.js
index 47268e65..94567e05 100644
--- a/lib/highcharts/highcharts-ng.js
+++ b/lib/highcharts/highcharts-ng.js
@@ -1,18 +1,84 @@
if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.exports === exports){
module.exports = 'highcharts-ng';
}
+
(function () {
'use strict';
/*global angular: false, Highcharts: false */
- angular.module('highcharts-ng', [])
- .factory('highchartsNGUtils', highchartsNGUtils)
- .directive('highchart', ['highchartsNGUtils', '$timeout', highchart]);
-
- function highchartsNGUtils() {
+ angular.module('highcharts-ng', [])
+ .provider('highchartsNG', highchartsNGProvider)
+ .directive('highchart', ['highchartsNG', '$timeout', highchart]);
+
+ function highchartsNGProvider(){
+ var modules = [];
+ var basePath = false;
+ var lazyLoad = false;
return {
-
+ HIGHCHART: 'highcharts.js',
+ HIGHSTOCK: 'stock/highstock.js',
+ basePath: function (p) {
+ basePath = p;
+ },
+ lazyLoad: function (list) {
+ if (list === undefined) {
+ modules = [this.HIGHCHART];
+ } else {
+ modules = list;
+ }
+ lazyLoad = true;
+ },
+ $get: ['$window', '$rootScope', function ($window, $rootScope) {
+ if (!basePath) {
+ basePath = (window.location.protocol === 'https:' ? 'https' : 'http') + '://code.highcharts.com/';
+ }
+ return highchartsNG($window, $rootScope, lazyLoad, basePath, modules);
+ }]
+ };
+ }
+ function highchartsNG($window, $rootScope, lazyload, basePath, modules) {
+ var readyQueue = [];
+ var loading = false;
+ return {
+ lazyLoad:lazyload,
+ ready: function (callback, thisArg) {
+ if (typeof $window.Highcharts !== 'undefined' || !lazyload) {
+ callback();
+ } else {
+ readyQueue.push([callback, thisArg]);
+ if (loading) {
+ return;
+ }
+ loading = true;
+ var self = this;
+ if (typeof jQuery === 'undefined') {
+ modules.unshift('adapters/standalone-framework.js');
+ }
+ var doWork = function () {
+ if (modules.length === 0) {
+ loading = false;
+ $rootScope.$apply(function () {
+ angular.forEach(readyQueue, function (e) {
+ // invoke callback passing 'thisArg'
+ e[0].apply(e[1], []);
+ });
+ });
+ } else {
+ var s = modules.shift();
+ self.loadScript(s, doWork);
+ }
+ };
+ doWork();
+ }
+ },
+ loadScript: function (path, callback) {
+ var s = document.createElement('script');
+ s.type = 'text/javascript';
+ s.src = basePath + path;
+ s.onload = callback;
+ document.getElementsByTagName('body')[0].appendChild(s);
+ },
//IE8 support
indexOf: function (arr, find, i /*opt*/) {
if (i === undefined) i = 0;
@@ -47,6 +113,7 @@ if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.ex
destination[i] = deepExtend(destination[i] || {}, source[i]);
}
} else if (angular.isObject(source)) {
+ destination = angular.isObject(destination) ? destination : {};
for (var property in source) {
destination[property] = deepExtend(destination[property] || {}, source[property]);
}
@@ -93,10 +160,15 @@ if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.ex
series: [],
credits: {},
plotOptions: {},
- navigator: {enabled: false}
+ navigator: {enabled: false},
+ xAxis: {
+ events: {}
+ },
+ yAxis: {
+ events: {}
+ }
};
-
if (config.options) {
mergedOptions = highchartsNGUtils.deepExtend(defaultOptions, config.options);
} else {
@@ -106,7 +178,7 @@ if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.ex
angular.forEach(axisNames, function(axisName) {
if(angular.isDefined(config[axisName])) {
- mergedOptions[axisName] = angular.copy(config[axisName]);
+ mergedOptions[axisName] = highchartsNGUtils.deepExtend(mergedOptions[axisName] || {}, config[axisName]);
if(angular.isDefined(config[axisName].currentMin) ||
angular.isDefined(config[axisName].currentMax)) {
@@ -131,6 +203,16 @@ if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.ex
scope.config[axisName].currentMin = this[axisName][0].min || scope.config[axisName].currentMin;
scope.config[axisName].currentMax = this[axisName][0].max || scope.config[axisName].currentMax;
});
+ highchartsNGUtils.prependMethod(mergedOptions[axisName].events, 'setExtremes', function (e) {
+ if (e.trigger && e.trigger !== 'zoom') { // zoom trigger is handled by selection event
+ $timeout(function () {
+ scope.config[axisName].currentMin = e.min;
+ scope.config[axisName].currentMax = e.max;
+ scope.config[axisName].min = e.min; // set min and max to adjust scrollbar/navigator
+ scope.config[axisName].max = e.max;
+ }, 0);
+ }
+ });
}
}
});
@@ -152,37 +234,17 @@ if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.ex
mergedOptions.chart.height = config.size.height;
}
}
-
- if (config.chart.options3d) {
- mergedOptions.chart.options3d = config.chart.options3d;
- }
-
- if (config.chart.tooltip) {
- mergedOptions.chart.tooltip = config.chart.tooltip;
- }
-
- if (config.colors) {
- mergedOptions.colors = config.colors;
- }
-
- if (config.chart.margin) {
- mergedOptions.chart.margin = config.chart.margin;
- }
-
- if (config.legend) {
- mergedOptions.legend = config.legend;
- }
-
- if (config.plotOptions) {
- mergedOptions.plotOptions = config.plotOptions;
- }
return mergedOptions;
};
var updateZoom = function (axis, modelAxis) {
var extremes = axis.getExtremes();
if(modelAxis.currentMin !== extremes.dataMin || modelAxis.currentMax !== extremes.dataMax) {
- axis.setExtremes(modelAxis.currentMin, modelAxis.currentMax, false);
+ if (axis.setExtremes) {
+ axis.setExtremes(modelAxis.currentMin, modelAxis.currentMax, false);
+ } else {
+ axis.detachedsetExtremes(modelAxis.currentMin, modelAxis.currentMax, false);
+ }
}
};
@@ -193,7 +255,10 @@ if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.ex
};
var chartOptionsWithoutEasyOptions = function (options) {
- return highchartsNGUtils.deepExtend({}, options, {data: null, visible: null});
+ return angular.extend(
+ highchartsNGUtils.deepExtend({}, options),
+ { data: null, visible: null }
+ );
};
var getChartType = function(scope) {
@@ -202,7 +267,7 @@ if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.ex
(scope.config.useHighStocks ? 'StockChart' : 'Chart');
};
- return {
+ var res = {
restrict: 'EAC',
replace: true,
template: '',
@@ -223,7 +288,7 @@ if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.ex
if(series) {
var setIds = ensureIds(series);
- if(setIds) {
+ if(setIds && !scope.disableDataWatch) {
//If we have set some ids this will trigger another digest cycle.
//In this scenario just return early and let the next cycle take care of changes
return false;
@@ -289,15 +354,7 @@ if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.ex
var func = config.func || undefined;
var chartType = getChartType(scope);
- Highcharts.setOptions({
- global : {
- useUTC : false
- }
- });
-
chart = new Highcharts[chartType](mergedOptions, func);
-
- scope.$parent.$parent.chartObj = chart;
for (var i = 0; i < axisNames.length; i++) {
if (config[axisNames[i]]) {
@@ -312,8 +369,6 @@ if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.ex
};
};
-
-
initChart();
@@ -427,5 +482,17 @@ if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.ex
}
};
+
+ // override link fn if lazy loading is enabled
+ if(highchartsNGUtils.lazyLoad){
+ var oldLink = res.link;
+ res.link = function(){
+ var args = arguments;
+ highchartsNGUtils.ready(function(){
+ oldLink.apply(this, args);
+ }, this);
+ };
+ }
+ return res;
}
}());
diff --git a/share/app.js b/share/app.js
index ed06dcfe..5769ee59 100644
--- a/share/app.js
+++ b/share/app.js
@@ -19,6 +19,7 @@
homer.modules.core.name,
'homer.modal',
'homer.cflow',
+ 'highcharts-ng',
'homerCore'
]);
diff --git a/share/controller.js b/share/controller.js
index ca9b90c9..f4781659 100644
--- a/share/controller.js
+++ b/share/controller.js
@@ -30,9 +30,6 @@
var tid = $location.path();
if(tid.substring(0, 1) == '/') tid = tid.substring(1);
- console.log(tid);
-
-
console.log('HOMER INIT:',$rootScope);
var test;
@@ -59,6 +56,9 @@
$scope.enableRTCPReport = false;
$scope.enableLogReport = false;
$scope.enableXRTPReport = false;
+ $scope.enableQOSChart = false;
+ $scope.colorsChart = ['aqua', 'black', 'blue', 'fuchsia', 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple', 'red', 'silver', 'teal', 'white', 'yellow'];
+
// Voicenter vars
@@ -81,6 +81,7 @@
$scope.jittersFilterAll = true;
$scope.packetsLostFilterAll = true;
+
// Voicenter vars end
var getCallFileName = function() {
@@ -190,7 +191,6 @@
if(ret) {
if(obj.type == 'host') {
console.log('clicked on host');
- console.log(obj);
}
else if(obj.type == 'message') {
$scope.showMessage(obj.data, event);
@@ -211,14 +211,11 @@
}
search.searchTransactionById(data).then( function (msg) {
- console.log(msg);
if (msg.calldata.length > 0) {
$scope.transaction = msg;
$scope.showPage = true;
$scope.drawCanvas('shareit', msg);
-
- $scope.voicenterAnalyzeSipData(msg); // Voicenter function
- $scope.showRTCPReport(data);
+ //$scope.showRTCPReport(data);
}
else {
$rootScope.showError = true;
@@ -262,8 +259,6 @@
$scope.enableRTCPReport = true;
$scope.rtcpreport = msg;
- $scope.setRtcpMembers(rdata); // Voicenter function
- $scope.showRTCPChart(); // Voicenter function
} else {
console.log('DISCARDING:',msg);
}
@@ -274,6 +269,230 @@
};
+ $scope.showQOSReport = function(rdata) {
+
+ search.searchQOSReportById(rdata).then(function(msg) {
+
+ var chartDataExtended = {
+ list: [],
+ from: 0,
+ to: 0,
+ totalRtcpMessages: 0,
+ totalPacketLost: 0,
+ totalJitters: 0,
+ averageJitterMsec: 0,
+ averagePacketLost: 0,
+ maxPacketLost: 0,
+ totalPackets: 0,
+ maxJitterMsec: 0,
+ msg: [],
+ mos: [],
+ averageMos: 0,
+ worstMos: 5
+ };
+
+
+ //$scope.rtcpreport = msg;
+ //$scope.setRtcpMembers(rdata); // Voicenter function
+ //$scope.showRTCPChart(); // Voicenter function
+
+ if (msg.global) {
+
+ try {
+ if (msg.global.main) {
+ // Call Duration
+ var adur = new Date(null); adur.setSeconds(msg.global.main.duration/1000); // seconds
+ $scope.call_duration = adur.toISOString().substr(11, 8);
+ // Map averages
+ chartDataExtended.averageMos = (msg.global.main.mos_average).toFixed(2);
+ chartDataExtended.worstMos = (msg.global.main.mos_worst).toFixed(2);
+ chartDataExtended.totalPacketLost = msg.global.main.packets_lost;
+ chartDataExtended.maxPacketLost = msg.global.main.packets_lost;
+ chartDataExtended.totalPackets = msg.global.main.packets_sent + msg.global.main.packets_recv;
+ chartDataExtended.averagePacketLost = (msg.global.main.packets_lost * 100 / chartDataExtended.totalPackets).toFixed(1);
+ chartDataExtended.averageJitterMsec = msg.global.main.jitter_avg.toFixed(2);
+ chartDataExtended.maxJitterMsec = msg.global.main.jitter_max.toFixed(2);
+ }
+ } catch(e) { console.log('no rtcp stats'); }
+
+
+ try {
+ if (msg.global.calls) {
+ var leg = 1;
+ $scope.calc_calls = msg.global.calls;
+ }
+ } catch(e) { console.log('no call stats'); }
+
+ try {
+ if (msg.reports.xrtpstats.main) {
+ $scope.calc_xrtp = msg.reports.xrtpstats.main;
+ $scope.calc_xrtp.mos_avg = $scope.calc_xrtp.mos_avg.toFixed(2);
+ $scope.calc_xrtp.mos_worst = $scope.calc_xrtp.mos_worst.toFixed(2);
+ $scope.calc_xrtp.packets_all = parseInt($scope.calc_xrtp.packets_sent) + parseInt($scope.calc_xrtp.packets_recv);
+ $scope.calc_xrtp.lost_avg = ($scope.calc_xrtp.packets_lost * 100 / $scope.calc_xrtp.packets_all ).toFixed(2);
+ }
+ } catch(e) { console.log('no x-rtp stats'); }
+
+
+ // RTCP
+ try {
+ if(msg.reports && msg.reports.rtcp && msg.reports.rtcp.chart) {
+ //$scope.showQOSChart();
+ var charts = msg.reports.rtcp.chart;
+ // RTCP-XR
+ if(msg.reports.rtcpxr && msg.reports.rtcpxr.chart) {
+ //$scope.chartData.concat(msg.reports.rtcpxr.chart);
+ var xrcharts = msg.reports.rtcpxr.chart;
+ angular.forEach(xrcharts, function(count, key) {
+ if(!charts[key]) charts[key] = count;
+ });
+ }
+
+ $scope.chartData = charts;
+ $scope.streamsChart = {};
+ var i = 0;
+ angular.forEach(charts, function(count, key) {
+ $scope.streamsChart[key] = {};
+ $scope.streamsChart[key]["enable"] = true;
+ $scope.streamsChart[key]["name"] = key;
+ $scope.streamsChart[key]["short_name"] = key.substr(key.indexOf(' ')+1);
+ $scope.streamsChart[key]["type"] = key.substr(0, key.indexOf(' '));
+ $scope.streamsChart[key]["sub"] = {};
+ angular.forEach(count, function(v, k) {
+ $scope.streamsChart[key]["sub"][k] = {};
+ $scope.streamsChart[key]["sub"][k]["enable"] = false;
+ $scope.streamsChart[key]["sub"][k]["parent"] = key;
+ $scope.streamsChart[key]["sub"][k]["name"] = k;
+ $scope.streamsChart[key]["sub"][k]["color"]= $scope.colorsChart[i++];
+ if (k == 'mos') $scope.streamsChart[key]["sub"][k]["enable"] = true;
+ });
+ });
+
+ var selData = $scope.presetQOSChartData();
+ $scope.showQOSChart(selData);
+
+ }
+ } catch(e) { console.log('no chart data'); }
+
+
+
+ // $scope.RTCPChart = msg.reports.rtcp.chart;
+ // console.log($scope.RTCPChart);
+
+ }
+
+ //showQOSChart
+ $scope.calc_report = chartDataExtended;
+ $scope.enableRTCPReport = true;
+
+ },
+ function(sdata) {
+ return;
+ }).finally(function() {
+ $scope.dataLoading = false;
+ });
+ };
+
+ $scope.addRemoveStreamSerie = function(stream, subeb) {
+
+ var selData = $scope.presetQOSChartData();
+ $scope.showQOSChart(selData);
+ };
+
+
+ $scope.presetQOSChartData = function() {
+
+ var seriesData = [];
+ var chartData = $scope.chartData;
+ $scope.selectedColorsChart = [];
+ angular.forEach(chartData, function(count, key) {
+
+ if($scope.streamsChart && $scope.streamsChart[key] && $scope.streamsChart[key]["enable"] == false)
+ return;
+
+ var localData = chartData[key];
+ angular.forEach(localData, function(das, kes) {
+
+ /* skip it */
+
+ if($scope.streamsChart[key]["sub"][kes]["enable"] == false) return;
+
+ var sar = {};
+ sar["name"] = kes;
+ sar["type"] = "line";
+ sar["color"] = $scope.streamsChart[key]["sub"][kes]["color"];
+
+ var lDas = [];
+ angular.forEach(das, function(v, k) { lDas.push([v[0],v[1]]);});
+
+ lDas.sort(function(a, b) {
+ return a[0] - b[0];
+ });
+ sar["data"] = lDas;
+ seriesData.push(sar);
+ });
+ });
+ return seriesData;
+ };
+
+
+ $scope.showQOSChart = function(seriesData) {
+
+ $scope.enableQOSChart = true;
+
+ $scope.chartConfig = {
+ chart: {
+ type: 'line'
+ },
+ credits: {
+ enabled: false
+ },
+ title: {
+ text: "TEST",
+ style: {
+ display: "none"
+ }
+ },
+ xAxis: {
+ title: {
+ text: null
+ },
+ type: "datetime"
+ },
+ yAxis: {
+ title: {
+ text: null
+ },
+ min: 0
+ },
+ plotOptions: {
+ column: {}
+ },
+ tooltip: {},
+ legend: {
+ enabled: false,
+ borderWidth: 0
+ },
+ series: seriesData,
+ func: function(chart) {
+ $scope.$evalAsync(function () {
+ chart.reflow();
+ });
+ }
+ };
+
+ $scope.chartConfig.chart["zoomType"] = "x";
+ $scope.chartConfig.tooltip["crosshairs"] = true;
+ $scope.chartConfig.tooltip["shared"] = true;
+
+ };
+
+ $scope.refreshChart = function() {
+ $timeout(function() {
+ $scope.$broadcast('highchartsng.reflow');
+ }, 30);
+ };
+
$scope.showLogReport = function(rdata) {
search.searchLogReportById(rdata).then( function (msg) {
@@ -305,690 +524,10 @@
$scope.dataLoading = false;
});
};
-
- // Voicenter implimentations
-
- $scope.showRTCPChart = function (rdata) {
-
- $scope.calc_report = $scope.setDataBySelectedRange();
- //$scope.setChartSeries();
- //$scope.filterRtcpData(true);
-
- console.log("Start showRTCPChart ",$scope.rtcpreport);
- if($scope.RTCPChart != undefined){
- $scope.RTCPChart.destroy ();
- }
-
- $scope.RTCPChart = new Highcharts.Chart({
- chart: {
- renderTo: 'rtcpchart-container',
- type: 'line',
- // width: '1000',
- zoomType: 'x'
- },
- title: {
- text: 'Information graph'
- },
- subtitle: {
- text: 'Jitters & Packets lost'
- },
- xAxis: {
- type: 'datetime',
- dateTimeLabelFormats: { // don't display the dummy year
- month: '%e. %b',
- year: '%b'
- },
- title: {
- text: 'Duration'
- },
- //max: rtcpChartData.to,
- //min: rtcpChartData.from
- },
- yAxis: {
-
- title: {
- text: 'Amount'
- },
- minRange:0,
- startOnTick:0,
- min: 0
- },
- plotOptions: {
- series: {
- cursor: 'pointer',
- point: {
- events: {
-
- click: function (e) {
- var clickTimeStemp= e.delegateTarget.options.x + $scope.TimeOffSetMs ;
-
- if(!$scope.beginRTCPDataIsSet) {
- // Select from date:
- $scope.endRTCPDataDisplay = 0;
- $scope.beginRTCPDataDisplay = clickTimeStemp ;
- $scope.beginRTCPDataIsSet=true;
- $("#beginningDiv").addClass("bold");
-
- } else {
- // Select end date:
- $scope.endRTCPDataDisplay = clickTimeStemp;
- $scope.beginRTCPDataIsSet=false;
- $("#beginningDiv").removeClass("bold");
-
-
- // Switch between dates in case of reverse selection
- if( $scope.endRTCPDataDisplay < $scope.beginRTCPDataDisplay ){
- var tmp = $scope.endRTCPDataDisplay;
- $scope.endRTCPDataDisplay = $scope.beginRTCPDataDisplay;
- $scope.beginRTCPDataDisplay = tmp;
- }
-
-
- // Render data
- $scope.calc_report = $scope.setDataBySelectedRange();
- $scope.setChartSeries();
- $scope.$apply();
- }
- }
- }
-
- },
- marker: {
- lineWidth: 1
- }
- },
- line: {
-
- events: {
- legendItemClick: function (item) {
- //alert('I am an alert');
- //console.log("Clicked ", item);
- return false;
- // <== returning false will cancel the default action
- }
- }
- ,
- showInLegend: true
- }
- }
- });
-
- $scope.setChartSeries();
- $scope.filterRtcpData(true);
- //$scope.$apply();
- };
-
- $scope.filterRtcpData = function(showAll) {
-
- if(showAll==null){showAll=false;}
-
- $("#beginRTCPDataInputDate").val((new Date($scope.beginRTCPDataDisplay).toLocaleDateString("he-IL")));
- $("#beginRTCPDataInputTime").val((new Date($scope.beginRTCPDataDisplay).toLocaleTimeString("he-IL")));
- $("#endRTCPDataInputDate").val((new Date($scope.endRTCPDataDisplay).toLocaleDateString("he-IL")));
- $("#endRTCPDataInputTime").val((new Date($scope.endRTCPDataDisplay).toLocaleTimeString("he-IL")));
-
- $("div[id*=RtcpDiv]").each(function(){
- // if( $(this).attr('id').match(/pattern/) ) {
- // your code goes here
- // }
-
-
- var DivTime = (this.id.toString().replace("RtcpDiv-",""))/1000 ;//+ $scope.TimeOffSetMs ;
-
- //console.log("beginRTCPDataDisplay-", $scope.beginRTCPDataDisplay);
- //console.log("DivTime--------------",DivTime);
- //console.log("endRTCPDataDisplay---",$scope.endRTCPDataDisplay);
- //$(this).show(500);
- if (($scope.beginRTCPDataDisplay<=DivTime && $scope.endRTCPDataDisplay>=DivTime)||showAll){
-
- $(this).show(500);
- }else{
-
- $(this).hide(500);
- }
- });
- };
-
- $scope.setChartSeries = function(){
- // Remove existing series
- console.log("$scope.rtcpMembers",$scope.rtcpMembers);
- console.log("$scope.calc_report",$scope.calc_report);
- while($scope.RTCPChart.series.length > 0)
- $scope.RTCPChart.series[0].remove(true);
-
- // Add series
- $scope.calc_report.list.forEach(function(ip) {
- $scope.rtcpMembers.forEach(function(member){
- console.log("ip",ip);
- console.log("member",member);
-
- if(ip == member.name)
- {
- if(member.isShowJitter == true)
- {
- $scope.RTCPChart.addSeries({name: "Jitter " + $scope.calc_report[ip].source_ip + " -> " + $scope.calc_report[ip].destination_ip, data: $scope.calc_report[ip].jitter});
- console.log("add jitter serie: " , {name: "Jitter " + $scope.calc_report[ip].source_ip + " -> " + $scope.calc_report[ip].destination_ip, data: $scope.calc_report[ip].jitter});
- }
- if(member.isShowPacketLost == true)
- {
- $scope.RTCPChart.addSeries({name: "Packets Lost " + $scope.calc_report[ip].source_ip + " -> " + $scope.calc_report[ip].destination_ip, data: $scope.calc_report[ip].packets_lost});
- console.log("add rtcp series :", {name: "Packets Lost " + $scope.calc_report[ip].source_ip + " -> " + $scope.calc_report[ip].destination_ip, data: $scope.calc_report[ip].packets_lost});
- }
- }
- });
-
-
- //totalPackets += $scope.calc_report[ip].totalPackets;
-
- });
- console.log("$scope.RTCPChart",$scope.RTCPChart);
- }
-
- $scope.vc_CalculateJitterMos = function(rtt, jitter, num_packets_lost){
- /*
- Take the rtt latency, add jitter, but double the impact to latency
- then add 10 for protocol latancies
- */
- if(rtt == 0)
- rtt = 10;
- var effective_latency = rtt + (jitter * 2) + 10;
- var mos_val;
- var r_factor;
- /*
- Implement a basic curve - deduct 4 for the r_factor at 160ms of latency
- (round trip). Anything over that gets a much more agressive deduction
- */
- if (effective_latency < 160)
- {
- r_factor = 93.2 - (effective_latency / 40);
- }
- else
- {
- r_factor = 93.2 - (effective_latency - 120) / 10;
- }
- /*
- Now, let's deduct 2.5 r_factor per percentage of num_packets_lost
- */
- r_factor = r_factor - (num_packets_lost * 100 * 2.5);
- if (r_factor > 100)
- r_factor = 100;
- else if (r_factor < 0)
- r_factor = 0;
-
-
- /* Convert the r_factor into an MOS value. (this is a known formula) */
- mos_val = 1 + (0.035) * (r_factor) + (0.000007) * (r_factor) * ((r_factor) - 60) * (100 - (r_factor));
-
- if (mos_val > 5)
- mos_val = 5;
-
- //LERR("[RTT: %.2f][Jitter: %.2f] [# Packet Lost: %u][R-Factor: %.2f][MOS: %.2f]", rtt, jitter, num_packets_lost, *r_factor, mos_val);
-
- return (mos_val);
- }
-
- $scope.setDataBySelectedRange = function() {
- var chartDataExtended = {
- list : [],
- from : 0,
- to: 0,
- totalRtcpMessages: 0,
- totalPacketLost: 0,
- totalJitters: 0,
- averageJitterMsec: 0,
- averagePacketLost: 0,
- maxPacketLost: 0,
- totalPackets: 0,
- maxJitterMsec: 0,
- msg: [],
- mos:[] ,
- averageMos:0,
- worstMos:5
- };
-
- var beginDate = $scope.beginRTCPDataDisplay * 1000;
- var endDate = $scope.endRTCPDataDisplay * 1000;
-
- console.log(beginDate, endDate);
-
-
- var mosCounter = 0;
- $scope.rtcpreport.forEach(function(rtcpData) {
-
- console.log("rtcpData loop ",rtcpData);
- if(rtcpData.msg != undefined && rtcpData.msg != null ){
-
- //console.log("from " , beginDate, rtcpData.micro_ts);
- //console.log("to " , endDate, rtcpData.micro_ts);
-
-
-
- if (beginDate <= rtcpData.micro_ts && endDate >= rtcpData.micro_ts){ // Check we are in selected range
- if(rtcpData.msg.report_blocks != undefined && rtcpData.msg.report_blocks != null){
-
-
- if(rtcpData.msg.report_blocks[0] !== undefined) {
- mosCounter++;
- var tmpMos = $scope.vc_CalculateJitterMos(rtcpData.msg.report_blocks[0].dlsr,rtcpData.msg.report_blocks[0].ia_jitter,rtcpData.msg.report_blocks[0].packets_lost);
- chartDataExtended.mos.push(tmpMos);
- chartDataExtended.averageMos += tmpMos;
- if(chartDataExtended.worstMos > tmpMos)
- chartDataExtended.worstMos = tmpMos;
-
-
- }
- var currentName = rtcpData.source_ip+ " -> " + rtcpData.destination_ip ;
- var isJitterForShow = true;
- var isPacketLostForShow = true;
- var isShowStream = true;
- $scope.rtcpMembers.forEach(function(member){
- if(member.name == currentName && !member.isShowJitter)
- {
- isJitterForShow = false;
- }
- if(member.name == currentName && !member.isShowPacketLost)
- {
- isPacketLostForShow = false;
- }
- if(member.name == currentName && !member.isShowStream)
- {
- isShowStream = false
- }
- });
-
- if(isShowStream){
- chartDataExtended.msg.push(rtcpData);
- if(chartDataExtended[currentName] == undefined){
- chartDataExtended.list.push(currentName);
- chartDataExtended[currentName] = {};
- chartDataExtended[currentName].jitter = [];
- chartDataExtended[currentName].packets_lost = [];
- chartDataExtended[currentName].source_ip = rtcpData.source_ip;
- chartDataExtended[currentName].destination_ip = rtcpData.destination_ip;
- chartDataExtended[currentName].totalPackets = 0;
- }
-
- var timestamp = rtcpData.micro_ts/1000 - $scope.TimeOffSetMs;
- if(chartDataExtended.from == 0){
- chartDataExtended.from = timestamp;
- }
- if(chartDataExtended.to < timestamp){
- chartDataExtended.to = timestamp;
- }
-
- if(isJitterForShow)
- {
- // Set jitter
- if( rtcpData.msg.report_blocks[0] !== undefined){
- chartDataExtended[currentName].jitter.push([timestamp , rtcpData.msg.report_blocks[0].ia_jitter]);
- if(chartDataExtended.maxJitterMsec < rtcpData.msg.report_blocks[0].ia_jitter){
- chartDataExtended.maxJitterMsec = rtcpData.msg.report_blocks[0].ia_jitter;
- }
- chartDataExtended.totalJitters += rtcpData.msg.report_blocks[0].ia_jitter;
- }
- }
- // Set packet lost
- if(isPacketLostForShow){
- if(rtcpData.msg.report_blocks[0] !== undefined){
- var packetLostTmp = [timestamp , rtcpData.msg.report_blocks[0].packets_lost];
- chartDataExtended[currentName].packets_lost.push(packetLostTmp);
- if(chartDataExtended.maxPacketLost < packetLostTmp[1]) {
- // Set maximum packet lost
- chartDataExtended.maxPacketLost = packetLostTmp[1];
- }
- chartDataExtended.totalPacketLost+=packetLostTmp[1];
- }
- }
-
- chartDataExtended.totalRtcpMessages++;
- // Set total packets
- if(rtcpData.msg.sender_information != undefined && chartDataExtended[currentName].totalPackets < rtcpData.msg.sender_information.packets){
- chartDataExtended[currentName].totalPackets = rtcpData.msg.sender_information.packets;
-
- }
- }
- }
- }
- }
- });
-
- chartDataExtended.averageMos = (chartDataExtended.averageMos / mosCounter).toFixed(2);
- chartDataExtended.worstMos = (chartDataExtended.worstMos).toFixed(2);
- // Total packets sum
- chartDataExtended.list.forEach(function(data) {
- chartDataExtended.totalPackets += chartDataExtended[data].totalPackets;
-
- });
- // Calculate averages
- if(chartDataExtended.totalPacketLost != 0 && chartDataExtended.totalRtcpMessages != 0){
- chartDataExtended.averagePacketLost = (chartDataExtended.totalPacketLost / chartDataExtended.totalRtcpMessages).toFixed(2);
- } else {
- chartDataExtended.averagePacketLost = 0;
- }
-
- if(chartDataExtended.totalJitters != 0 && chartDataExtended.totalRtcpMessages != 0){
- chartDataExtended.averageJitterMsec = (chartDataExtended.totalJitters / chartDataExtended.totalRtcpMessages).toFixed(2);
- } else {
- chartDataExtended.averageJitterMsec = 0;
- }
-
- $scope.calc_report = chartDataExtended;
- $scope.enableRTCPReport = true;
- $scope.filterRtcpData(true);
- //$scope.$apply();
- console.log("calc_report: ", $scope.calc_report);
- return chartDataExtended;
- }
-
- $scope.voicenterAnalyzeSipData = function(msg){
-
- console.log("voicenterAnalyzeSipData",msg);
-
- if (msg.calldata.length > 0) {
-
- // Calculate start & end & duration
- var startTime = msg.calldata[0].milli_ts;
- var endTime = msg.calldata[msg.calldata.length-1].milli_ts;
- var duration = parseInt((endTime - startTime) / 1000,10);
-
- $scope.beginRTCPDataDisplay = startTime;
- $scope.endRTCPDataDisplay = endTime;
-
-
- console.log("$scope.beginRTCPDataDisplay",$scope.beginRTCPDataDisplay);
- console.log("$scope.endRTCPDataDisplay",$scope.endRTCPDataDisplay);
-
- var hours = Math.floor(duration / 3600);
- duration %= 3600;
- var minutes = Math.floor(duration / 60);
- var seconds = duration % 60;
-
- if(hours < 10)
- hours = "0" + hours;
-
- if(minutes < 10)
- minutes = "0" + minutes;
-
- $scope.call_duration = "" + hours + ":" + minutes + ":" + seconds;
- // Calculate start & end & duration end
-
- // Get FROM / TO
- var leg1Callid = "";
- var leg2Callid = "";
- var leg1Invite = {};
- var leg2Invite = {};
- var leg1200 = {};
- var leg2200 = {};
-
- if(msg.calldata.length > 0){
- leg1Callid = msg.calldata[0].callid;
- }
-
-
- msg.calldata.forEach(function(sipPacket) {
-
- if(sipPacket.callid != leg1Callid && leg2Callid == ""){
- leg2Callid = sipPacket.callid;
- }
-
- if(jQuery.trim(sipPacket.method_text) == "INVITE (SDP)") {
- if(leg1Invite.callid == undefined && sipPacket.callid == leg1Callid){
- leg1Invite = sipPacket;
- } else {
- if(sipPacket.callid == leg2Callid){
- leg2Invite = sipPacket;
- }
- }
- }
- if(jQuery.trim(sipPacket.method_text) == "200 OK (SDP)"){
- if(leg1200.callid == undefined && sipPacket.callid == leg1Callid){
- leg1200 = sipPacket;
- } else {
- if(sipPacket.callid == leg2Callid){
- leg2200 = sipPacket;
- }
- }
- }
- });
-
-
-
- $scope.LEG1_DTMFMODE = "INFO / INBAND";
- $scope.LEG2_DTMFMODE = "INFO / INBAND";
-
-
- var leg1From = "";
- var leg1To = "";
- var leg1CodecsInvite = [];
- var leg2CodecsInvite = [];
- var leg1Codecs200 = [];
- var leg2Codecs200 = [];
- try {
- var tmp = leg1Invite.msg.split(/\r?\n/);
- // var tmp = leg1Invite.msg.split("\r\n");
- } catch(err) {
- console.log(err); var tmp = [];
- }
-
- tmp.forEach(function(sipHeader){
- if(sipHeader.substring(0,4).toUpperCase() == "FROM"){
- leg1From = sipHeader.substring(6).split(";")[0];
- }
- if(sipHeader.substring(0,2).toUpperCase() == "TO"){
- leg1To = sipHeader.substring(4).split(";")[0];
- }
- if(sipHeader.substring(0,8).toLowerCase() == "a=rtpmap"){
- var t = sipHeader.split(" ")[1].split("/");
- if(t[0] != "telephone-event"){
- leg1CodecsInvite.push(t[0]);
- //console.log(t[0]);
- } else {
- $scope.LEG1_DTMFMODE = "RFC2833";
- }
- }
- });
-
- var leg2From = "";
- var leg2To = "";
-
- if(leg2Invite.msg != undefined){
- tmp = leg2Invite.msg.split("\r\n");
- tmp.forEach(function(sipHeader){
- if(sipHeader.substring(0,4).toUpperCase() == "FROM"){
- leg2From = sipHeader.substring(6).split(";")[0];
- }
- if(sipHeader.substring(0,2).toUpperCase() == "TO"){
- leg2To = sipHeader.substring(4).split(";")[0];
- }
- if(sipHeader.substring(0,8).toLowerCase() == "a=rtpmap"){
- var t = sipHeader.split(" ")[1].split("/");
- if(t[0] != "telephone-event"){
- leg2CodecsInvite.push(t[0]);
- //console.log(t[0]);
- } else {
- $scope.LEG2_DTMFMODE = "RFC2833";
- }
- }
- });
- }
-
- if(leg1200.msg != undefined){
- tmp = leg1200.msg.split("\r\n");
- tmp.forEach(function(sipHeader){
- if(sipHeader.substring(0,8).toLowerCase() == "a=rtpmap"){
- var t = sipHeader.split(" ")[1].split("/");
- if(t[0] != "telephone-event"){
- leg1Codecs200.push(t[0]);
- //console.log("Leg1 code " + t[0]);
- }
- }
- });
- }
-
- if(leg2200.msg != undefined){
- tmp = leg2200.msg.split("\r\n");
- tmp.forEach(function(sipHeader){
- if(sipHeader.substring(0,8).toLowerCase() == "a=rtpmap"){
- var t = sipHeader.split(" ")[1].split("/");
- if(t[0] != "telephone-event"){
- leg2Codecs200.push(t[0]);
- //console.log("Leg2 code " + t[0]);
- }
- }
- });
- }
- $scope.FROM_LEG_1 = leg1From;
- $scope.TO_LEG_1 = leg1To;
- $scope.FROM_LEG_2 = leg2From;
- $scope.TO_LEG_2 = leg2To;
-
- // End get from / to
- // Set codecs:
- $scope.LEG11_CODEC1 = leg1CodecsInvite[0];
- $scope.LEG11_CODEC2 = leg1CodecsInvite[1];
- $scope.LEG11_CODEC3 = leg1CodecsInvite[2];
-
- $scope.LEG21_CODEC1 = leg1Codecs200[0];
- $scope.LEG21_CODEC2 = leg1Codecs200[1];
- $scope.LEG21_CODEC3 = leg1Codecs200[2];
-
- $scope.LEG12_CODEC1 = leg2CodecsInvite[0];
- $scope.LEG12_CODEC2 = leg2CodecsInvite[1];
- $scope.LEG12_CODEC3 = leg2CodecsInvite[2];
-
- $scope.LEG22_CODEC1 = leg2Codecs200[0];
- $scope.LEG22_CODEC2 = leg2Codecs200[1];
- $scope.LEG22_CODEC3 = leg2Codecs200[2];
-
- // Selected codecs:
- for(var ind = 0; ind < 3 ; ind++){
- if(leg1CodecsInvite[ind] == leg1Codecs200[ind]) {
- $scope.SELECTED_CODEC_LEG1 = leg1Codecs200[ind];
- break;
- }
- }
- for(var ind = 0; ind < 3 ; ind++){
- if(leg2CodecsInvite[ind] == leg2Codecs200[ind]) {
- $scope.SELECTED_CODEC_LEG2 = leg2Codecs200[ind];
- break;
- }
- }
-
- if (!$scope.SELECTED_CODEC_LEG1) $scope.SELECTED_CODEC_LEG1 = $scope.LEG21_CODEC1;
- if (!$scope.SELECTED_CODEC_LEG2) $scope.SELECTED_CODEC_LEG2 = $scope.LEG22_CODEC1;
- }
-
- };
-
- $scope.setRtcpMembers = function(){
- $scope.rtcpMembers = [];
- var tmp = {};
- $scope.rtcpreport.forEach(function(rtcpData) {
- var currentName = rtcpData.source_ip+ " -> " + rtcpData.destination_ip ;
- if(tmp[currentName] == undefined){
- $scope.rtcpMembers.push({
- name : currentName,
- isShowJitter: true,
- isShowPacketLost: true,
- isShowStream: true
- });
- tmp[currentName] = currentName;
- }
- });
- console.log("$scope.rtcpMembers: ", $scope.rtcpMembers);
- }
-
-
- // Chart
-
- $scope.resetData = function(){
- $scope.rtcpMembers.forEach(function(member){
- member.isShowJitter = true;
- member.isShowPacketLost = true;
- member.isShowStream = true;
- });
- $scope.beginRTCPDataDisplay = $scope.rtcpreport[0].micro_ts/1000 ;
- $scope.endRTCPDataDisplay = $scope.rtcpreport[$scope.rtcpreport.length-1].micro_ts/1000 ;
- $scope.calc_report = $scope.setDataBySelectedRange();
- $scope.setChartSeries();
- }
-
- $scope.showAllJitters = function(jittersFilterAll){
- if($scope.rtcpMembers == undefined){
- return;
- }
- if(jittersFilterAll == true)
- {
- $scope.rtcpMembers.forEach(function(member){
- member.isShowJitter = true;
- });
- } else {
- $scope.rtcpMembers.forEach(function(member){
- member.isShowJitter = false;
- });
- }
- $scope.calc_report = $scope.setDataBySelectedRange();
- $scope.setChartSeries();
- }
-
- $scope.showAllPacketsLost = function(packetsLostFilterAll){
- if($scope.rtcpMembers == undefined){
- return;
- }
- if(packetsLostFilterAll == true)
- {
- $scope.rtcpMembers.forEach(function(member){
- member.isShowPacketLost = true;
- });
- } else {
- $scope.rtcpMembers.forEach(function(member){
- member.isShowPacketLost = false;
- });
- }
- $scope.calc_report = $scope.setDataBySelectedRange();
- $scope.setChartSeries();
- }
-
- $scope.addRemoveJitterSerie = function(el){
-
- if($scope.rtcpMembers == undefined){
- return;
- }
- $scope.calc_report = $scope.setDataBySelectedRange();
- $scope.setChartSeries();
- }
-
- $scope.addRemovePacketLostSerie = function(el){
- if($scope.rtcpMembers == undefined){
- return;
- }
- $scope.calc_report = $scope.setDataBySelectedRange();
- $scope.setChartSeries();
- }
-
- $scope.addRemoveStreamSerie = function(el){
- if($scope.rtcpMembers == undefined){
- return;
- }
- if(el.isShowStream){
- el.isShowPacketLost = true;
- el.isShowJitter = true;
- } else {
- el.isShowPacketLost = false;
- el.isShowJitter = false;
- }
- $scope.calc_report = $scope.setDataBySelectedRange();
- $scope.setChartSeries();
- }
-
- // Chart end
-
- // Voicenter implimentations end
-
- // $scope.showRTCPReport(data); // Move to search.searchTransactionById
+
$scope.showLogReport(data);
$scope.showQualityReport(data);
- console.log("Reporting...", data);
+ $scope.showQOSReport(data);
$timeout(function() {
if($homerModal.getOpenedModals().indexOf('tempModal') !== -1) {
@@ -1006,8 +545,6 @@
'$sce',
function($scope, $homerModal, $homerModalParams, $timeout, $sce) {
- console.log($homerModalParams);
-
var sdata = $homerModalParams.params;
@@ -1019,8 +556,6 @@
console.log("details");
};
- console.log($homerModalParams);
-
var swapText = function(text){
var swpA, swpB;
text = text.split('<').join('<');
@@ -1055,7 +590,6 @@
for (var p in sdata) {
if(p == "msg") continue;
if (sdata.hasOwnProperty(p) && sdata[p] != '' && typeof sdata[p] == 'string') {
- console.log(sdata[p]);
tabjson.push(''+p +''+ ': ' + sdata[p].split('<').join('<')+'
');
}
tabjson.push();
@@ -1075,9 +609,6 @@
restrict: 'EA',
link: function(scope, element) {
- console.log('DRAGG');
- console.log(scope);
-
$(element)
.draggable({
cancel: ".homer-modal-body, .close",
@@ -1086,14 +617,12 @@
.resizable({
resize: function (evt, ui) {
var canv = $(element).find('#cflowcanv');
- console.log($(element).height());
if($(canv).length > 0)
{
scope.reDrawCanvas();
}
var messagebody = $(element).find('.homer-modal-body');
- console.log(messagebody);
$(messagebody).width(ui.size.width - 10);
$(messagebody).height(ui.size.height - 50);
}
diff --git a/share/index.html b/share/index.html
index cb367d67..4574d7c7 100644
--- a/share/index.html
+++ b/share/index.html
@@ -28,6 +28,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/share/search.js b/share/search.js
index e10c972e..35a638c9 100644
--- a/share/search.js
+++ b/share/search.js
@@ -112,6 +112,29 @@
return defer.promise;
};
+
+ var searchQOSReportById = function (data) {
+
+ var defer = $q.defer();
+
+ $http.post('/api/v1/report/share/qos', data).then(
+ /* good response */
+ function (results) {
+ if(results.data.auth == "false") {
+ defer.reject('user not authorized');
+ }
+ else {
+ defer.resolve(results.data.data);
+ }
+ },
+ /* bad response */
+ function (results) {
+ defer.reject('bad response combination');
+ }
+ );
+
+ return defer.promise;
+ };
var searchLogReportById = function (data) {
@@ -166,7 +189,8 @@
makePcapTextforTransactionById: makePcapTextforTransactionById,
searchQualityReportById: searchQualityReportById,
searchLogReportById: searchLogReportById,
- searchRTCPReportById: searchRTCPReportById
+ searchRTCPReportById: searchRTCPReportById,
+ searchQOSReportById: searchQOSReportById
};
}
diff --git a/templates/dialogs/transaction.html b/templates/dialogs/transaction.html
index 38710059..538ac038 100644
--- a/templates/dialogs/transaction.html
+++ b/templates/dialogs/transaction.html
@@ -39,6 +39,7 @@