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 = "
"+tabjson.join('')+"
"; - $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 = "
" + tabjson.join('') + "
"; + $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 @@