Sfc-ui patch set based on feedback (I, II, III) 50/13250/6
authorAndrej Kincel <[email protected]>
Mon, 24 Nov 2014 09:27:10 +0000 (10:27 +0100)
committerAndrej Kincel <[email protected]>
Tue, 2 Dec 2014 09:46:45 +0000 (09:46 +0000)
+ Added webconsole as boot feature for sfc-karaf

+ SFF set as default view on UI access
+ SN topology showing data from SFF as default
+ Table view for service-function-type
+ RESTconf URL kept in storage of web browser persistently
+ System info tab: karaf features + karaf logs
+ Top menu responsive - in future should be even more improved
+ Fixed UI layout for low-res screens

Change-Id: If10de42271e47ef888c417afb433dcd602065a60
Signed-off-by: Andrej Kincel <[email protected]>
29 files changed:
sfc-karaf/pom.xml
sfc-ui/src/main/resources/pages/assets/data/locale-en_US.json [changed mode: 0644->0755]
sfc-ui/src/main/resources/pages/assets/opendaylight-dlux-0.1.0.css
sfc-ui/src/main/resources/pages/src/app/sfc/acl/acl.services.js
sfc-ui/src/main/resources/pages/src/app/sfc/acl/acl.tpl.html
sfc-ui/src/main/resources/pages/src/app/sfc/config/config.controller.js
sfc-ui/src/main/resources/pages/src/app/sfc/config/config.tpl.html
sfc-ui/src/main/resources/pages/src/app/sfc/metadata/metadata.tpl.html
sfc-ui/src/main/resources/pages/src/app/sfc/root.tpl.html
sfc-ui/src/main/resources/pages/src/app/sfc/servicechain/servicechain.tpl.html
sfc-ui/src/main/resources/pages/src/app/sfc/serviceforwarder/serviceforwarder.tpl.html
sfc-ui/src/main/resources/pages/src/app/sfc/servicefunction/servicefunction.controller.js
sfc-ui/src/main/resources/pages/src/app/sfc/servicefunction/servicefunction.tpl.html
sfc-ui/src/main/resources/pages/src/app/sfc/servicenode/servicenode.controller.js
sfc-ui/src/main/resources/pages/src/app/sfc/servicenode/servicenode.tpl.html
sfc-ui/src/main/resources/pages/src/app/sfc/servicepath/servicepath.tpl.html
sfc-ui/src/main/resources/pages/src/app/sfc/sfc.controller.js
sfc-ui/src/main/resources/pages/src/app/sfc/sfc.less
sfc-ui/src/main/resources/pages/src/app/sfc/sfc.module.js
sfc-ui/src/main/resources/pages/src/app/sfc/sfc.services.js
sfc-ui/src/main/resources/pages/src/app/sfc/system/system.controller.js [new file with mode: 0644]
sfc-ui/src/main/resources/pages/src/app/sfc/system/system.modal.exception.tpl.html [new file with mode: 0644]
sfc-ui/src/main/resources/pages/src/app/sfc/system/system.services.js [new file with mode: 0644]
sfc-ui/src/main/resources/pages/src/app/sfc/system/system.tpl.html [new file with mode: 0644]
sfc-ui/src/main/resources/pages/src/main.js
sfc-ui/src/main/resources/pages/vendor/angular-bootstrap/ui-bootstrap-tpls.min.js
sfc-ui/src/main/resources/pages/vendor/angular-cookies/angular-cookies.min.js.map [new file with mode: 0644]
sfc-ui/src/main/resources/pages/vendor/angular-dragdrop/draganddrop.js
sfc-ui/src/main/resources/pages/vendor/ngStorage/ngStorage.min.js [new file with mode: 0644]

index bc6702356a5ee59ce5e88ae4e72d8a646b12ff43..7c193c84fb1631028fb0d02a0cd8067fc43507c7 100644 (file)
         <configuration>
           <bootFeatures>
             <feature>standard</feature>
-            <feature>odl-restconf</feature> 
+            <feature>webconsole</feature>
+            <feature>odl-restconf</feature>
             <feature>odl-sfc-all</feature>
             <feature>odl-mdsal-apidocs</feature>
             <!-- 
old mode 100644 (file)
new mode 100755 (executable)
index 4b333f5..e8b003a
   "SFC_SERVICE_NODES": "Service Nodes",\r
   "SFC_SERVICE_FORWARDERS": "Service Function Forwarders",\r
   "SFC_SERVICE_FUNCTIONS": "Service Functions",\r
+  "SFC_SERVICE_FUNCTIONS_TYPES": "Service Function Types",\r
   "SFC_SERVICE_CHAINS": "Service Function Chains",\r
   "SFC_SERVICE_PATHS": "Service Function Paths",\r
   "SFC_CONFIG": "Config",\r
+  "SFC_SYSTEM": "System info",\r
   "SFC_ACCESS_LISTS": "Access Lists/Classifiers",\r
   "SFC_METADATA": "NSH Metadata",\r
   "SFC_RESTCONF_URL": "Restconf URL",\r
   "SFC_METADATA_CREATE_VARIABLE_TLV_DATA": "Type in a string",\r
   "SFC_METADATA_VARIABLE_TLV_LENGTH": "Length of the variable metadata",\r
   "SFC_METADATA_CREATE_VARIABLE_TLV_LENGTH": "Number in range 0-32",\r
+  "SFC_SYSTEM_KARAF_FEATURES": "SFC Karaf Features",\r
+  "SFC_SYSTEM_KARAF_LOGS": "Karaf logs",\r
+  "SFC_SYSTEM_FEATURE_ID": "Karaf Feature ID",\r
+  "SFC_SYSTEM_FEATURE_REPOSITORY_URL": "Repository URL",\r
+  "SFC_SYSTEM_FEATURE_STATUS": "Status",\r
+  "SFC_SYSTEM_FEATURE_UNINSTALL": "Uninstall feature",\r
+  "SFC_SYSTEM_FEATURE_INSTALL": "Install feature",\r
+  "SFC_SYSTEM_REPOSITORY_REFRESH": "Refresh repository",\r
+  "SFC_SYSTEM_LOG_RECEIVED": "Received",\r
+  "SFC_SYSTEM_LOG_LEVEL": "Level",\r
+  "SFC_SYSTEM_LOG_MESSAGE": "Message",\r
+  "SFC_SYSTEM_LOG_BUNDLE": "Bundle",\r
+  "SFC_SYSTEM_LOG_EXCEPTION": "Exception",\r
+  "SFC_SYSTEM_LOG_SHOW_EXCEPTION": "Show exception",\r
+  "SFC_SYSTEM_MODAL_EXCEPTION_HEAD": "Bundle exception",\r
+  "SFC_SYSTEM_MODAL_EXCEPTION_CLOSE": "Close",\r
 \r
   "JSON_LAST_PROPERTY": "Stabile last property of this JSON, for nice merging"\r
 }\r
index d7c611d8de628ee8ba0076a7ea07febad8a86d12..aa9463edda6dba36aaf5d8755c376ef4abc879b9 100644 (file)
@@ -7,7 +7,15 @@
  * First, we include the Twitter Bootstrap LESS files. Only the ones used in the
  * project should be imported as the rest are just wasting space.
  */
-/*! normalize.css v2.1.3 | MIT License | git.io/normalize */
+/*! normalize.css v3.0.0 | MIT License | git.io/normalize */
+html {
+  font-family: sans-serif;
+  -ms-text-size-adjust: 100%;
+  -webkit-text-size-adjust: 100%;
+}
+body {
+  margin: 0;
+}
 article,
 aside,
 details,
@@ -24,8 +32,10 @@ summary {
 }
 audio,
 canvas,
+progress,
 video {
   display: inline-block;
+  vertical-align: baseline;
 }
 audio:not([controls]) {
   display: none;
@@ -35,28 +45,13 @@ audio:not([controls]) {
 template {
   display: none;
 }
-html {
-  font-family: sans-serif;
-  -ms-text-size-adjust: 100%;
-  -webkit-text-size-adjust: 100%;
-}
-body {
-  margin: 0;
-}
 a {
   background: transparent;
 }
-a:focus {
-  outline: thin dotted;
-}
 a:active,
 a:hover {
   outline: 0;
 }
-h1 {
-  font-size: 2em;
-  margin: 0.67em 0;
-}
 abbr[title] {
   border-bottom: 1px dotted;
 }
@@ -67,28 +62,14 @@ strong {
 dfn {
   font-style: italic;
 }
-hr {
-  -moz-box-sizing: content-box;
-  box-sizing: content-box;
-  height: 0;
+h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
 }
 mark {
   background: #ff0;
   color: #000;
 }
-code,
-kbd,
-pre,
-samp {
-  font-family: monospace, serif;
-  font-size: 1em;
-}
-pre {
-  white-space: pre-wrap;
-}
-q {
-  quotes: "\201C" "\201D" "\2018" "\2019";
-}
 small {
   font-size: 80%;
 }
@@ -112,28 +93,34 @@ svg:not(:root) {
   overflow: hidden;
 }
 figure {
-  margin: 0;
+  margin: 1em 40px;
 }
-fieldset {
-  border: 1px solid #c0c0c0;
-  margin: 0 2px;
-  padding: 0.35em 0.625em 0.75em;
+hr {
+  -moz-box-sizing: content-box;
+  box-sizing: content-box;
+  height: 0;
 }
-legend {
-  border: 0;
-  padding: 0;
+pre {
+  overflow: auto;
+}
+code,
+kbd,
+pre,
+samp {
+  font-family: monospace, monospace;
+  font-size: 1em;
 }
 button,
 input,
+optgroup,
 select,
 textarea {
-  font-family: inherit;
-  font-size: 100%;
+  color: inherit;
+  font: inherit;
   margin: 0;
 }
-button,
-input {
-  line-height: normal;
+button {
+  overflow: visible;
 }
 button,
 select {
@@ -150,11 +137,23 @@ button[disabled],
 html input[disabled] {
   cursor: default;
 }
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+  border: 0;
+  padding: 0;
+}
+input {
+  line-height: normal;
+}
 input[type="checkbox"],
 input[type="radio"] {
   box-sizing: border-box;
   padding: 0;
 }
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
 input[type="search"] {
   -webkit-appearance: textfield;
   -moz-box-sizing: content-box;
@@ -165,19 +164,29 @@ input[type="search"]::-webkit-search-cancel-button,
 input[type="search"]::-webkit-search-decoration {
   -webkit-appearance: none;
 }
-button::-moz-focus-inner,
-input::-moz-focus-inner {
+fieldset {
+  border: 1px solid #c0c0c0;
+  margin: 0 2px;
+  padding: 0.35em 0.625em 0.75em;
+}
+legend {
   border: 0;
   padding: 0;
 }
 textarea {
   overflow: auto;
-  vertical-align: top;
+}
+optgroup {
+  font-weight: bold;
 }
 table {
   border-collapse: collapse;
   border-spacing: 0;
 }
+td,
+th {
+  padding: 0;
+}
 @media print {
   * {
     text-shadow: none !important;
@@ -214,9 +223,6 @@ table {
   img {
     max-width: 100% !important;
   }
-  @page {
-    margin: 2cm .5cm;
-  }
   p,
   h2,
   h3 {
@@ -252,7 +258,11 @@ table {
     border: 1px solid #ddd !important;
   }
 }
-*,
+* {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
 *:before,
 *:after {
   -webkit-box-sizing: border-box;
@@ -292,10 +302,17 @@ a:focus {
   outline: 5px auto -webkit-focus-ring-color;
   outline-offset: -2px;
 }
+figure {
+  margin: 0;
+}
 img {
   vertical-align: middle;
 }
-.img-responsive {
+.img-responsive,
+.thumbnail > img,
+.thumbnail a > img,
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
   display: block;
   max-width: 100%;
   height: auto;
@@ -346,7 +363,7 @@ h6,
 .h4,
 .h5,
 .h6 {
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-family: inherit;
   font-weight: 500;
   line-height: 1.1;
   color: inherit;
@@ -380,31 +397,49 @@ h6 .small,
   color: #999999;
 }
 h1,
+.h1,
 h2,
-h3 {
+.h2,
+h3,
+.h3 {
   margin-top: 20px;
   margin-bottom: 10px;
 }
 h1 small,
+.h1 small,
 h2 small,
+.h2 small,
 h3 small,
+.h3 small,
 h1 .small,
+.h1 .small,
 h2 .small,
-h3 .small {
+.h2 .small,
+h3 .small,
+.h3 .small {
   font-size: 65%;
 }
 h4,
+.h4,
 h5,
-h6 {
+.h5,
+h6,
+.h6 {
   margin-top: 10px;
   margin-bottom: 10px;
 }
 h4 small,
+.h4 small,
 h5 small,
+.h5 small,
 h6 small,
+.h6 small,
 h4 .small,
+.h4 .small,
 h5 .small,
-h6 .small {
+.h5 .small,
+h6 .small,
+.h6 .small {
   font-size: 75%;
 }
 h1,
@@ -452,47 +487,81 @@ small,
 cite {
   font-style: normal;
 }
+.text-left {
+  text-align: left;
+}
+.text-right {
+  text-align: right;
+}
+.text-center {
+  text-align: center;
+}
+.text-justify {
+  text-align: justify;
+}
 .text-muted {
   color: #999999;
 }
 .text-primary {
   color: #428bca;
 }
-.text-primary:hover {
+a.text-primary:hover {
   color: #3071a9;
 }
+.text-success {
+  color: #3c763d;
+}
+a.text-success:hover {
+  color: #2b542c;
+}
+.text-info {
+  color: #31708f;
+}
+a.text-info:hover {
+  color: #245269;
+}
 .text-warning {
   color: #8a6d3b;
 }
-.text-warning:hover {
+a.text-warning:hover {
   color: #66512c;
 }
 .text-danger {
   color: #a94442;
 }
-.text-danger:hover {
+a.text-danger:hover {
   color: #843534;
 }
-.text-success {
-  color: #3c763d;
+.bg-primary {
+  color: #fff;
+  background-color: #428bca;
 }
-.text-success:hover {
-  color: #2b542c;
+a.bg-primary:hover {
+  background-color: #3071a9;
 }
-.text-info {
-  color: #31708f;
+.bg-success {
+  background-color: #dff0d8;
 }
-.text-info:hover {
-  color: #245269;
+a.bg-success:hover {
+  background-color: #c1e2b3;
 }
-.text-left {
-  text-align: left;
+.bg-info {
+  background-color: #d9edf7;
 }
-.text-right {
-  text-align: right;
+a.bg-info:hover {
+  background-color: #afd9ee;
 }
-.text-center {
-  text-align: center;
+.bg-warning {
+  background-color: #fcf8e3;
+}
+a.bg-warning:hover {
+  background-color: #f7ecb5;
+}
+.bg-danger {
+  background-color: #f2dede;
+}
+a.bg-danger:hover {
+  background-color: #e4b9b9;
 }
 .page-header {
   padding-bottom: 9px;
@@ -517,15 +586,13 @@ ol ol {
 .list-inline {
   padding-left: 0;
   list-style: none;
+  margin-left: -5px;
 }
 .list-inline > li {
   display: inline-block;
   padding-left: 5px;
   padding-right: 5px;
 }
-.list-inline > li:first-child {
-  padding-left: 0;
-}
 dl {
   margin-top: 0;
   margin-bottom: 20px;
@@ -553,22 +620,6 @@ dd {
   .dl-horizontal dd {
     margin-left: 180px;
   }
-  .dl-horizontal dd:before,
-  .dl-horizontal dd:after {
-    content: " ";
-    display: table;
-  }
-  .dl-horizontal dd:after {
-    clear: both;
-  }
-  .dl-horizontal dd:before,
-  .dl-horizontal dd:after {
-    content: " ";
-    display: table;
-  }
-  .dl-horizontal dd:after {
-    clear: both;
-  }
 }
 abbr[title],
 abbr[data-original-title] {
@@ -582,42 +633,48 @@ abbr[data-original-title] {
 blockquote {
   padding: 10px 20px;
   margin: 0 0 20px;
-  border-left: 5px solid #eeeeee;
-}
-blockquote p {
   font-size: 17.5px;
-  font-weight: 300;
-  line-height: 1.25;
+  border-left: 5px solid #eeeeee;
 }
-blockquote p:last-child {
+blockquote p:last-child,
+blockquote ul:last-child,
+blockquote ol:last-child {
   margin-bottom: 0;
 }
+blockquote footer,
 blockquote small,
 blockquote .small {
   display: block;
+  font-size: 80%;
   line-height: 1.428571429;
   color: #999999;
 }
+blockquote footer:before,
 blockquote small:before,
 blockquote .small:before {
   content: '\2014 \00A0';
 }
+.blockquote-reverse,
 blockquote.pull-right {
   padding-right: 15px;
   padding-left: 0;
   border-right: 5px solid #eeeeee;
   border-left: 0;
-}
-blockquote.pull-right p,
-blockquote.pull-right small,
-blockquote.pull-right .small {
   text-align: right;
 }
+.blockquote-reverse footer:before,
+blockquote.pull-right footer:before,
+.blockquote-reverse small:before,
 blockquote.pull-right small:before,
+.blockquote-reverse .small:before,
 blockquote.pull-right .small:before {
   content: '';
 }
+.blockquote-reverse footer:after,
+blockquote.pull-right footer:after,
+.blockquote-reverse small:after,
 blockquote.pull-right small:after,
+.blockquote-reverse .small:after,
 blockquote.pull-right .small:after {
   content: '\00A0 \2014';
 }
@@ -644,6 +701,14 @@ code {
   white-space: nowrap;
   border-radius: 4px;
 }
+kbd {
+  padding: 2px 4px;
+  font-size: 90%;
+  color: #ffffff;
+  background-color: #333333;
+  border-radius: 3px;
+  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
 pre {
   display: block;
   padding: 9.5px;
@@ -675,28 +740,12 @@ pre code {
   padding-left: 15px;
   padding-right: 15px;
 }
-.container:before,
-.container:after {
-  content: " ";
-  display: table;
-}
-.container:after {
-  clear: both;
-}
-.container:before,
-.container:after {
-  content: " ";
-  display: table;
-}
-.container:after {
-  clear: both;
-}
-@media (min-width: 768px) {
+@media (min-width: 769px) {
   .container {
     width: 750px;
   }
 }
-@media (min-width: 992px) {
+@media (min-width: 993px) {
   .container {
     width: 970px;
   }
@@ -706,26 +755,16 @@ pre code {
     width: 1170px;
   }
 }
+.container-fluid {
+  margin-right: auto;
+  margin-left: auto;
+  padding-left: 15px;
+  padding-right: 15px;
+}
 .row {
   margin-left: -15px;
   margin-right: -15px;
 }
-.row:before,
-.row:after {
-  content: " ";
-  display: table;
-}
-.row:after {
-  clear: both;
-}
-.row:before,
-.row:after {
-  content: " ";
-  display: table;
-}
-.row:after {
-  clear: both;
-}
 .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
   position: relative;
   min-height: 1px;
@@ -1440,73 +1479,110 @@ table col[class*="col-"] {
 }
 table td[class*="col-"],
 table th[class*="col-"] {
+  position: static;
   float: none;
   display: table-cell;
 }
-.table > thead > tr > .active,
-.table > tbody > tr > .active,
-.table > tfoot > tr > .active,
-.table > thead > .active > td,
-.table > tbody > .active > td,
-.table > tfoot > .active > td,
-.table > thead > .active > th,
-.table > tbody > .active > th,
-.table > tfoot > .active > th {
+.table > thead > tr > td.active,
+.table > tbody > tr > td.active,
+.table > tfoot > tr > td.active,
+.table > thead > tr > th.active,
+.table > tbody > tr > th.active,
+.table > tfoot > tr > th.active,
+.table > thead > tr.active > td,
+.table > tbody > tr.active > td,
+.table > tfoot > tr.active > td,
+.table > thead > tr.active > th,
+.table > tbody > tr.active > th,
+.table > tfoot > tr.active > th {
   background-color: #f5f5f5;
 }
-.table-hover > tbody > tr > .active:hover,
-.table-hover > tbody > .active:hover > td,
-.table-hover > tbody > .active:hover > th {
+.table-hover > tbody > tr > td.active:hover,
+.table-hover > tbody > tr > th.active:hover,
+.table-hover > tbody > tr.active:hover > td,
+.table-hover > tbody > tr.active:hover > th {
   background-color: #e8e8e8;
 }
-.table > thead > tr > .success,
-.table > tbody > tr > .success,
-.table > tfoot > tr > .success,
-.table > thead > .success > td,
-.table > tbody > .success > td,
-.table > tfoot > .success > td,
-.table > thead > .success > th,
-.table > tbody > .success > th,
-.table > tfoot > .success > th {
+.table > thead > tr > td.success,
+.table > tbody > tr > td.success,
+.table > tfoot > tr > td.success,
+.table > thead > tr > th.success,
+.table > tbody > tr > th.success,
+.table > tfoot > tr > th.success,
+.table > thead > tr.success > td,
+.table > tbody > tr.success > td,
+.table > tfoot > tr.success > td,
+.table > thead > tr.success > th,
+.table > tbody > tr.success > th,
+.table > tfoot > tr.success > th {
   background-color: #dff0d8;
 }
-.table-hover > tbody > tr > .success:hover,
-.table-hover > tbody > .success:hover > td,
-.table-hover > tbody > .success:hover > th {
+.table-hover > tbody > tr > td.success:hover,
+.table-hover > tbody > tr > th.success:hover,
+.table-hover > tbody > tr.success:hover > td,
+.table-hover > tbody > tr.success:hover > th {
   background-color: #d0e9c6;
 }
-.table > thead > tr > .danger,
-.table > tbody > tr > .danger,
-.table > tfoot > tr > .danger,
-.table > thead > .danger > td,
-.table > tbody > .danger > td,
-.table > tfoot > .danger > td,
-.table > thead > .danger > th,
-.table > tbody > .danger > th,
-.table > tfoot > .danger > th {
-  background-color: #f2dede;
-}
-.table-hover > tbody > tr > .danger:hover,
-.table-hover > tbody > .danger:hover > td,
-.table-hover > tbody > .danger:hover > th {
-  background-color: #ebcccc;
+.table > thead > tr > td.info,
+.table > tbody > tr > td.info,
+.table > tfoot > tr > td.info,
+.table > thead > tr > th.info,
+.table > tbody > tr > th.info,
+.table > tfoot > tr > th.info,
+.table > thead > tr.info > td,
+.table > tbody > tr.info > td,
+.table > tfoot > tr.info > td,
+.table > thead > tr.info > th,
+.table > tbody > tr.info > th,
+.table > tfoot > tr.info > th {
+  background-color: #d9edf7;
 }
-.table > thead > tr > .warning,
-.table > tbody > tr > .warning,
-.table > tfoot > tr > .warning,
-.table > thead > .warning > td,
-.table > tbody > .warning > td,
-.table > tfoot > .warning > td,
-.table > thead > .warning > th,
-.table > tbody > .warning > th,
-.table > tfoot > .warning > th {
+.table-hover > tbody > tr > td.info:hover,
+.table-hover > tbody > tr > th.info:hover,
+.table-hover > tbody > tr.info:hover > td,
+.table-hover > tbody > tr.info:hover > th {
+  background-color: #c4e3f3;
+}
+.table > thead > tr > td.warning,
+.table > tbody > tr > td.warning,
+.table > tfoot > tr > td.warning,
+.table > thead > tr > th.warning,
+.table > tbody > tr > th.warning,
+.table > tfoot > tr > th.warning,
+.table > thead > tr.warning > td,
+.table > tbody > tr.warning > td,
+.table > tfoot > tr.warning > td,
+.table > thead > tr.warning > th,
+.table > tbody > tr.warning > th,
+.table > tfoot > tr.warning > th {
   background-color: #fcf8e3;
 }
-.table-hover > tbody > tr > .warning:hover,
-.table-hover > tbody > .warning:hover > td,
-.table-hover > tbody > .warning:hover > th {
+.table-hover > tbody > tr > td.warning:hover,
+.table-hover > tbody > tr > th.warning:hover,
+.table-hover > tbody > tr.warning:hover > td,
+.table-hover > tbody > tr.warning:hover > th {
   background-color: #faf2cc;
 }
+.table > thead > tr > td.danger,
+.table > tbody > tr > td.danger,
+.table > tfoot > tr > td.danger,
+.table > thead > tr > th.danger,
+.table > tbody > tr > th.danger,
+.table > tfoot > tr > th.danger,
+.table > thead > tr.danger > td,
+.table > tbody > tr.danger > td,
+.table > tfoot > tr.danger > td,
+.table > thead > tr.danger > th,
+.table > tbody > tr.danger > th,
+.table > tfoot > tr.danger > th {
+  background-color: #f2dede;
+}
+.table-hover > tbody > tr > td.danger:hover,
+.table-hover > tbody > tr > th.danger:hover,
+.table-hover > tbody > tr.danger:hover > td,
+.table-hover > tbody > tr.danger:hover > th {
+  background-color: #ebcccc;
+}
 @media (max-width: 768px) {
   .table-responsive {
     width: 100%;
@@ -1558,6 +1634,7 @@ fieldset {
   padding: 0;
   margin: 0;
   border: 0;
+  min-width: 0;
 }
 legend {
   display: block;
@@ -1590,15 +1667,14 @@ input[type="checkbox"] {
 input[type="file"] {
   display: block;
 }
+input[type="range"] {
+  display: block;
+  width: 100%;
+}
 select[multiple],
 select[size] {
   height: auto;
 }
-select optgroup {
-  font-size: inherit;
-  font-style: inherit;
-  font-family: inherit;
-}
 input[type="file"]:focus,
 input[type="radio"]:focus,
 input[type="checkbox"]:focus {
@@ -1606,17 +1682,12 @@ input[type="checkbox"]:focus {
   outline: 5px auto -webkit-focus-ring-color;
   outline-offset: -2px;
 }
-input[type="number"]::-webkit-outer-spin-button,
-input[type="number"]::-webkit-inner-spin-button {
-  height: auto;
-}
 output {
   display: block;
   padding-top: 7px;
   font-size: 14px;
   line-height: 1.428571429;
   color: #858585;
-  vertical-align: middle;
 }
 .form-control {
   display: block;
@@ -1626,7 +1697,6 @@ output {
   font-size: 14px;
   line-height: 1.428571429;
   color: #858585;
-  vertical-align: middle;
   background-color: #ffffff;
   background-image: none;
   border: 1px solid #d5d5d5;
@@ -1642,9 +1712,6 @@ output {
   -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
   box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
 }
-.form-control:-moz-placeholder {
-  color: #999999;
-}
 .form-control::-moz-placeholder {
   color: #999999;
   opacity: 1;
@@ -1660,10 +1727,17 @@ output {
 fieldset[disabled] .form-control {
   cursor: not-allowed;
   background-color: #eeeeee;
+  opacity: 1;
 }
 textarea.form-control {
   height: auto;
 }
+input[type="search"] {
+  -webkit-appearance: none;
+}
+input[type="date"] {
+  line-height: 34px;
+}
 .form-group {
   margin-bottom: 15px;
 }
@@ -1674,12 +1748,10 @@ textarea.form-control {
   margin-top: 10px;
   margin-bottom: 10px;
   padding-left: 20px;
-  vertical-align: middle;
 }
 .radio label,
 .checkbox label {
   display: inline;
-  margin-bottom: 0;
   font-weight: normal;
   cursor: pointer;
 }
@@ -1733,7 +1805,8 @@ select.input-sm {
   height: 30px;
   line-height: 30px;
 }
-textarea.input-sm {
+textarea.input-sm,
+select[multiple].input-sm {
   height: auto;
 }
 .input-lg {
@@ -1747,20 +1820,63 @@ select.input-lg {
   height: 46px;
   line-height: 46px;
 }
-textarea.input-lg {
+textarea.input-lg,
+select[multiple].input-lg {
   height: auto;
 }
-.has-warning .help-block,
-.has-warning .control-label,
-.has-warning .radio,
-.has-warning .checkbox,
-.has-warning .radio-inline,
-.has-warning .checkbox-inline {
-  color: #8a6d3b;
+.has-feedback {
+  position: relative;
 }
-.has-warning .form-control {
-  border-color: #8a6d3b;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+.has-feedback .form-control {
+  padding-right: 42.5px;
+}
+.has-feedback .form-control-feedback {
+  position: absolute;
+  top: 25px;
+  right: 0;
+  display: block;
+  width: 34px;
+  height: 34px;
+  line-height: 34px;
+  text-align: center;
+}
+.has-success .help-block,
+.has-success .control-label,
+.has-success .radio,
+.has-success .checkbox,
+.has-success .radio-inline,
+.has-success .checkbox-inline {
+  color: #3c763d;
+}
+.has-success .form-control {
+  border-color: #3c763d;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+.has-success .form-control:focus {
+  border-color: #2b542c;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
+}
+.has-success .input-group-addon {
+  color: #3c763d;
+  border-color: #3c763d;
+  background-color: #dff0d8;
+}
+.has-success .form-control-feedback {
+  color: #3c763d;
+}
+.has-warning .help-block,
+.has-warning .control-label,
+.has-warning .radio,
+.has-warning .checkbox,
+.has-warning .radio-inline,
+.has-warning .checkbox-inline {
+  color: #8a6d3b;
+}
+.has-warning .form-control {
+  border-color: #8a6d3b;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
   box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
 }
 .has-warning .form-control:focus {
@@ -1773,6 +1889,9 @@ textarea.input-lg {
   border-color: #8a6d3b;
   background-color: #fcf8e3;
 }
+.has-warning .form-control-feedback {
+  color: #8a6d3b;
+}
 .has-error .help-block,
 .has-error .control-label,
 .has-error .radio,
@@ -1796,28 +1915,8 @@ textarea.input-lg {
   border-color: #a94442;
   background-color: #f2dede;
 }
-.has-success .help-block,
-.has-success .control-label,
-.has-success .radio,
-.has-success .checkbox,
-.has-success .radio-inline,
-.has-success .checkbox-inline {
-  color: #3c763d;
-}
-.has-success .form-control {
-  border-color: #3c763d;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-}
-.has-success .form-control:focus {
-  border-color: #2b542c;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
-  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
-}
-.has-success .input-group-addon {
-  color: #3c763d;
-  border-color: #3c763d;
-  background-color: #dff0d8;
+.has-error .form-control-feedback {
+  color: #a94442;
 }
 .form-control-static {
   margin-bottom: 0;
@@ -1828,7 +1927,7 @@ textarea.input-lg {
   margin-bottom: 10px;
   color: #797979;
 }
-@media (min-width: 768px) {
+@media (min-width: 769px) {
   .form-inline .form-group {
     display: inline-block;
     margin-bottom: 0;
@@ -1836,9 +1935,15 @@ textarea.input-lg {
   }
   .form-inline .form-control {
     display: inline-block;
-  }
-  .form-inline select.form-control {
     width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .input-group > .form-control {
+    width: 100%;
+  }
+  .form-inline .control-label {
+    margin-bottom: 0;
+    vertical-align: middle;
   }
   .form-inline .radio,
   .form-inline .checkbox {
@@ -1846,12 +1951,16 @@ textarea.input-lg {
     margin-top: 0;
     margin-bottom: 0;
     padding-left: 0;
+    vertical-align: middle;
   }
   .form-inline .radio input[type="radio"],
   .form-inline .checkbox input[type="checkbox"] {
     float: none;
     margin-left: 0;
   }
+  .form-inline .has-feedback .form-control-feedback {
+    top: 0;
+  }
 }
 .form-horizontal .control-label,
 .form-horizontal .radio,
@@ -1870,22 +1979,6 @@ textarea.input-lg {
   margin-left: -15px;
   margin-right: -15px;
 }
-.form-horizontal .form-group:before,
-.form-horizontal .form-group:after {
-  content: " ";
-  display: table;
-}
-.form-horizontal .form-group:after {
-  clear: both;
-}
-.form-horizontal .form-group:before,
-.form-horizontal .form-group:after {
-  content: " ";
-  display: table;
-}
-.form-horizontal .form-group:after {
-  clear: both;
-}
 .form-horizontal .form-control-static {
   padding-top: 7px;
 }
@@ -1894,6 +1987,10 @@ textarea.input-lg {
     text-align: right;
   }
 }
+.form-horizontal .has-feedback .form-control-feedback {
+  top: 0;
+  right: 15px;
+}
 .btn {
   display: inline-block;
   margin-bottom: 0;
@@ -1911,10 +2008,11 @@ textarea.input-lg {
   -webkit-user-select: none;
   -moz-user-select: none;
   -ms-user-select: none;
-  -o-user-select: none;
   user-select: none;
 }
-.btn:focus {
+.btn:focus,
+.btn:active:focus,
+.btn.active:focus {
   outline: thin dotted;
   outline: 5px auto -webkit-focus-ring-color;
   outline-offset: -2px;
@@ -1980,7 +2078,7 @@ fieldset[disabled] .btn-default.active {
 }
 .btn-default .badge {
   color: #ffffff;
-  background-color: #fff;
+  background-color: #333333;
 }
 .btn-primary {
   color: #ffffff;
@@ -2021,89 +2119,7 @@ fieldset[disabled] .btn-primary.active {
 }
 .btn-primary .badge {
   color: #428bca;
-  background-color: #fff;
-}
-.btn-warning {
-  color: #ffffff;
-  background-color: #f0ad4e;
-  border-color: #eea236;
-}
-.btn-warning:hover,
-.btn-warning:focus,
-.btn-warning:active,
-.btn-warning.active,
-.open .dropdown-toggle.btn-warning {
-  color: #ffffff;
-  background-color: #ed9c28;
-  border-color: #d58512;
-}
-.btn-warning:active,
-.btn-warning.active,
-.open .dropdown-toggle.btn-warning {
-  background-image: none;
-}
-.btn-warning.disabled,
-.btn-warning[disabled],
-fieldset[disabled] .btn-warning,
-.btn-warning.disabled:hover,
-.btn-warning[disabled]:hover,
-fieldset[disabled] .btn-warning:hover,
-.btn-warning.disabled:focus,
-.btn-warning[disabled]:focus,
-fieldset[disabled] .btn-warning:focus,
-.btn-warning.disabled:active,
-.btn-warning[disabled]:active,
-fieldset[disabled] .btn-warning:active,
-.btn-warning.disabled.active,
-.btn-warning[disabled].active,
-fieldset[disabled] .btn-warning.active {
-  background-color: #f0ad4e;
-  border-color: #eea236;
-}
-.btn-warning .badge {
-  color: #f0ad4e;
-  background-color: #fff;
-}
-.btn-danger {
-  color: #ffffff;
-  background-color: #d9534f;
-  border-color: #d43f3a;
-}
-.btn-danger:hover,
-.btn-danger:focus,
-.btn-danger:active,
-.btn-danger.active,
-.open .dropdown-toggle.btn-danger {
-  color: #ffffff;
-  background-color: #d2322d;
-  border-color: #ac2925;
-}
-.btn-danger:active,
-.btn-danger.active,
-.open .dropdown-toggle.btn-danger {
-  background-image: none;
-}
-.btn-danger.disabled,
-.btn-danger[disabled],
-fieldset[disabled] .btn-danger,
-.btn-danger.disabled:hover,
-.btn-danger[disabled]:hover,
-fieldset[disabled] .btn-danger:hover,
-.btn-danger.disabled:focus,
-.btn-danger[disabled]:focus,
-fieldset[disabled] .btn-danger:focus,
-.btn-danger.disabled:active,
-.btn-danger[disabled]:active,
-fieldset[disabled] .btn-danger:active,
-.btn-danger.disabled.active,
-.btn-danger[disabled].active,
-fieldset[disabled] .btn-danger.active {
-  background-color: #d9534f;
-  border-color: #d43f3a;
-}
-.btn-danger .badge {
-  color: #d9534f;
-  background-color: #fff;
+  background-color: #ffffff;
 }
 .btn-success {
   color: #ffffff;
@@ -2144,7 +2160,7 @@ fieldset[disabled] .btn-success.active {
 }
 .btn-success .badge {
   color: #5cb85c;
-  background-color: #fff;
+  background-color: #ffffff;
 }
 .btn-info {
   color: #ffffff;
@@ -2185,7 +2201,89 @@ fieldset[disabled] .btn-info.active {
 }
 .btn-info .badge {
   color: #5bc0de;
-  background-color: #fff;
+  background-color: #ffffff;
+}
+.btn-warning {
+  color: #ffffff;
+  background-color: #f0ad4e;
+  border-color: #eea236;
+}
+.btn-warning:hover,
+.btn-warning:focus,
+.btn-warning:active,
+.btn-warning.active,
+.open .dropdown-toggle.btn-warning {
+  color: #ffffff;
+  background-color: #ed9c28;
+  border-color: #d58512;
+}
+.btn-warning:active,
+.btn-warning.active,
+.open .dropdown-toggle.btn-warning {
+  background-image: none;
+}
+.btn-warning.disabled,
+.btn-warning[disabled],
+fieldset[disabled] .btn-warning,
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled:active,
+.btn-warning[disabled]:active,
+fieldset[disabled] .btn-warning:active,
+.btn-warning.disabled.active,
+.btn-warning[disabled].active,
+fieldset[disabled] .btn-warning.active {
+  background-color: #f0ad4e;
+  border-color: #eea236;
+}
+.btn-warning .badge {
+  color: #f0ad4e;
+  background-color: #ffffff;
+}
+.btn-danger {
+  color: #ffffff;
+  background-color: #d9534f;
+  border-color: #d43f3a;
+}
+.btn-danger:hover,
+.btn-danger:focus,
+.btn-danger:active,
+.btn-danger.active,
+.open .dropdown-toggle.btn-danger {
+  color: #ffffff;
+  background-color: #d2322d;
+  border-color: #ac2925;
+}
+.btn-danger:active,
+.btn-danger.active,
+.open .dropdown-toggle.btn-danger {
+  background-image: none;
+}
+.btn-danger.disabled,
+.btn-danger[disabled],
+fieldset[disabled] .btn-danger,
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled:active,
+.btn-danger[disabled]:active,
+fieldset[disabled] .btn-danger:active,
+.btn-danger.disabled.active,
+.btn-danger[disabled].active,
+fieldset[disabled] .btn-danger.active {
+  background-color: #d9534f;
+  border-color: #d43f3a;
+}
+.btn-danger .badge {
+  color: #d9534f;
+  background-color: #ffffff;
 }
 .btn-link {
   color: #428bca;
@@ -2220,19 +2318,22 @@ fieldset[disabled] .btn-link:focus {
   color: #999999;
   text-decoration: none;
 }
-.btn-lg {
+.btn-lg,
+.btn-group-lg > .btn {
   padding: 10px 16px;
   font-size: 18px;
   line-height: 1.33;
   border-radius: 6px;
 }
-.btn-sm {
+.btn-sm,
+.btn-group-sm > .btn {
   padding: 5px 10px;
   font-size: 12px;
   line-height: 1.5;
   border-radius: 3px;
 }
-.btn-xs {
+.btn-xs,
+.btn-group-xs > .btn {
   padding: 1px 5px;
   font-size: 12px;
   line-height: 1.5;
@@ -2276,7 +2377,7 @@ input[type="button"].btn-block {
 @font-face {
   font-family: 'Glyphicons Halflings';
   src: url('../fonts/glyphicons-halflings-regular.eot');
-  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg');
+  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
 }
 .glyphicon {
   position: relative;
@@ -2289,9 +2390,6 @@ input[type="button"].btn-block {
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
 }
-.glyphicon:empty {
-  width: 1em;
-}
 .glyphicon-asterisk:before {
   content: "\2a";
 }
@@ -2980,6 +3078,14 @@ input[type="button"].btn-block {
 .open > a {
   outline: 0;
 }
+.dropdown-menu-right {
+  left: auto;
+  right: 0;
+}
+.dropdown-menu-left {
+  left: 0;
+  right: auto;
+}
 .dropdown-header {
   display: block;
   padding: 3px 20px;
@@ -3013,8 +3119,12 @@ input[type="button"].btn-block {
 }
 @media (min-width: 769px) {
   .navbar-right .dropdown-menu {
-    right: 0;
     left: auto;
+    right: 0;
+  }
+  .navbar-right .dropdown-menu-left {
+    left: 0;
+    right: auto;
   }
 }
 .btn-group,
@@ -3048,29 +3158,16 @@ input[type="button"].btn-block {
 .btn-group .btn-group + .btn-group {
   margin-left: -1px;
 }
-.btn-toolbar:before,
-.btn-toolbar:after {
-  content: " ";
-  display: table;
-}
-.btn-toolbar:after {
-  clear: both;
-}
-.btn-toolbar:before,
-.btn-toolbar:after {
-  content: " ";
-  display: table;
-}
-.btn-toolbar:after {
-  clear: both;
+.btn-toolbar {
+  margin-left: -5px;
 }
-.btn-toolbar .btn-group {
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
   float: left;
 }
-.btn-toolbar > .btn + .btn,
-.btn-toolbar > .btn-group + .btn,
-.btn-toolbar > .btn + .btn-group,
-.btn-toolbar > .btn-group + .btn-group {
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
   margin-left: 5px;
 }
 .btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
@@ -3107,24 +3204,6 @@ input[type="button"].btn-block {
 .btn-group.open .dropdown-toggle {
   outline: 0;
 }
-.btn-group-xs > .btn {
-  padding: 1px 5px;
-  font-size: 12px;
-  line-height: 1.5;
-  border-radius: 3px;
-}
-.btn-group-sm > .btn {
-  padding: 5px 10px;
-  font-size: 12px;
-  line-height: 1.5;
-  border-radius: 3px;
-}
-.btn-group-lg > .btn {
-  padding: 10px 16px;
-  font-size: 18px;
-  line-height: 1.33;
-  border-radius: 6px;
-}
 .btn-group > .btn + .dropdown-toggle {
   padding-left: 8px;
   padding-right: 8px;
@@ -3159,22 +3238,6 @@ input[type="button"].btn-block {
   width: 100%;
   max-width: 100%;
 }
-.btn-group-vertical > .btn-group:before,
-.btn-group-vertical > .btn-group:after {
-  content: " ";
-  display: table;
-}
-.btn-group-vertical > .btn-group:after {
-  clear: both;
-}
-.btn-group-vertical > .btn-group:before,
-.btn-group-vertical > .btn-group:after {
-  content: " ";
-  display: table;
-}
-.btn-group-vertical > .btn-group:after {
-  clear: both;
-}
 .btn-group-vertical > .btn-group > .btn {
   float: none;
 }
@@ -3201,12 +3264,12 @@ input[type="button"].btn-block {
 .btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
   border-radius: 0;
 }
-.btn-group-vertical > .btn-group:first-child > .btn:last-child,
-.btn-group-vertical > .btn-group:first-child > .dropdown-toggle {
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
   border-bottom-right-radius: 0;
   border-bottom-left-radius: 0;
 }
-.btn-group-vertical > .btn-group:last-child > .btn:first-child {
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
   border-top-right-radius: 0;
   border-top-left-radius: 0;
 }
@@ -3240,6 +3303,9 @@ input[type="button"].btn-block {
   padding-right: 0;
 }
 .input-group .form-control {
+  position: relative;
+  z-index: 2;
+  float: left;
   width: 100%;
   margin-bottom: 0;
 }
@@ -3260,7 +3326,10 @@ select.input-group-lg > .input-group-btn > .btn {
 }
 textarea.input-group-lg > .form-control,
 textarea.input-group-lg > .input-group-addon,
-textarea.input-group-lg > .input-group-btn > .btn {
+textarea.input-group-lg > .input-group-btn > .btn,
+select[multiple].input-group-lg > .form-control,
+select[multiple].input-group-lg > .input-group-addon,
+select[multiple].input-group-lg > .input-group-btn > .btn {
   height: auto;
 }
 .input-group-sm > .form-control,
@@ -3280,7 +3349,10 @@ select.input-group-sm > .input-group-btn > .btn {
 }
 textarea.input-group-sm > .form-control,
 textarea.input-group-sm > .input-group-addon,
-textarea.input-group-sm > .input-group-btn > .btn {
+textarea.input-group-sm > .input-group-btn > .btn,
+select[multiple].input-group-sm > .form-control,
+select[multiple].input-group-sm > .input-group-addon,
+select[multiple].input-group-sm > .input-group-btn > .btn {
   height: auto;
 }
 .input-group-addon,
@@ -3327,8 +3399,10 @@ textarea.input-group-sm > .input-group-btn > .btn {
 .input-group .form-control:first-child,
 .input-group-addon:first-child,
 .input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group > .btn,
 .input-group-btn:first-child > .dropdown-toggle,
-.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) {
+.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
   border-bottom-right-radius: 0;
   border-top-right-radius: 0;
 }
@@ -3338,8 +3412,10 @@ textarea.input-group-sm > .input-group-btn > .btn {
 .input-group .form-control:last-child,
 .input-group-addon:last-child,
 .input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group > .btn,
 .input-group-btn:last-child > .dropdown-toggle,
-.input-group-btn:first-child > .btn:not(:first-child) {
+.input-group-btn:first-child > .btn:not(:first-child),
+.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
   border-bottom-left-radius: 0;
   border-top-left-radius: 0;
 }
@@ -3348,45 +3424,33 @@ textarea.input-group-sm > .input-group-btn > .btn {
 }
 .input-group-btn {
   position: relative;
+  font-size: 0;
   white-space: nowrap;
 }
-.input-group-btn:first-child > .btn {
-  margin-right: -1px;
-}
-.input-group-btn:last-child > .btn {
-  margin-left: -1px;
-}
 .input-group-btn > .btn {
   position: relative;
 }
 .input-group-btn > .btn + .btn {
-  margin-left: -4px;
+  margin-left: -1px;
 }
 .input-group-btn > .btn:hover,
+.input-group-btn > .btn:focus,
 .input-group-btn > .btn:active {
   z-index: 2;
 }
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group {
+  margin-right: -1px;
+}
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group {
+  margin-left: -1px;
+}
 .nav {
   margin-bottom: 0;
   padding-left: 0;
   list-style: none;
 }
-.nav:before,
-.nav:after {
-  content: " ";
-  display: table;
-}
-.nav:after {
-  clear: both;
-}
-.nav:before,
-.nav:after {
-  content: " ";
-  display: table;
-}
-.nav:after {
-  clear: both;
-}
 .nav > li {
   position: relative;
   display: block;
@@ -3580,42 +3644,10 @@ textarea.input-group-sm > .input-group-btn > .btn {
   margin-bottom: 20px;
   border: 1px solid transparent;
 }
-.navbar:before,
-.navbar:after {
-  content: " ";
-  display: table;
-}
-.navbar:after {
-  clear: both;
-}
-.navbar:before,
-.navbar:after {
-  content: " ";
-  display: table;
-}
-.navbar:after {
-  clear: both;
-}
 @media (min-width: 769px) {
-  .navbar {
-    border-radius: 4px;
-  }
-}
-.navbar-header:before,
-.navbar-header:after {
-  content: " ";
-  display: table;
-}
-.navbar-header:after {
-  clear: both;
-}
-.navbar-header:before,
-.navbar-header:after {
-  content: " ";
-  display: table;
-}
-.navbar-header:after {
-  clear: both;
+  .navbar {
+    border-radius: 4px;
+  }
 }
 @media (min-width: 769px) {
   .navbar-header {
@@ -3631,22 +3663,6 @@ textarea.input-group-sm > .input-group-btn > .btn {
   box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
   -webkit-overflow-scrolling: touch;
 }
-.navbar-collapse:before,
-.navbar-collapse:after {
-  content: " ";
-  display: table;
-}
-.navbar-collapse:after {
-  clear: both;
-}
-.navbar-collapse:before,
-.navbar-collapse:after {
-  content: " ";
-  display: table;
-}
-.navbar-collapse:after {
-  clear: both;
-}
 .navbar-collapse.in {
   overflow-y: auto;
 }
@@ -3673,13 +3689,17 @@ textarea.input-group-sm > .input-group-btn > .btn {
   }
 }
 .container > .navbar-header,
-.container > .navbar-collapse {
+.container-fluid > .navbar-header,
+.container > .navbar-collapse,
+.container-fluid > .navbar-collapse {
   margin-right: -15px;
   margin-left: -15px;
 }
 @media (min-width: 769px) {
   .container > .navbar-header,
-  .container > .navbar-collapse {
+  .container-fluid > .navbar-header,
+  .container > .navbar-collapse,
+  .container-fluid > .navbar-collapse {
     margin-right: 0;
     margin-left: 0;
   }
@@ -3720,13 +3740,15 @@ textarea.input-group-sm > .input-group-btn > .btn {
   padding: 15px 15px;
   font-size: 18px;
   line-height: 20px;
+  height: 50px;
 }
 .navbar-brand:hover,
 .navbar-brand:focus {
   text-decoration: none;
 }
 @media (min-width: 769px) {
-  .navbar > .container .navbar-brand {
+  .navbar > .container .navbar-brand,
+  .navbar > .container-fluid .navbar-brand {
     margin-left: -15px;
   }
 }
@@ -3742,6 +3764,9 @@ textarea.input-group-sm > .input-group-btn > .btn {
   border: 1px solid transparent;
   border-radius: 4px;
 }
+.navbar-toggle:focus {
+  outline: none;
+}
 .navbar-toggle .icon-bar {
   display: block;
   width: 22px;
@@ -3821,7 +3846,7 @@ textarea.input-group-sm > .input-group-btn > .btn {
   margin-top: 8px;
   margin-bottom: 8px;
 }
-@media (min-width: 768px) {
+@media (min-width: 769px) {
   .navbar-form .form-group {
     display: inline-block;
     margin-bottom: 0;
@@ -3829,9 +3854,15 @@ textarea.input-group-sm > .input-group-btn > .btn {
   }
   .navbar-form .form-control {
     display: inline-block;
-  }
-  .navbar-form select.form-control {
     width: auto;
+    vertical-align: middle;
+  }
+  .navbar-form .input-group > .form-control {
+    width: 100%;
+  }
+  .navbar-form .control-label {
+    margin-bottom: 0;
+    vertical-align: middle;
   }
   .navbar-form .radio,
   .navbar-form .checkbox {
@@ -3839,12 +3870,16 @@ textarea.input-group-sm > .input-group-btn > .btn {
     margin-top: 0;
     margin-bottom: 0;
     padding-left: 0;
+    vertical-align: middle;
   }
   .navbar-form .radio input[type="radio"],
   .navbar-form .checkbox input[type="checkbox"] {
     float: none;
     margin-left: 0;
   }
+  .navbar-form .has-feedback .form-control-feedback {
+    top: 0;
+  }
 }
 @media (max-width: 768px) {
   .navbar-form .form-group {
@@ -3875,11 +3910,6 @@ textarea.input-group-sm > .input-group-btn > .btn {
   border-bottom-right-radius: 0;
   border-bottom-left-radius: 0;
 }
-.navbar-nav.pull-right > li > .dropdown-menu,
-.navbar-nav > li > .dropdown-menu.pull-right {
-  left: auto;
-  right: 0;
-}
 .navbar-btn {
   margin-top: 8px;
   margin-bottom: 8px;
@@ -3949,7 +3979,7 @@ textarea.input-group-sm > .input-group-btn > .btn {
   background-color: #dddddd;
 }
 .navbar-default .navbar-toggle .icon-bar {
-  background-color: #cccccc;
+  background-color: #888888;
 }
 .navbar-default .navbar-collapse,
 .navbar-default .navbar-form {
@@ -4112,6 +4142,7 @@ textarea.input-group-sm > .input-group-btn > .btn {
   padding: 6px 12px;
   line-height: 1.428571429;
   text-decoration: none;
+  color: #428bca;
   background-color: #ffffff;
   border: 1px solid #dddddd;
   margin-left: -1px;
@@ -4131,7 +4162,9 @@ textarea.input-group-sm > .input-group-btn > .btn {
 .pagination > li > span:hover,
 .pagination > li > a:focus,
 .pagination > li > span:focus {
+  color: #2a6496;
   background-color: #eeeeee;
+  border-color: #dddddd;
 }
 .pagination > .active > a,
 .pagination > .active > span,
@@ -4192,22 +4225,6 @@ textarea.input-group-sm > .input-group-btn > .btn {
   list-style: none;
   text-align: center;
 }
-.pager:before,
-.pager:after {
-  content: " ";
-  display: table;
-}
-.pager:after {
-  clear: both;
-}
-.pager:before,
-.pager:after {
-  content: " ";
-  display: table;
-}
-.pager:after {
-  clear: both;
-}
 .pager li {
   display: inline;
 }
@@ -4328,6 +4345,10 @@ textarea.input-group-sm > .input-group-btn > .btn {
   position: relative;
   top: -1px;
 }
+.btn-xs .badge {
+  top: 0;
+  padding: 1px 5px;
+}
 a.badge:hover,
 a.badge:focus {
   color: #ffffff;
@@ -4345,19 +4366,17 @@ a.list-group-item.active > .badge,
 .jumbotron {
   padding: 30px;
   margin-bottom: 30px;
-  font-size: 21px;
-  font-weight: 200;
-  line-height: 2.1428571435;
   color: inherit;
   background-color: #eeeeee;
 }
 .jumbotron h1,
 .jumbotron .h1 {
-  line-height: 1;
   color: inherit;
 }
 .jumbotron p {
-  line-height: 1.4;
+  margin-bottom: 15px;
+  font-size: 21px;
+  font-weight: 200;
 }
 .container .jumbotron {
   border-radius: 6px;
@@ -4392,9 +4411,6 @@ a.list-group-item.active > .badge,
 }
 .thumbnail > img,
 .thumbnail a > img {
-  display: block;
-  max-width: 100%;
-  height: auto;
   margin-left: auto;
   margin-right: auto;
 }
@@ -4643,6 +4659,94 @@ a.list-group-item.active:hover .list-group-item-text,
 a.list-group-item.active:focus .list-group-item-text {
   color: #e1edf7;
 }
+.list-group-item-success {
+  color: #3c763d;
+  background-color: #dff0d8;
+}
+a.list-group-item-success {
+  color: #3c763d;
+}
+a.list-group-item-success .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-success:hover,
+a.list-group-item-success:focus {
+  color: #3c763d;
+  background-color: #d0e9c6;
+}
+a.list-group-item-success.active,
+a.list-group-item-success.active:hover,
+a.list-group-item-success.active:focus {
+  color: #fff;
+  background-color: #3c763d;
+  border-color: #3c763d;
+}
+.list-group-item-info {
+  color: #31708f;
+  background-color: #d9edf7;
+}
+a.list-group-item-info {
+  color: #31708f;
+}
+a.list-group-item-info .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-info:hover,
+a.list-group-item-info:focus {
+  color: #31708f;
+  background-color: #c4e3f3;
+}
+a.list-group-item-info.active,
+a.list-group-item-info.active:hover,
+a.list-group-item-info.active:focus {
+  color: #fff;
+  background-color: #31708f;
+  border-color: #31708f;
+}
+.list-group-item-warning {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+}
+a.list-group-item-warning {
+  color: #8a6d3b;
+}
+a.list-group-item-warning .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-warning:hover,
+a.list-group-item-warning:focus {
+  color: #8a6d3b;
+  background-color: #faf2cc;
+}
+a.list-group-item-warning.active,
+a.list-group-item-warning.active:hover,
+a.list-group-item-warning.active:focus {
+  color: #fff;
+  background-color: #8a6d3b;
+  border-color: #8a6d3b;
+}
+.list-group-item-danger {
+  color: #a94442;
+  background-color: #f2dede;
+}
+a.list-group-item-danger {
+  color: #a94442;
+}
+a.list-group-item-danger .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-danger:hover,
+a.list-group-item-danger:focus {
+  color: #a94442;
+  background-color: #ebcccc;
+}
+a.list-group-item-danger.active,
+a.list-group-item-danger.active:hover,
+a.list-group-item-danger.active:focus {
+  color: #fff;
+  background-color: #a94442;
+  border-color: #a94442;
+}
 .list-group-item-heading {
   margin-top: 0;
   margin-bottom: 5px;
@@ -4662,34 +4766,47 @@ a.list-group-item.active:focus .list-group-item-text {
 .panel-body {
   padding: 15px;
 }
-.panel-body:before,
-.panel-body:after {
-  content: " ";
-  display: table;
+.panel-heading {
+  padding: 10px 15px;
+  border-bottom: 1px solid transparent;
+  border-top-right-radius: 3px;
+  border-top-left-radius: 3px;
 }
-.panel-body:after {
-  clear: both;
+.panel-heading > .dropdown .dropdown-toggle {
+  color: inherit;
 }
-.panel-body:before,
-.panel-body:after {
-  content: " ";
-  display: table;
+.panel-title {
+  margin-top: 0;
+  margin-bottom: 0;
+  font-size: 16px;
+  color: inherit;
 }
-.panel-body:after {
-  clear: both;
+.panel-title > a {
+  color: inherit;
+}
+.panel-footer {
+  padding: 10px 15px;
+  background-color: #f5f5f5;
+  border-top: 1px solid #dddddd;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
 }
 .panel > .list-group {
   margin-bottom: 0;
 }
 .panel > .list-group .list-group-item {
   border-width: 1px 0;
+  border-radius: 0;
 }
-.panel > .list-group .list-group-item:first-child {
-  border-top-right-radius: 0;
-  border-top-left-radius: 0;
+.panel > .list-group:first-child .list-group-item:first-child {
+  border-top: 0;
+  border-top-right-radius: 3px;
+  border-top-left-radius: 3px;
 }
-.panel > .list-group .list-group-item:last-child {
+.panel > .list-group:last-child .list-group-item:last-child {
   border-bottom: 0;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
 }
 .panel-heading + .list-group .list-group-item:first-child {
   border-top-width: 0;
@@ -4698,12 +4815,62 @@ a.list-group-item.active:focus .list-group-item-text {
 .panel > .table-responsive > .table {
   margin-bottom: 0;
 }
+.panel > .table:first-child,
+.panel > .table-responsive:first-child > .table:first-child {
+  border-top-right-radius: 3px;
+  border-top-left-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {
+  border-top-left-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {
+  border-top-right-radius: 3px;
+}
+.panel > .table:last-child,
+.panel > .table-responsive:last-child > .table:last-child {
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {
+  border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {
+  border-bottom-right-radius: 3px;
+}
 .panel > .panel-body + .table,
 .panel > .panel-body + .table-responsive {
   border-top: 1px solid #dddddd;
 }
-.panel > .table > tbody:first-child th,
-.panel > .table > tbody:first-child td {
+.panel > .table > tbody:first-child > tr:first-child th,
+.panel > .table > tbody:first-child > tr:first-child td {
   border-top: 0;
 }
 .panel > .table-bordered,
@@ -4738,48 +4905,32 @@ a.list-group-item.active:focus .list-group-item-text {
 .panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {
   border-right: 0;
 }
-.panel > .table-bordered > thead > tr:last-child > th,
-.panel > .table-responsive > .table-bordered > thead > tr:last-child > th,
-.panel > .table-bordered > tbody > tr:last-child > th,
-.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,
-.panel > .table-bordered > tfoot > tr:last-child > th,
-.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th,
-.panel > .table-bordered > thead > tr:last-child > td,
-.panel > .table-responsive > .table-bordered > thead > tr:last-child > td,
+.panel > .table-bordered > thead > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,
+.panel > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-bordered > thead > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,
+.panel > .table-bordered > tbody > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {
+  border-bottom: 0;
+}
 .panel > .table-bordered > tbody > tr:last-child > td,
 .panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,
 .panel > .table-bordered > tfoot > tr:last-child > td,
-.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td {
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-bordered > tfoot > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {
   border-bottom: 0;
 }
 .panel > .table-responsive {
   border: 0;
   margin-bottom: 0;
 }
-.panel-heading {
-  padding: 10px 15px;
-  border-bottom: 1px solid transparent;
-  border-top-right-radius: 3px;
-  border-top-left-radius: 3px;
-}
-.panel-heading > .dropdown .dropdown-toggle {
-  color: inherit;
-}
-.panel-title {
-  margin-top: 0;
-  margin-bottom: 0;
-  font-size: 16px;
-  color: inherit;
-}
-.panel-title > a {
-  color: inherit;
-}
-.panel-footer {
-  padding: 10px 15px;
-  background-color: #f5f5f5;
-  border-top: 1px solid #dddddd;
-  border-bottom-right-radius: 3px;
-  border-bottom-left-radius: 3px;
+.panel-group {
+  margin-bottom: 20px;
 }
 .panel-group .panel {
   margin-bottom: 0;
@@ -4843,6 +4994,20 @@ a.list-group-item.active:focus .list-group-item-text {
 .panel-success > .panel-footer + .panel-collapse .panel-body {
   border-bottom-color: #d6e9c6;
 }
+.panel-info {
+  border-color: #bce8f1;
+}
+.panel-info > .panel-heading {
+  color: #31708f;
+  background-color: #d9edf7;
+  border-color: #bce8f1;
+}
+.panel-info > .panel-heading + .panel-collapse .panel-body {
+  border-top-color: #bce8f1;
+}
+.panel-info > .panel-footer + .panel-collapse .panel-body {
+  border-bottom-color: #bce8f1;
+}
 .panel-warning {
   border-color: #faebcc;
 }
@@ -4871,20 +5036,6 @@ a.list-group-item.active:focus .list-group-item-text {
 .panel-danger > .panel-footer + .panel-collapse .panel-body {
   border-bottom-color: #ebccd1;
 }
-.panel-info {
-  border-color: #bce8f1;
-}
-.panel-info > .panel-heading {
-  color: #31708f;
-  background-color: #d9edf7;
-  border-color: #bce8f1;
-}
-.panel-info > .panel-heading + .panel-collapse .panel-body {
-  border-top-color: #bce8f1;
-}
-.panel-info > .panel-footer + .panel-collapse .panel-body {
-  border-bottom-color: #bce8f1;
-}
 .well {
   min-height: 20px;
   padding: 19px;
@@ -4944,7 +5095,9 @@ button.close {
   right: 0;
   bottom: 0;
   left: 0;
-  z-index: 1040;
+  z-index: 1050;
+  -webkit-overflow-scrolling: touch;
+  outline: 0;
 }
 .modal.fade .modal-dialog {
   -webkit-transform: translate(0, -25%);
@@ -4964,7 +5117,6 @@ button.close {
   position: relative;
   width: auto;
   margin: 10px;
-  z-index: 1050;
 }
 .modal-content {
   position: relative;
@@ -4983,7 +5135,7 @@ button.close {
   right: 0;
   bottom: 0;
   left: 0;
-  z-index: 1030;
+  z-index: 1040;
   background-color: #000000;
 }
 .modal-backdrop.fade {
@@ -5016,22 +5168,6 @@ button.close {
   text-align: right;
   border-top: 1px solid #e5e5e5;
 }
-.modal-footer:before,
-.modal-footer:after {
-  content: " ";
-  display: table;
-}
-.modal-footer:after {
-  clear: both;
-}
-.modal-footer:before,
-.modal-footer:after {
-  content: " ";
-  display: table;
-}
-.modal-footer:after {
-  clear: both;
-}
 .modal-footer .btn + .btn {
   margin-left: 5px;
   margin-bottom: 0;
@@ -5042,7 +5178,7 @@ button.close {
 .modal-footer .btn-block + .btn-block {
   margin-left: 0;
 }
-@media screen and (min-width: 769px) {
+@media (min-width: 769px) {
   .modal-dialog {
     width: 600px;
     margin: 30px auto;
@@ -5051,6 +5187,14 @@ button.close {
     -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
     box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
   }
+  .modal-sm {
+    width: 300px;
+  }
+}
+@media (min-width: 993px) {
+  .modal-lg {
+    width: 900px;
+  }
 }
 .tooltip {
   position: absolute;
@@ -5193,8 +5337,8 @@ button.close {
 .popover-content {
   padding: 9px 14px;
 }
-.popover .arrow,
-.popover .arrow:after {
+.popover .arrow,
+.popover .arrow:after {
   position: absolute;
   display: block;
   width: 0;
@@ -5202,14 +5346,14 @@ button.close {
   border-color: transparent;
   border-style: solid;
 }
-.popover .arrow {
+.popover .arrow {
   border-width: 11px;
 }
-.popover .arrow:after {
+.popover .arrow:after {
   border-width: 10px;
   content: "";
 }
-.popover.top .arrow {
+.popover.top .arrow {
   left: 50%;
   margin-left: -11px;
   border-bottom-width: 0;
@@ -5217,14 +5361,14 @@ button.close {
   border-top-color: rgba(0, 0, 0, 0.25);
   bottom: -11px;
 }
-.popover.top .arrow:after {
+.popover.top .arrow:after {
   content: " ";
   bottom: 1px;
   margin-left: -10px;
   border-bottom-width: 0;
   border-top-color: #ffffff;
 }
-.popover.right .arrow {
+.popover.right .arrow {
   top: 50%;
   left: -11px;
   margin-top: -11px;
@@ -5232,14 +5376,14 @@ button.close {
   border-right-color: #999999;
   border-right-color: rgba(0, 0, 0, 0.25);
 }
-.popover.right .arrow:after {
+.popover.right .arrow:after {
   content: " ";
   left: 1px;
   bottom: -10px;
   border-left-width: 0;
   border-right-color: #ffffff;
 }
-.popover.bottom .arrow {
+.popover.bottom .arrow {
   left: 50%;
   margin-left: -11px;
   border-top-width: 0;
@@ -5247,14 +5391,14 @@ button.close {
   border-bottom-color: rgba(0, 0, 0, 0.25);
   top: -11px;
 }
-.popover.bottom .arrow:after {
+.popover.bottom .arrow:after {
   content: " ";
   top: 1px;
   margin-left: -10px;
   border-top-width: 0;
   border-bottom-color: #ffffff;
 }
-.popover.left .arrow {
+.popover.left .arrow {
   top: 50%;
   right: -11px;
   margin-top: -11px;
@@ -5262,7 +5406,7 @@ button.close {
   border-left-color: #999999;
   border-left-color: rgba(0, 0, 0, 0.25);
 }
-.popover.left .arrow:after {
+.popover.left .arrow:after {
   content: " ";
   right: 1px;
   border-right-width: 0;
@@ -5285,9 +5429,6 @@ button.close {
 }
 .carousel-inner > .item > img,
 .carousel-inner > .item > a > img {
-  display: block;
-  max-width: 100%;
-  height: auto;
   line-height: 1;
 }
 .carousel-inner > .active,
@@ -5431,8 +5572,8 @@ button.close {
   text-shadow: none;
 }
 @media screen and (min-width: 769px) {
-  .carousel-control .glyphicons-chevron-left,
-  .carousel-control .glyphicons-chevron-right,
+  .carousel-control .glyphicon-chevron-left,
+  .carousel-control .glyphicon-chevron-right,
   .carousel-control .icon-prev,
   .carousel-control .icon-next {
     width: 30px;
@@ -5451,11 +5592,50 @@ button.close {
   }
 }
 .clearfix:before,
-.clearfix:after {
+.clearfix:after,
+.container:before,
+.container:after,
+.container-fluid:before,
+.container-fluid:after,
+.row:before,
+.row:after,
+.form-horizontal .form-group:before,
+.form-horizontal .form-group:after,
+.btn-toolbar:before,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:before,
+.btn-group-vertical > .btn-group:after,
+.nav:before,
+.nav:after,
+.navbar:before,
+.navbar:after,
+.navbar-header:before,
+.navbar-header:after,
+.navbar-collapse:before,
+.navbar-collapse:after,
+.pager:before,
+.pager:after,
+.panel-body:before,
+.panel-body:after,
+.modal-footer:before,
+.modal-footer:after {
   content: " ";
   display: table;
 }
-.clearfix:after {
+.clearfix:after,
+.container:after,
+.container-fluid:after,
+.row:after,
+.form-horizontal .form-group:after,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:after,
+.nav:after,
+.navbar:after,
+.navbar-header:after,
+.navbar-collapse:after,
+.pager:after,
+.panel-body:after,
+.modal-footer:after {
   clear: both;
 }
 .center-block {
@@ -5496,9 +5676,9 @@ button.close {
   width: device-width;
 }
 .visible-xs,
-tr.visible-xs,
-th.visible-xs,
-td.visible-xs {
+.visible-sm,
+.visible-md,
+.visible-lg {
   display: none !important;
 }
 @media (max-width: 768px) {
@@ -5516,72 +5696,6 @@ td.visible-xs {
     display: table-cell !important;
   }
 }
-@media (min-width: 769px) and (max-width: 992px) {
-  .visible-xs.visible-sm {
-    display: block !important;
-  }
-  table.visible-xs.visible-sm {
-    display: table;
-  }
-  tr.visible-xs.visible-sm {
-    display: table-row !important;
-  }
-  th.visible-xs.visible-sm,
-  td.visible-xs.visible-sm {
-    display: table-cell !important;
-  }
-}
-@media (min-width: 993px) and (max-width: 1200px) {
-  .visible-xs.visible-md {
-    display: block !important;
-  }
-  table.visible-xs.visible-md {
-    display: table;
-  }
-  tr.visible-xs.visible-md {
-    display: table-row !important;
-  }
-  th.visible-xs.visible-md,
-  td.visible-xs.visible-md {
-    display: table-cell !important;
-  }
-}
-@media (min-width: 1201px) {
-  .visible-xs.visible-lg {
-    display: block !important;
-  }
-  table.visible-xs.visible-lg {
-    display: table;
-  }
-  tr.visible-xs.visible-lg {
-    display: table-row !important;
-  }
-  th.visible-xs.visible-lg,
-  td.visible-xs.visible-lg {
-    display: table-cell !important;
-  }
-}
-.visible-sm,
-tr.visible-sm,
-th.visible-sm,
-td.visible-sm {
-  display: none !important;
-}
-@media (max-width: 768px) {
-  .visible-sm.visible-xs {
-    display: block !important;
-  }
-  table.visible-sm.visible-xs {
-    display: table;
-  }
-  tr.visible-sm.visible-xs {
-    display: table-row !important;
-  }
-  th.visible-sm.visible-xs,
-  td.visible-sm.visible-xs {
-    display: table-cell !important;
-  }
-}
 @media (min-width: 769px) and (max-width: 992px) {
   .visible-sm {
     display: block !important;
@@ -5597,72 +5711,6 @@ td.visible-sm {
     display: table-cell !important;
   }
 }
-@media (min-width: 993px) and (max-width: 1200px) {
-  .visible-sm.visible-md {
-    display: block !important;
-  }
-  table.visible-sm.visible-md {
-    display: table;
-  }
-  tr.visible-sm.visible-md {
-    display: table-row !important;
-  }
-  th.visible-sm.visible-md,
-  td.visible-sm.visible-md {
-    display: table-cell !important;
-  }
-}
-@media (min-width: 1201px) {
-  .visible-sm.visible-lg {
-    display: block !important;
-  }
-  table.visible-sm.visible-lg {
-    display: table;
-  }
-  tr.visible-sm.visible-lg {
-    display: table-row !important;
-  }
-  th.visible-sm.visible-lg,
-  td.visible-sm.visible-lg {
-    display: table-cell !important;
-  }
-}
-.visible-md,
-tr.visible-md,
-th.visible-md,
-td.visible-md {
-  display: none !important;
-}
-@media (max-width: 768px) {
-  .visible-md.visible-xs {
-    display: block !important;
-  }
-  table.visible-md.visible-xs {
-    display: table;
-  }
-  tr.visible-md.visible-xs {
-    display: table-row !important;
-  }
-  th.visible-md.visible-xs,
-  td.visible-md.visible-xs {
-    display: table-cell !important;
-  }
-}
-@media (min-width: 769px) and (max-width: 992px) {
-  .visible-md.visible-sm {
-    display: block !important;
-  }
-  table.visible-md.visible-sm {
-    display: table;
-  }
-  tr.visible-md.visible-sm {
-    display: table-row !important;
-  }
-  th.visible-md.visible-sm,
-  td.visible-md.visible-sm {
-    display: table-cell !important;
-  }
-}
 @media (min-width: 993px) and (max-width: 1200px) {
   .visible-md {
     display: block !important;
@@ -5678,72 +5726,6 @@ td.visible-md {
     display: table-cell !important;
   }
 }
-@media (min-width: 1201px) {
-  .visible-md.visible-lg {
-    display: block !important;
-  }
-  table.visible-md.visible-lg {
-    display: table;
-  }
-  tr.visible-md.visible-lg {
-    display: table-row !important;
-  }
-  th.visible-md.visible-lg,
-  td.visible-md.visible-lg {
-    display: table-cell !important;
-  }
-}
-.visible-lg,
-tr.visible-lg,
-th.visible-lg,
-td.visible-lg {
-  display: none !important;
-}
-@media (max-width: 768px) {
-  .visible-lg.visible-xs {
-    display: block !important;
-  }
-  table.visible-lg.visible-xs {
-    display: table;
-  }
-  tr.visible-lg.visible-xs {
-    display: table-row !important;
-  }
-  th.visible-lg.visible-xs,
-  td.visible-lg.visible-xs {
-    display: table-cell !important;
-  }
-}
-@media (min-width: 769px) and (max-width: 992px) {
-  .visible-lg.visible-sm {
-    display: block !important;
-  }
-  table.visible-lg.visible-sm {
-    display: table;
-  }
-  tr.visible-lg.visible-sm {
-    display: table-row !important;
-  }
-  th.visible-lg.visible-sm,
-  td.visible-lg.visible-sm {
-    display: table-cell !important;
-  }
-}
-@media (min-width: 993px) and (max-width: 1200px) {
-  .visible-lg.visible-md {
-    display: block !important;
-  }
-  table.visible-lg.visible-md {
-    display: table;
-  }
-  tr.visible-lg.visible-md {
-    display: table-row !important;
-  }
-  th.visible-lg.visible-md,
-  td.visible-lg.visible-md {
-    display: table-cell !important;
-  }
-}
 @media (min-width: 1201px) {
   .visible-lg {
     display: block !important;
@@ -5759,190 +5741,27 @@ td.visible-lg {
     display: table-cell !important;
   }
 }
-.hidden-xs {
-  display: block !important;
-}
-table.hidden-xs {
-  display: table;
-}
-tr.hidden-xs {
-  display: table-row !important;
-}
-th.hidden-xs,
-td.hidden-xs {
-  display: table-cell !important;
-}
-@media (max-width: 768px) {
-  .hidden-xs,
-  tr.hidden-xs,
-  th.hidden-xs,
-  td.hidden-xs {
-    display: none !important;
-  }
-}
-@media (min-width: 769px) and (max-width: 992px) {
-  .hidden-xs.hidden-sm,
-  tr.hidden-xs.hidden-sm,
-  th.hidden-xs.hidden-sm,
-  td.hidden-xs.hidden-sm {
-    display: none !important;
-  }
-}
-@media (min-width: 993px) and (max-width: 1200px) {
-  .hidden-xs.hidden-md,
-  tr.hidden-xs.hidden-md,
-  th.hidden-xs.hidden-md,
-  td.hidden-xs.hidden-md {
-    display: none !important;
-  }
-}
-@media (min-width: 1201px) {
-  .hidden-xs.hidden-lg,
-  tr.hidden-xs.hidden-lg,
-  th.hidden-xs.hidden-lg,
-  td.hidden-xs.hidden-lg {
-    display: none !important;
-  }
-}
-.hidden-sm {
-  display: block !important;
-}
-table.hidden-sm {
-  display: table;
-}
-tr.hidden-sm {
-  display: table-row !important;
-}
-th.hidden-sm,
-td.hidden-sm {
-  display: table-cell !important;
-}
-@media (max-width: 768px) {
-  .hidden-sm.hidden-xs,
-  tr.hidden-sm.hidden-xs,
-  th.hidden-sm.hidden-xs,
-  td.hidden-sm.hidden-xs {
-    display: none !important;
-  }
-}
-@media (min-width: 769px) and (max-width: 992px) {
-  .hidden-sm,
-  tr.hidden-sm,
-  th.hidden-sm,
-  td.hidden-sm {
-    display: none !important;
-  }
-}
-@media (min-width: 993px) and (max-width: 1200px) {
-  .hidden-sm.hidden-md,
-  tr.hidden-sm.hidden-md,
-  th.hidden-sm.hidden-md,
-  td.hidden-sm.hidden-md {
-    display: none !important;
-  }
-}
-@media (min-width: 1201px) {
-  .hidden-sm.hidden-lg,
-  tr.hidden-sm.hidden-lg,
-  th.hidden-sm.hidden-lg,
-  td.hidden-sm.hidden-lg {
-    display: none !important;
-  }
-}
-.hidden-md {
-  display: block !important;
-}
-table.hidden-md {
-  display: table;
-}
-tr.hidden-md {
-  display: table-row !important;
-}
-th.hidden-md,
-td.hidden-md {
-  display: table-cell !important;
-}
-@media (max-width: 768px) {
-  .hidden-md.hidden-xs,
-  tr.hidden-md.hidden-xs,
-  th.hidden-md.hidden-xs,
-  td.hidden-md.hidden-xs {
-    display: none !important;
-  }
-}
-@media (min-width: 769px) and (max-width: 992px) {
-  .hidden-md.hidden-sm,
-  tr.hidden-md.hidden-sm,
-  th.hidden-md.hidden-sm,
-  td.hidden-md.hidden-sm {
-    display: none !important;
-  }
-}
-@media (min-width: 993px) and (max-width: 1200px) {
-  .hidden-md,
-  tr.hidden-md,
-  th.hidden-md,
-  td.hidden-md {
-    display: none !important;
-  }
-}
-@media (min-width: 1201px) {
-  .hidden-md.hidden-lg,
-  tr.hidden-md.hidden-lg,
-  th.hidden-md.hidden-lg,
-  td.hidden-md.hidden-lg {
-    display: none !important;
-  }
-}
-.hidden-lg {
-  display: block !important;
-}
-table.hidden-lg {
-  display: table;
-}
-tr.hidden-lg {
-  display: table-row !important;
-}
-th.hidden-lg,
-td.hidden-lg {
-  display: table-cell !important;
-}
 @media (max-width: 768px) {
-  .hidden-lg.hidden-xs,
-  tr.hidden-lg.hidden-xs,
-  th.hidden-lg.hidden-xs,
-  td.hidden-lg.hidden-xs {
+  .hidden-xs {
     display: none !important;
   }
 }
 @media (min-width: 769px) and (max-width: 992px) {
-  .hidden-lg.hidden-sm,
-  tr.hidden-lg.hidden-sm,
-  th.hidden-lg.hidden-sm,
-  td.hidden-lg.hidden-sm {
+  .hidden-sm {
     display: none !important;
   }
 }
 @media (min-width: 993px) and (max-width: 1200px) {
-  .hidden-lg.hidden-md,
-  tr.hidden-lg.hidden-md,
-  th.hidden-lg.hidden-md,
-  td.hidden-lg.hidden-md {
+  .hidden-md {
     display: none !important;
   }
 }
 @media (min-width: 1201px) {
-  .hidden-lg,
-  tr.hidden-lg,
-  th.hidden-lg,
-  td.hidden-lg {
+  .hidden-lg {
     display: none !important;
   }
 }
-.visible-print,
-tr.visible-print,
-th.visible-print,
-td.visible-print {
+.visible-print {
   display: none !important;
 }
 @media print {
@@ -5959,10 +5778,9 @@ td.visible-print {
   td.visible-print {
     display: table-cell !important;
   }
-  .hidden-print,
-  tr.hidden-print,
-  th.hidden-print,
-  td.hidden-print {
+}
+@media print {
+  .hidden-print {
     display: none !important;
   }
 }
@@ -7103,6 +6921,9 @@ a.editable-click {
 .modal {
   overflow: hidden;
 }
+.modal-body {
+  overflow: auto;
+}
 .has-error .select2-choice {
   border-color: #a94442 !important;
   -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075) !important;
@@ -7121,3 +6942,80 @@ a.editable-click {
   right: 5px;
   color: #f1f1f1;
 }
+.nav-tabs li a {
+  color: white !important;
+  background-color: transparent !important;
+  border-radius: 4px 4px 0 0 !important;
+}
+.nav-tabs {
+  border-bottom: none !important;
+}
+@-webkit-keyframes rotating {
+  from {
+    -webkit-transform: rotate(0deg);
+  }
+  to {
+    -webkit-transform: rotate(360deg);
+  }
+}
+@-moz-keyframes rotating {
+  from {
+    -moz-transform: rotate(0deg);
+  }
+  to {
+    -moz-transform: rotate(360deg);
+  }
+}
+@keyframes rotating {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+@-ms-keyframes rotating {
+  from {
+    -ms-transform: rotate(0deg);
+  }
+  to {
+    -ms-transform: rotate(360deg);
+  }
+}
+@-o-keyframes rotating {
+  from {
+    -o-transform: rotate(0deg);
+  }
+  to {
+    -o-transform: rotate(360deg);
+  }
+}
+.rotating {
+  -moz-animation: rotating 1.5s linear infinite;
+  -webkit-animation: rotating 1.5s linear infinite;
+  -o-animation: rotating 1.5s linear infinite;
+  -ms-animation: rotating 1.5s linear infinite;
+  animation: rotating 1.5s linear infinite;
+}
+@media screen and (max-height: 700px) {
+  .modal-body {
+    max-height: 355px;
+  }
+  .modal-dialog {
+    height: 500px;
+  }
+  .modal-content {
+    height: 100%;
+  }
+}
+@media screen and (max-height: 540px) {
+  .modal-body {
+    max-height: 225px;
+  }
+  .modal-dialog {
+    height: 370px;
+  }
+  .modal-content {
+    height: 100%;
+  }
+}
index 0b070e17f7d859834f281e4249d943b93d18be4c..a3fc8989f4ec3e800ebec80fd8f6b0e574273ae7 100644 (file)
@@ -224,7 +224,6 @@ define(['app/sfc/sfc.module'], function (sfc) {
       modalInstance = $modal.open({
         templateUrl: 'src/app/sfc/acl/acl.modal.metadata.tpl.html',
         backdrop: false,
-        size: "sm",
         controller: 'sfcAclModalMetadataCtrl',
         resolve: {
           ace: function () {
index 5b88367eb622694da671e1c74ab87b3606ad844e..54f65ae2664ecb6943dee384609579bfd3d7a6ca 100644 (file)
@@ -1,80 +1,7 @@
-<a class="btn btn-info add-row" href="index.html#/sfc/acl-create">
-    {{'SFC_ACL_ADD' | translate}}
-</a>
+<div class="col-xs-12" style="padding: 0px">
 
-<button type="button" ng-click="tableParams.sorting({})" class="btn btn-default pull-right">{{'SFC_CLEAR_SORTING' |
-    translate}}
-</button>
-
-<table ng-table="tableParams" show-filter="true" class="footable table">
-    <tr ng-repeat="entry in $data track by $index">
-        <td data-title="'SFC_ACL_SHORT_NAME' | translate" sortable="'valueOf()[\'acl-name\']'"
-            filter="{ 'acl-name': 'text' }">
-            {{entry['acl-name']}}
-        </td>
-        <td data-title="'SFC_ACL_SHORT_RULE_NAME' | translate" sortable="'valueOf()[\'rule-name\']'"
-            filter="{ 'rule-name': 'text' }">
-            {{entry['rule-name']}}
-        </td>
-        <td data-title="'SFC_ACL_ACTIONS_SFP' | translate"
-            sortable="'valueOf()[\'actions\'][\'service-function-path\']'" filter="{ 'actions': 'text' }">
-            {{entry['actions']['service-function-path']}}
-        </td>
-        <td data-title="'SFC_ACL_SHORT_SRC_IP_MAC_ADDRESS' | translate"
-            sortable="'valueOf()[\'source-ip-mac-mask-string\']'" filter="{ 'source-ip-mac-mask-string': 'text' }">
-            {{entry['matches']['source-ipv4-address']}}{{entry['matches']['source-ipv6-address']}}
-            {{entry['matches']['source-mac-address']}}<span class="spanText"
-                                                            ng-if="entry['matches']['source-mac-address-mask']"><br/>({{entry['matches']['source-mac-address-mask']}})</span>
-
-        </td>
-        <td data-title="'SFC_ACL_SHORT_DST_IP_MAC_ADDRESS' | translate"
-            sortable="'valueOf()[\'destination-ip-mac-mask-string\']'"
-            filter="{ 'destination-ip-mac-mask-string': 'text' }">
-            {{entry['matches']['destination-ipv4-address']}}{{entry['matches']['destination-ipv6-address']}}
-            {{entry['matches']['destination-mac-address']}}<span class="spanText"
-                                                                 ng-if="entry['matches']['destination-mac-address-mask']"><br/>({{entry['matches']['destination-mac-address-mask']}})</span>
-        </td>
-        <td data-title="'SFC_ACL_SHORT_IPV6_FLOW_LABEL' | translate" sortable="'valueOf()[\'flow-label-string\']'"
-            filter="{ 'flow-label-string': 'text' }">
-            {{entry['matches']['flow-label']}}
-        </td>
-        <td data-title="'SFC_ACL_SHORT_SRC_PORT_RANGE' | translate" sortable="'valueOf()[\'source-port-range-string\']'"
-            filter="{ 'source-port-range-string': 'text' }">
-            {{entry['matches']['source-port-range']['lower-port']}}-{{entry['matches']['source-port-range']['upper-port']}}
-        </td>
-        <td data-title="'SFC_ACL_SHORT_DST_PORT_RANGE' | translate"
-            sortable="'valueOf()[\'destination-port-range-string\']'"
-            filter="{ 'destination-port-range-string': 'text' }">
-            {{entry['matches']['destination-port-range']['lower-port']}}-{{entry['matches']['destination-port-range']['upper-port']}}
-        </td>
-        <td data-title="'SFC_ACL_SHORT_IP_PROTOCOL' | translate" sortable="'valueOf()[\'ip-protocol-string\']'"
-            filter="{ 'ip-protocol-string': 'text' }">
-            {{entry['matches']['ip-protocol']}}
-        </td>
-        <td data-title="'SFC_ACL_SHORT_DSCP' | translate" sortable="'valueOf()[\'dscp-string\']'"
-            filter="{ 'dscp-string': 'text' }">
-            {{entry['matches']['dscp']}}
-        </td>
-        <td data-title="'SFC_ACL_ACTIONS' | translate">
-            <a ng-click="showMetadata(entry)">
-                <i class="icon-list-alt" style="cursor: pointer" popover-trigger="mouseenter"
-                   popover="{{ 'SFC_ACL_SHORT_METADATA' | translate }}"></i>
-            </a>
-            <a ng-click="deleteItem(entry)">
-                <i class="icon-remove" style="cursor: pointer" popover-trigger="mouseenter"
-                   popover="{{ 'SFC_ACL_DELETE' | translate }}"></i>
-            </a>
-            <a ng-click="editItem(entry)">
-                <i class="icon-edit" style="cursor: pointer" popover-trigger="mouseenter"
-                   popover="{{ 'SFC_ACL_EDIT' | translate }}"></i>
-            </a>
-        </td>
-    </tr>
-</table>
-
-<div ng-controller="sfcClassifierCtrl">
-    <a class="btn btn-info add-row" href="index.html#/sfc/classifier-create">
-        {{'SFC_CLASSIFIER_ADD' | translate}}
+    <a class="btn btn-info add-row" href="index.html#/sfc/acl-create">
+        {{'SFC_ACL_ADD' | translate}}
     </a>
 
     <button type="button" ng-click="tableParams.sorting({})" class="btn btn-default pull-right">{{'SFC_CLEAR_SORTING' |
 
     <table ng-table="tableParams" show-filter="true" class="footable table">
         <tr ng-repeat="entry in $data track by $index">
-            <td data-title="'SFC_CLASSIFIER_NAME' | translate" sortable="'valueOf()[\'name\']'"
-                filter="{ 'name': 'text' }">
-                {{entry['name']}}
+            <td data-title="'SFC_ACL_SHORT_NAME' | translate" sortable="'valueOf()[\'acl-name\']'"
+                filter="{ 'acl-name': 'text' }">
+                {{entry['acl-name']}}
             </td>
-            <td data-title="'SFC_ACL_NAME' | translate" sortable="'valueOf()[\'access-list\']'"
-                filter="{ 'access-list': 'text' }">
-                {{entry['access-list']}}
+            <td data-title="'SFC_ACL_SHORT_RULE_NAME' | translate" sortable="'valueOf()[\'rule-name\']'"
+                filter="{ 'rule-name': 'text' }">
+                {{entry['rule-name']}}
             </td>
-            <td data-title="'SFC_PATH' | translate" sortable="'valueOf()[\'service-function-path\']'"
-                filter="{ 'service-function-path': 'text' }">
-                {{entry['service-function-path']}}
+            <td data-title="'SFC_ACL_ACTIONS_SFP' | translate"
+                sortable="'valueOf()[\'actions\'][\'service-function-path\']'" filter="{ 'actions': 'text' }">
+                {{entry['actions']['service-function-path']}}
             </td>
-            <td data-title="'SFC_SERVICE_FORWARDERS' | translate"
-                sortable="'valueOf()[\'service-function-forwarder\'][\'name\']'"
-                filter="{ 'service-function-forwarder': 'text' }">
-           <span style="color: #1C94C4; cursor: pointer;" ng-repeat="sff in entry['service-function-forwarder']"
-                 tooltip-placement="bottom"
-                 tooltip-html-unsafe="
-                      <div style='text-align: left'>
-                      {{'SFC_CLASSIFIER_ATTACHMENT_POINT' | translate}}: <br/>
-                      {{getSffAttachmentPointTooltip(sff)}}
-                      </div>">
-                    {{sff['name']}}{{$last ? '' : ', '}}
+            <td data-title="'SFC_ACL_SHORT_SRC_IP_MAC_ADDRESS' | translate"
+                sortable="'valueOf()[\'source-ip-mac-mask-string\']'" filter="{ 'source-ip-mac-mask-string': 'text' }">
+                {{entry['matches']['source-ipv4-address']}}{{entry['matches']['source-ipv6-address']}}
+                {{entry['matches']['source-mac-address']}}
+                <span class="spanText" ng-if="entry['matches']['source-mac-address-mask']">
+                    <br/>({{entry['matches']['source-mac-address-mask']}})
                 </span>
             </td>
-
+            <td data-title="'SFC_ACL_SHORT_DST_IP_MAC_ADDRESS' | translate"
+                sortable="'valueOf()[\'destination-ip-mac-mask-string\']'"
+                filter="{ 'destination-ip-mac-mask-string': 'text' }">
+                {{entry['matches']['destination-ipv4-address']}}{{entry['matches']['destination-ipv6-address']}}
+                {{entry['matches']['destination-mac-address']}}
+                <span class="spanText" ng-if="entry['matches']['destination-mac-address-mask']">
+                    <br/>({{entry['matches']['destination-mac-address-mask']}})
+                </span>
+            </td>
+            <td data-title="'SFC_ACL_SHORT_IPV6_FLOW_LABEL' | translate" sortable="'valueOf()[\'flow-label-string\']'"
+                filter="{ 'flow-label-string': 'text' }">
+                {{entry['matches']['flow-label']}}
+            </td>
+            <td data-title="'SFC_ACL_SHORT_SRC_PORT_RANGE' | translate"
+                sortable="'valueOf()[\'source-port-range-string\']'"
+                filter="{ 'source-port-range-string': 'text' }">
+                {{entry['matches']['source-port-range']['lower-port']}}-{{entry['matches']['source-port-range']['upper-port']}}
+            </td>
+            <td data-title="'SFC_ACL_SHORT_DST_PORT_RANGE' | translate"
+                sortable="'valueOf()[\'destination-port-range-string\']'"
+                filter="{ 'destination-port-range-string': 'text' }">
+                {{entry['matches']['destination-port-range']['lower-port']}}-{{entry['matches']['destination-port-range']['upper-port']}}
+            </td>
+            <td data-title="'SFC_ACL_SHORT_IP_PROTOCOL' | translate" sortable="'valueOf()[\'ip-protocol-string\']'"
+                filter="{ 'ip-protocol-string': 'text' }">
+                {{entry['matches']['ip-protocol']}}
+            </td>
+            <td data-title="'SFC_ACL_SHORT_DSCP' | translate" sortable="'valueOf()[\'dscp-string\']'"
+                filter="{ 'dscp-string': 'text' }">
+                {{entry['matches']['dscp']}}
+            </td>
             <td data-title="'SFC_ACL_ACTIONS' | translate">
+                <a ng-click="showMetadata(entry)">
+                    <i class="icon-list-alt" style="cursor: pointer" popover-trigger="mouseenter"
+                       popover="{{ 'SFC_ACL_SHORT_METADATA' | translate }}"></i>
+                </a>
                 <a ng-click="deleteItem(entry)">
                     <i class="icon-remove" style="cursor: pointer" popover-trigger="mouseenter"
-                       popover="{{ 'SFC_CLASSIFIER_DELETE' | translate }}"></i>
+                       popover="{{ 'SFC_ACL_DELETE' | translate }}"></i>
                 </a>
                 <a ng-click="editItem(entry)">
                     <i class="icon-edit" style="cursor: pointer" popover-trigger="mouseenter"
-                       popover="{{ 'SFC_CLASSIFIER_EDIT' | translate }}"></i>
+                       popover="{{ 'SFC_ACL_EDIT' | translate }}"></i>
                 </a>
             </td>
         </tr>
     </table>
+
+    <div ng-controller="sfcClassifierCtrl">
+        <a class="btn btn-info add-row" href="index.html#/sfc/classifier-create">
+            {{'SFC_CLASSIFIER_ADD' | translate}}
+        </a>
+
+        <button type="button" ng-click="tableParams.sorting({})" class="btn btn-default pull-right">
+            {{'SFC_CLEAR_SORTING' |
+            translate}}
+        </button>
+
+        <table ng-table="tableParams" show-filter="true" class="footable table">
+            <tr ng-repeat="entry in $data track by $index">
+                <td data-title="'SFC_CLASSIFIER_NAME' | translate" sortable="'valueOf()[\'name\']'"
+                    filter="{ 'name': 'text' }">
+                    {{entry['name']}}
+                </td>
+                <td data-title="'SFC_ACL_NAME' | translate" sortable="'valueOf()[\'access-list\']'"
+                    filter="{ 'access-list': 'text' }">
+                    {{entry['access-list']}}
+                </td>
+            <td data-title="'SFC_PATH' | translate" sortable="'valueOf()[\'service-function-path\']'"
+                filter="{ 'service-function-path': 'text' }">
+                {{entry['service-function-path']}}
+                </td>
+                <td data-title="'SFC_SERVICE_FORWARDERS' | translate"
+                    sortable="'valueOf()[\'service-function-forwarder\'][\'name\']'"
+                    filter="{ 'service-function-forwarder': 'text' }">
+           <span style="color: #1C94C4; cursor: pointer;" ng-repeat="sff in entry['service-function-forwarder']"
+                 tooltip-placement="bottom"
+                 tooltip-html-unsafe="
+                      <div style='text-align: left'>
+                      {{'SFC_CLASSIFIER_ATTACHMENT_POINT' | translate}}: <br/>
+                      {{getSffAttachmentPointTooltip(sff)}}
+                      </div>">
+                    {{sff['name']}}{{$last ? '' : ', '}}
+                </span>
+                </td>
+
+                <td data-title="'SFC_ACL_ACTIONS' | translate">
+                    <a ng-click="deleteItem(entry)">
+                        <i class="icon-remove" style="cursor: pointer" popover-trigger="mouseenter"
+                           popover="{{ 'SFC_CLASSIFIER_DELETE' | translate }}"></i>
+                    </a>
+                    <a ng-click="editItem(entry)">
+                        <i class="icon-edit" style="cursor: pointer" popover-trigger="mouseenter"
+                           popover="{{ 'SFC_CLASSIFIER_EDIT' | translate }}"></i>
+                    </a>
+                </td>
+            </tr>
+        </table>
+    </div>
 </div>
\ No newline at end of file
index 9d16ad10d3afabc758e24c4f81cf56dcb34814a0..9fe31898671157b2bab2e5512b845efb12c2c9fd 100755 (executable)
@@ -1,12 +1,13 @@
 define(['app/sfc/sfc.module'], function (sfc) {
 
-  sfc.register.controller('configCtrl', function ($scope, SfcConfigSvc, SfcFileReaderSvc, SfcRestangularSvc, SfcConfigExportSvc, SfcRestconfError) {
+  sfc.register.controller('configCtrl', function ($scope, SfcConfigSvc, SfcFileReaderSvc, SfcRestangularSvc, SfcConfigExportSvc, SfcRestconfError, $localStorage) {
 
 
     $scope.validationRevision = SfcConfigSvc.getValidationRevision();
     $scope.validateBefore = false;
     $scope.fileContent = "";
-    $scope.restangularBaseUrl = SfcRestangularSvc.getCurrentBaseUrl();
+
+    $scope.$storage = $localStorage;
 
     $scope.getOnFileSelect = function (file) {
       SfcFileReaderSvc.readAsText(file, $scope)
@@ -48,12 +49,13 @@ define(['app/sfc/sfc.module'], function (sfc) {
 
     $scope.applyBaseUrl = function () {
       try {
-        SfcRestangularSvc.changeBaseUrl($scope.restangularBaseUrl);
-        alert('url set to: ' + $scope.restangularBaseUrl);
+        SfcRestangularSvc.changeBaseUrl($scope.$storage.restangularBaseUrl);
+        alert('url set to: ' + $scope.$storage.restangularBaseUrl);
       } catch (e) {
         alert(e.message);
       }
     };
+
   });
 
 });
\ No newline at end of file
index 14e08c1bc015f4ed00818be8ebc6979b4707e00a..9fe973b543a8217e9ff1c2125d9d224a129d4d25 100755 (executable)
@@ -1,28 +1,39 @@
-<div class="container col-md-8">
-    <form role="form" name="jsonConfigForm">
-        <div class="form-group">
-            <label for="config_content">{{'SFC_CONFIG_JSON_CONTENT' | translate}}</label>
-            <textarea id="config_content" style="width: 100%;" rows="20" wrap="soft" ng-model="fileContent"></textarea>
-            <button type="button" class="btn btn-primary" ng-click="applyConfig()">{{'SFC_CONFIG_APPLY' | translate}}</button>
-            <button type="button" class="btn btn-primary" ng-click="exportConfig()">{{'SFC_CONFIG_EXPORT' | translate}}</button>
-            <span style="display: inline-block; width: 10px;"></span>
-            <input type="checkbox" id="validateBefore" ng-model="validateBefore" class="ng-valid ng-dirty">
-            <label for="validateBefore">Validate to {{validationRevision}} before apply</label>
-        </div>
-    </form>
+<div class="col-xs-12" style="padding: 0px">
+    <div class="container col-xs-12 col-md-12 col-lg-8">
+        <form role="form" name="jsonConfigForm">
+            <div class="form-group">
+                <label for="config_content">{{'SFC_CONFIG_JSON_CONTENT' | translate}}</label>
+                <textarea id="config_content" style="width: 100%;" rows="20" wrap="soft"
+                          ng-model="fileContent"></textarea>
+                <button type="button" class="btn btn-primary" ng-click="applyConfig()">{{'SFC_CONFIG_APPLY' |
+                    translate}}
+                </button>
+                <button type="button" class="btn btn-primary" ng-click="exportConfig()">{{'SFC_CONFIG_EXPORT' |
+                    translate}}
+                </button>
+                <span style="display: inline-block; width: 10px;"></span>
+                <input type="checkbox" id="validateBefore" ng-model="validateBefore" class="ng-valid ng-dirty">
+                <label for="validateBefore">Validate to {{validationRevision}} before apply</label>
+            </div>
+        </form>
 
-    <form role="form" name="jsonLoadForm">
-        <div class="form-group">
-            <label for="select_file">{{'SFC_CONFIG_FILE' | translate}}</label>
-            <input id="select_file" type="file" class="form-control input-sm" ng-file-select="onFileSelect($files)"/>
-        </div>
-    </form>
+        <form role="form" name="jsonLoadForm">
+            <div class="form-group">
+                <label for="select_file">{{'SFC_CONFIG_FILE' | translate}}</label>
+                <input id="select_file" type="file" class="form-control input-sm"
+                       ng-file-select="onFileSelect($files)"/>
+            </div>
+        </form>
 
-    <form role="form" name="jsonBaseUrlForm">
-        <div class="form-group">
-            <label for="rest_url">{{'SFC_RESTCONF_URL' | translate}}</label>
-            <input id="rest_url" type="text" class="form-control input-sm" ng-model="restangularBaseUrl" ng-required="true"/>
-            <button type="submit" class="btn btn-primary" ng-click="applyBaseUrl()">{{'SFC_CONFIG_APPLY' | translate}}</button>
-        </div>
-    </form>
+        <form role="form" name="jsonBaseUrlForm">
+            <div class="form-group">
+                <label for="rest_url">{{'SFC_RESTCONF_URL' | translate}}</label>
+                <input id="rest_url" type="text" class="form-control input-sm" ng-model="$storage.restangularBaseUrl"
+                       ng-required="true"/>
+                <button type="submit" class="btn btn-primary" ng-click="applyBaseUrl()">{{'SFC_CONFIG_APPLY' |
+                    translate}}
+                </button>
+            </div>
+        </form>
+    </div>
 </div>
\ No newline at end of file
index c05b5edb4666b46323b3724aa93e2f0cf7564321..5fe857775a40ca76070b330e8c315b5708a4ae8f 100644 (file)
@@ -1,72 +1,84 @@
-<a class="btn btn-info add-row" href="index.html#/sfc/metadata-context-create">
-    {{'SFC_METADATA_CONTEXT_ADD' | translate}}
-</a>
-<a class="btn btn-info add-row" href="index.html#/sfc/metadata-variable-create">
-    {{'SFC_METADATA_VARIABLE_ADD' | translate}}
-</a>
+<div class="col-xs-12" style="padding: 0px">
+    <a class="btn btn-info add-row" href="index.html#/sfc/metadata-context-create">
+        {{'SFC_METADATA_CONTEXT_ADD' | translate}}
+    </a>
+    <a class="btn btn-info add-row" href="index.html#/sfc/metadata-variable-create">
+        {{'SFC_METADATA_VARIABLE_ADD' | translate}}
+    </a>
 
-<button type="button" ng-click="tableParamsContext.sorting({}); tableParamsVariable.sorting({})" class="btn btn-default pull-right">{{'SFC_CLEAR_SORTING' | translate}}
-</button>
+    <button type="button" ng-click="tableParamsContext.sorting({}); tableParamsVariable.sorting({})"
+            class="btn btn-default pull-right">{{'SFC_CLEAR_SORTING' | translate}}
+    </button>
 
-<table ng-table="tableParamsContext" show-filter="true" class="footable table">
-    <tr ng-repeat="entry in $data track by $index">
-        <td data-title="'SFC_METADATA_CONTEXT_NAME' | translate" sortable="'name'" filter="{ 'name': 'text' }">
-            {{entry['name']}}
-        </td>
-        <td data-title="'SFC_METADATA_CONTEXT_HEADER1' | translate" sortable="'valueOf([\'context-header1\'])'" filter="{ 'context-header1': 'text' }">
-            {{decimalToHex(entry['context-header1'])}}
-        </td>
-        <td data-title="'SFC_METADATA_CONTEXT_HEADER2' | translate" sortable="'valueOf([\'context-header2\'])'" filter="{ 'context-header2': 'text' }">
-            {{decimalToHex(entry['context-header2'])}}
-        </td>
-        <td data-title="'SFC_METADATA_CONTEXT_HEADER3' | translate" sortable="'valueOf([\'context-header3\'])'" filter="{ 'context-header3': 'text' }">
-            {{decimalToHex(entry['context-header3'])}}
-        </td>
-        <td data-title="'SFC_METADATA_CONTEXT_HEADER4' | translate" sortable="'valueOf([\'context-header4\'])'" filter="{ 'context-header4': 'text' }">
-            {{decimalToHex(entry['context-header4'])}}
-        </td>
-        <td data-title="'SFC_METADATA_ACTIONS' | translate">
-            <a ng-click="deleteContextItem(entry)">
-                <i class="icon-remove" style="cursor: pointer" popover-trigger="mouseenter"
-                   popover="{{ 'SFC_METADATA_DELETE' | translate }}"></i>
-            </a>
-            <a ng-click="editContextItem(entry)">
-                <i class="icon-edit" style="cursor: pointer" popover-trigger="mouseenter"
-                   popover="{{ 'SFC_METADATA_EDIT' | translate }}"></i>
-            </a>
-        </td>
-    </tr>
-</table>
+    <table ng-table="tableParamsContext" show-filter="true" class="footable table">
+        <tr ng-repeat="entry in $data track by $index">
+            <td data-title="'SFC_METADATA_CONTEXT_NAME' | translate" sortable="'name'" filter="{ 'name': 'text' }">
+                {{entry['name']}}
+            </td>
+            <td data-title="'SFC_METADATA_CONTEXT_HEADER1' | translate" sortable="'valueOf([\'context-header1\'])'"
+                filter="{ 'context-header1': 'text' }">
+                {{decimalToHex(entry['context-header1'])}}
+            </td>
+            <td data-title="'SFC_METADATA_CONTEXT_HEADER2' | translate" sortable="'valueOf([\'context-header2\'])'"
+                filter="{ 'context-header2': 'text' }">
+                {{decimalToHex(entry['context-header2'])}}
+            </td>
+            <td data-title="'SFC_METADATA_CONTEXT_HEADER3' | translate" sortable="'valueOf([\'context-header3\'])'"
+                filter="{ 'context-header3': 'text' }">
+                {{decimalToHex(entry['context-header3'])}}
+            </td>
+            <td data-title="'SFC_METADATA_CONTEXT_HEADER4' | translate" sortable="'valueOf([\'context-header4\'])'"
+                filter="{ 'context-header4': 'text' }">
+                {{decimalToHex(entry['context-header4'])}}
+            </td>
+            <td data-title="'SFC_METADATA_ACTIONS' | translate">
+                <a ng-click="deleteContextItem(entry)">
+                    <i class="icon-remove" style="cursor: pointer" popover-trigger="mouseenter"
+                       popover="{{ 'SFC_METADATA_DELETE' | translate }}"></i>
+                </a>
+                <a ng-click="editContextItem(entry)">
+                    <i class="icon-edit" style="cursor: pointer" popover-trigger="mouseenter"
+                       popover="{{ 'SFC_METADATA_EDIT' | translate }}"></i>
+                </a>
+            </td>
+        </tr>
+    </table>
 
-<table ng-table="tableParamsVariable" show-filter="true" class="footable table">
-    <tr ng-repeat="entry in $data track by $index">
-        <td data-title="'SFC_METADATA_VARIABLE_NAME' | translate" sortable="'name'" filter="{ 'name': 'text' }">
-            {{entry['name']}}
-        </td>
-        <td data-title="'SFC_METADATA_VARIABLE_TLV_CLASS' | translate" sortable="'valueOf([\'tlv-class\'])'" filter="{ 'tlv-class': 'text' }">
-            {{decimalToHex(entry['tlv-class'])}}
-        </td>
-        <td data-title="'SFC_METADATA_VARIABLE_TLV_TYPE' | translate" sortable="'valueOf([\'tlv-type\'])'" filter="{ 'tlv-type': 'text' }">
-            {{decimalToHex(entry['tlv-type'])}}
-        </td>
-        <td data-title="'SFC_METADATA_VARIABLE_FLAGS' | translate" sortable="'valueOf([\'flags\'])'" filter="{ 'flags': 'text' }">
-            {{entry['flags']}}
-        </td>
-        <td data-title="'SFC_METADATA_VARIABLE_LENGTH' | translate" sortable="'valueOf([\'length\'])'" filter="{ 'length': 'text' }">
-            {{entry['length']}}
-        </td>
-        <td data-title="'SFC_METADATA_VARIABLE_DATA' | translate" sortable="'valueOf([\'tlv-data\'])'" filter="{ 'tlv-data': 'text' }">
-            {{entry['tlv-data']}}
-        </td>
-        <td data-title="'SFC_METADATA_ACTIONS' | translate">
-            <a ng-click="deleteVariableItem(entry)">
-                <i class="icon-remove" style="cursor: pointer" popover-trigger="mouseenter"
-                   popover="{{ 'SFC_METADATA_DELETE' | translate }}"></i>
-            </a>
-            <a ng-click="editVariableItem(entry)">
-                <i class="icon-edit" style="cursor: pointer" popover-trigger="mouseenter"
-                   popover="{{ 'SFC_METADATA_EDIT' | translate }}"></i>
-            </a>
-        </td>
-    </tr>
-</table>
\ No newline at end of file
+    <table ng-table="tableParamsVariable" show-filter="true" class="footable table">
+        <tr ng-repeat="entry in $data track by $index">
+            <td data-title="'SFC_METADATA_VARIABLE_NAME' | translate" sortable="'name'" filter="{ 'name': 'text' }">
+                {{entry['name']}}
+            </td>
+            <td data-title="'SFC_METADATA_VARIABLE_TLV_CLASS' | translate" sortable="'valueOf([\'tlv-class\'])'"
+                filter="{ 'tlv-class': 'text' }">
+                {{decimalToHex(entry['tlv-class'])}}
+            </td>
+            <td data-title="'SFC_METADATA_VARIABLE_TLV_TYPE' | translate" sortable="'valueOf([\'tlv-type\'])'"
+                filter="{ 'tlv-type': 'text' }">
+                {{decimalToHex(entry['tlv-type'])}}
+            </td>
+            <td data-title="'SFC_METADATA_VARIABLE_FLAGS' | translate" sortable="'valueOf([\'flags\'])'"
+                filter="{ 'flags': 'text' }">
+                {{entry['flags']}}
+            </td>
+            <td data-title="'SFC_METADATA_VARIABLE_LENGTH' | translate" sortable="'valueOf([\'length\'])'"
+                filter="{ 'length': 'text' }">
+                {{entry['length']}}
+            </td>
+            <td data-title="'SFC_METADATA_VARIABLE_DATA' | translate" sortable="'valueOf([\'tlv-data\'])'"
+                filter="{ 'tlv-data': 'text' }">
+                {{entry['tlv-data']}}
+            </td>
+            <td data-title="'SFC_METADATA_ACTIONS' | translate">
+                <a ng-click="deleteVariableItem(entry)">
+                    <i class="icon-remove" style="cursor: pointer" popover-trigger="mouseenter"
+                       popover="{{ 'SFC_METADATA_DELETE' | translate }}"></i>
+                </a>
+                <a ng-click="editVariableItem(entry)">
+                    <i class="icon-edit" style="cursor: pointer" popover-trigger="mouseenter"
+                       popover="{{ 'SFC_METADATA_EDIT' | translate }}"></i>
+                </a>
+            </td>
+        </tr>
+    </table>
+</div>
\ No newline at end of file
index e03eabfb30bd34152cf14899ecc59b9c99c4c120..f979675ef6429d46cb8f5cb258d6004b80235fec 100755 (executable)
@@ -9,6 +9,7 @@
         <li ng-class="{ active: isState('main.sfc.acl') || isState ('main.sfc.acl-create') || isState ('main.sfc.classifier-create') }"><a href="#/sfc/acl">{{ 'SFC_ACCESS_LISTS' | translate }}</a></li>
         <li ng-class="{ active: isState('main.sfc.metadata') || isState ('main.sfc.metadata-create') }"><a href="#/sfc/metadata">{{ 'SFC_METADATA' | translate }}</a></li>
         <li ng-class="{ active: isState('main.sfc.config') }"><a href="#/sfc/config">{{ 'SFC_CONFIG' | translate }}</a></li>
+        <li ng-class="{ active: isState('main.sfc.system') }"><a href="#/sfc/system">{{ 'SFC_SYSTEM' | translate }}</a></li>
     </ul>
 
     <!-- For child state use-->
index bebf3bdc9d2eb8e1655a4e945f75fce169d3cc24..bc2cbbe8a83f34ae3b823ff05c4fb1b42cae4838 100755 (executable)
@@ -1,36 +1,39 @@
-<div class="col-md-2" style="padding-left: 0px">
-    <a style="width: 100%" class="btn btn-info add-row" href="index.html#/sfc/servicefunction-create">
-        {{'SFC_FUNCTION_ADD' | translate}}
-    </a>
-    <table ng-table="tableParamsSfType" class="footable table">
-        <!--<tr ng-hide="sfs.length">-->
-        <!--<td colspan="3" class="centerAlign">{{'NO_DATA_FOUND' | translate}}</td>-->
-        <!--</tr>-->
-        <tr ng-repeat="item in $data | unique:'type' track by $index " ng-model="items"
-            ui-draggable="true" drag="item" class="draggable">
-            <td data-title="'SFC_FUNCTION_TYPE' | translate" sortable="'type'">
-                {{item.type}}
-            </td>
-        </tr>
-    </table>
-</div>
+<div class="col-xs-12" style="padding: 0px">
+    <div class="col-md-2" style="padding-left: 0px">
+        <a style="width: 100%" class="btn btn-info add-row" href="index.html#/sfc/servicefunction-create">
+            {{'SFC_FUNCTION_ADD' | translate}}
+        </a>
+        <table ng-table="tableParamsSfType" class="footable table">
+            <!--<tr ng-hide="sfs.length">-->
+            <!--<td colspan="3" class="centerAlign">{{'NO_DATA_FOUND' | translate}}</td>-->
+            <!--</tr>-->
+            <tr ng-repeat="item in $data | unique:'type' track by $index " ng-model="items"
+                ui-draggable="true" drag="item" class="draggable">
+                <td data-title="'SFC_FUNCTION_TYPE' | translate" sortable="'type'">
+                    {{item.type}}
+                </td>
+            </tr>
+        </table>
+    </div>
 
-<div class="col-md-10" style="padding-right: 0px">
-    <a class="btn btn-info add-row" href="index.html#/sfc/servicechain-create">
-        {{'SFC_CHAIN_ADD' | translate}}
-    </a>
+    <div class="col-md-10" style="padding-right: 0px">
+        <a class="btn btn-info add-row" href="index.html#/sfc/servicechain-create">
+            {{'SFC_CHAIN_ADD' | translate}}
+        </a>
 
-    <button type="button" ng-click="tableParams.sorting({}); tableParamsSfType.sorting({});" class="btn btn-default pull-right">{{'SFC_CLEAR_SORTING' | translate}}</button>
+        <button type="button" ng-click="tableParams.sorting({}); tableParamsSfType.sorting({});"
+                class="btn btn-default pull-right">{{'SFC_CLEAR_SORTING' | translate}}
+        </button>
 
-    <table ng-table="tableParams" class="footable table">
-        <!--<tr ng-hide="sfcs.length">-->
-        <!--<td colspan="1" class="centerAlign">{{'NO_DATA_FOUND' | translate}}</td>-->
-        <!--</tr>-->
-        <tr ng-repeat="sfc in $data track by $index" id="{{sfc.name}}~!~{{$index}}">
-            <td data-title="'SFC_CHAIN' | translate" sortable="'name'" ui-on-Drop="onSFCdrop($data, sfc)"
-                ng-class="getSFCstate(sfc)" effect-me="sfcEffectMe[sfc.name]">
-                <p>
-                    <span class="spanText"><b>{{sfc.name}}</b></span>
+        <table ng-table="tableParams" class="footable table">
+            <!--<tr ng-hide="sfcs.length">-->
+            <!--<td colspan="1" class="centerAlign">{{'NO_DATA_FOUND' | translate}}</td>-->
+            <!--</tr>-->
+            <tr ng-repeat="sfc in $data track by $index" id="{{sfc.name}}~!~{{$index}}">
+                <td data-title="'SFC_CHAIN' | translate" sortable="'name'" ui-on-Drop="onSFCdrop($data, sfc)"
+                    ng-class="getSFCstate(sfc)" effect-me="sfcEffectMe[sfc.name]">
+                    <p>
+                        <span class="spanText"><b>{{sfc.name}}</b></span>
                     <span ng-show="isSFCstate(sfc, sfcState.NEW)">
                         <a>
                             <i class="icon-undo" style="cursor: pointer" ng-click="undoSFCnew(sfc)"
                     </span>
                     <span class="spanText"
                           ng-show="isSFCstate(sfc, sfcState.NEW)">({{'SFC_CHAIN_NEW' | translate}})</span>
-                    <span class="spanText" ng-show="isSFCstate(sfc, sfcState.EDITED)">({{'SFC_CHAIN_EDITED' | translate}})</span>
+                        <span class="spanText" ng-show="isSFCstate(sfc, sfcState.EDITED)">({{'SFC_CHAIN_EDITED' | translate}})</span>
 
                     <span class="spanText pull-right">
                         {{'SFC_CHAIN_SYMMETRIC' | translate}}
-                        <input type="checkbox" ng-model="sfc.symmetric" ng-checked="sfc.symmetric" id="symmetricSFC" ng-change="setSFCstate(sfc, sfcState.EDITED)">
+                        <input type="checkbox" ng-model="sfc.symmetric" ng-checked="sfc.symmetric" id="symmetricSFC"
+                               ng-change="setSFCstate(sfc, sfcState.EDITED)">
                     </span>
-                </p>
-
-                <div class="sfc-sf-component"
-                     style="width: 18px;">
-                    <div style="width: 100%; height: 64px;">
-                        <div class="arrow-left-part"></div>
-                    </div>
-                </div>
-
-                <div class="connected-apps-container dropcontainer"
-                     ui-sortable="sortableOptions"
-                     ng-model="sfc['sfc-service-function']">
+                    </p>
 
                     <div class="sfc-sf-component"
-                         style="width: 104px;"
-                         ng-repeat="s in sfc['sfc-service-function'] track by $index">
+                         style="width: 18px;">
                         <div style="width: 100%; height: 64px;">
-                            <div class="arrow-right-part"></div>
-                            <div class="obr-box sf">
-                                <i class="icon-remove"
-                                   style="cursor: pointer; position: relative; top: 0px; left: 60px;"
-                                   ng-click="removeSFfromSFC(sfc, $index)" popover-trigger="mouseenter"
-                                   popover="{{ 'SFC_FUNCTION_DELETE' | translate }}">
-                                </i>
-                            </div>
                             <div class="arrow-left-part"></div>
                         </div>
-                        <div style="width: 100%; height: 36px; text-align: center;">
-                            <div style="display: inline-block;">
+                    </div>
+
+                    <div class="connected-apps-container dropcontainer"
+                         ui-sortable="sortableOptions"
+                         ng-model="sfc['sfc-service-function']">
+
+                        <div class="sfc-sf-component"
+                             style="width: 104px;"
+                             ng-repeat="s in sfc['sfc-service-function'] track by $index">
+                            <div style="width: 100%; height: 64px;">
+                                <div class="arrow-right-part"></div>
+                                <div class="obr-box sf">
+                                    <i class="icon-remove"
+                                       style="cursor: pointer; position: relative; top: 0px; left: 60px;"
+                                       ng-click="removeSFfromSFC(sfc, $index)" popover-trigger="mouseenter"
+                                       popover="{{ 'SFC_FUNCTION_DELETE' | translate }}">
+                                    </i>
+                                </div>
+                                <div class="arrow-left-part"></div>
+                            </div>
+                            <div style="width: 100%; height: 36px; text-align: center;">
+                                <div style="display: inline-block;">
                                 <span style="cursor: pointer;" easy-editable-textarea="s.name"
                                       buttons="no" e-required onaftersave="setSFCstate(sfc, sfcState.EDITED)"
                                       popover-trigger="mouseenter"
                                       popover="{{ 'SFC_FUNCTION_RENAME' | translate }}"
                                       popover-placement="bottom">{{s.name || 'error'}}
                                 </span>
+                                </div>
                             </div>
                         </div>
                     </div>
-                </div>
 
-                <div class="sfc-sf-component"
-                     style="width: 22px;">
-                    <div style="width: 100%; height: 64px;">
-                        <div class="arrow-right-part"></div>
+                    <div class="sfc-sf-component"
+                         style="width: 22px;">
+                        <div style="width: 100%; height: 64px;">
+                            <div class="arrow-right-part"></div>
+                        </div>
                     </div>
-                </div>
-            </td>
-        </tr>
-    </table>
+                </td>
+            </tr>
+        </table>
+    </div>
 </div>
\ No newline at end of file
index 6e4f3139c5811ff0bdc091ed0367c7be23e71568..fb18ab568d98fbaf056f5e542f02767f99c711e1 100755 (executable)
@@ -1,27 +1,37 @@
-<a class="btn btn-info add-row" href="index.html#/sfc/serviceforwarder-create">
-    {{'SFC_FORWARDER_ADD' | translate}}
-</a>
+<div class="col-xs-12" style="padding: 0px">
 
-<button type="button" ng-click="tableParams.sorting({})" class="btn btn-default pull-right">{{'SFC_CLEAR_SORTING' | translate}}</button>
+    <a class="btn btn-info add-row" href="index.html#/sfc/serviceforwarder-create">
+        {{'SFC_FORWARDER_ADD' | translate}}
+    </a>
 
-<table ng-table="tableParams" show-filter="true" class="footable table">
-    <tr ng-repeat="sff in $data track by $index | filter:search" ng-model="sffs">
-        <td data-title="'SFC_FORWARDER_NAME' | translate" sortable="'name'" filter="{ 'name': 'text' }">
-            {{sff['name']}}
-        </td>
-        <td data-title="'SFC_FORWARDER_SHORT_IP_MGMT_ADDRESS' | translate" sortable="'valueOf()[\'ip-mgmt-address\']'" filter="{ 'ip-mgmt-address': 'text' }">
-            {{sff['ip-mgmt-address']}}
-        </td>
-        <td data-title="'SFC_FORWARDER_SHORT_REST_URI' | translate" sortable="'valueOf()[\'rest-uri\']'" filter="{ 'rest-uri': 'text' }">
-            {{sff['rest-uri']}}
-        </td>
-        <td data-title="'SFC_FORWARDER_SERVICE_NODE' | translate" sortable="'valueOf()[\'service-node\']'" filter="{ 'service-node': 'text' }">
-            {{sff['service-node']}}
-        </td>
-        <td data-title="'SFC_FORWARDER_CLASSIFIER' | translate" sortable="'classifier'" filter="{ 'classifier': 'text' }">
-            {{sff['classifier']}}
-        </td>
-        <td data-title="'SFC_FUNCTION_DATA_PLANE_LOCATOR' | translate" sortable="'valueOf()[\'sff-data-plane-locator-string\']'" filter = "{ 'sff-data-plane-locator-string': 'text' }">
+    <button type="button" ng-click="tableParams.sorting({})" class="btn btn-default pull-right">{{'SFC_CLEAR_SORTING' |
+        translate}}
+    </button>
+
+    <table ng-table="tableParams" show-filter="true" class="footable table">
+        <tr ng-repeat="sff in $data track by $index | filter:search" ng-model="sffs">
+            <td data-title="'SFC_FORWARDER_NAME' | translate" sortable="'name'" filter="{ 'name': 'text' }">
+                {{sff['name']}}
+            </td>
+            <td data-title="'SFC_FORWARDER_SHORT_IP_MGMT_ADDRESS' | translate"
+                sortable="'valueOf()[\'ip-mgmt-address\']'" filter="{ 'ip-mgmt-address': 'text' }">
+                {{sff['ip-mgmt-address']}}
+            </td>
+            <td data-title="'SFC_FORWARDER_SHORT_REST_URI' | translate" sortable="'valueOf()[\'rest-uri\']'"
+                filter="{ 'rest-uri': 'text' }">
+                {{sff['rest-uri']}}
+            </td>
+            <td data-title="'SFC_FORWARDER_SERVICE_NODE' | translate" sortable="'valueOf()[\'service-node\']'"
+                filter="{ 'service-node': 'text' }">
+                {{sff['service-node']}}
+            </td>
+            <td data-title="'SFC_FORWARDER_CLASSIFIER' | translate" sortable="'classifier'"
+                filter="{ 'classifier': 'text' }">
+                {{sff['classifier']}}
+            </td>
+            <td data-title="'SFC_FUNCTION_DATA_PLANE_LOCATOR' | translate"
+                sortable="'valueOf()[\'sff-data-plane-locator-string\']'"
+                filter="{ 'sff-data-plane-locator-string': 'text' }">
                 <span style="color: #1C94C4; cursor: pointer;" ng-repeat="loc in sff['sff-data-plane-locator']"
                       tooltip-placement="bottom"
                       tooltip-html-unsafe="
 
                     {{loc['name']}}{{$last ? '' : ', '}}
                 </span>
-        </td>
-        <td data-title="'SFC_FORWARDER_SF_DICTIONARY' | translate" sortable="'valueOf()[\'service-function-dictionary-string\']'" filter = "{ 'service-function-dictionary-string': 'text' }">
+            </td>
+            <td data-title="'SFC_FORWARDER_SF_DICTIONARY' | translate"
+                sortable="'valueOf()[\'service-function-dictionary-string\']'"
+                filter="{ 'service-function-dictionary-string': 'text' }">
                 <span style="color: #1C94C4; cursor: pointer;" ng-repeat="sf in sff['service-function-dictionary']"
                       tooltip-placement="bottom"
                       tooltip-html-unsafe="
 
                     {{sf['name']}}{{$last ? '' : ', '}}
                 </span>
-        </td>
-        <td data-title="'SFC_FORWARDER_ACTIONS' | translate">
-            <a ng-click="deleteSFF(sff)">
-                <i class="icon-remove" style="cursor: pointer" popover-trigger="mouseenter"
-                   popover="{{ 'SFC_FORWARDER_DELETE' | translate }}"></i>
-            </a>
-            <a ng-click="editSFF(sff.name)">
-                <i class="icon-edit" style="cursor: pointer" popover-trigger="mouseenter"
-                   popover="{{ 'SFC_FORWARDER_EDIT' | translate }}"></i>
-            </a>
-        </td>
-    </tr>
-</table>
\ No newline at end of file
+            </td>
+            <td data-title="'SFC_FORWARDER_ACTIONS' | translate">
+                <a ng-click="deleteSFF(sff)">
+                    <i class="icon-remove" style="cursor: pointer" popover-trigger="mouseenter"
+                       popover="{{ 'SFC_FORWARDER_DELETE' | translate }}"></i>
+                </a>
+                <a ng-click="editSFF(sff.name)">
+                    <i class="icon-edit" style="cursor: pointer" popover-trigger="mouseenter"
+                       popover="{{ 'SFC_FORWARDER_EDIT' | translate }}"></i>
+                </a>
+            </td>
+        </tr>
+    </table>
+</div>
\ No newline at end of file
index cc54d616df0df99361d1cd69f68ad3b5cb6c54d5..c106db9d0d99e84c0322770b7e064d6ba7c0e2d0 100755 (executable)
@@ -34,7 +34,7 @@ define(['app/sfc/sfc.module'], function (sfc) {
         });
     });
 
-    $scope.getSfLocatorTooltipText = function(locator) {
+    $scope.getSfLocatorTooltipText = function (locator) {
       return ServiceLocatorHelper.getSfLocatorTooltipText(locator, $scope);
     };
 
@@ -70,7 +70,12 @@ define(['app/sfc/sfc.module'], function (sfc) {
     };
 
     $scope.editSF = function editSF(sfName) {
-      $state.transitionTo('main.sfc.servicefunction-edit', {sfName: sfName}, { location: true, inherit: true, relative: $state.$current, notify: true });
+      $state.transitionTo('main.sfc.servicefunction-edit', {sfName: sfName}, {
+        location: true,
+        inherit: true,
+        relative: $state.$current,
+        notify: true
+      });
     };
   });
 
@@ -81,7 +86,7 @@ define(['app/sfc/sfc.module'], function (sfc) {
     ServiceForwarderSvc.getArray(function (data) {
       $scope.sffs = data;
 
-      if(angular.isDefined($stateParams.sfName)){
+      if (angular.isDefined($stateParams.sfName)) {
         ServiceFunctionSvc.getItem($stateParams.sfName, function (item) {
           $scope.data = item;
           ServiceFunctionHelper.nshAwareToString($scope.data);
@@ -99,9 +104,63 @@ define(['app/sfc/sfc.module'], function (sfc) {
 
     $scope.submit = function () {
       ServiceFunctionSvc.putItem($scope.data, function () {
-        $state.transitionTo('main.sfc.servicefunction', null, { location: true, inherit: true, relative: $state.$current, notify: true });
+        $state.transitionTo('main.sfc.servicefunction', null, {
+          location: true,
+          inherit: true,
+          relative: $state.$current,
+          notify: true
+        });
       });
     };
   });
 
+  sfc.register.controller('serviceFunctionTypeCtrl', function ($scope, ServiceFunctionTypeSvc, ngTableParams, $filter) {
+
+    $scope.sfts = [];
+
+    var NgTableParams = ngTableParams;
+    $scope.tableParams = new NgTableParams({
+        page: 1,            // show first page
+        count: 10,          // count per page
+        sorting: {
+          'type': 'asc'     // initial sorting
+        }
+      },
+      {
+        total: $scope.sfts.length,
+        getData: function ($defer, params) {
+          // use build-in angular filter
+          var filteredData = params.filter() ?
+            $filter('filter')($scope.sfts, params.filter()) :
+            $scope.sfts;
+
+          var orderedData = params.sorting() ?
+            $filter('orderBy')(filteredData, params.orderBy()) :
+            filteredData;
+
+          params.total(orderedData.length);
+          $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
+        }
+      });
+
+    this.fetchData = function () {
+      $scope.sfts = [];
+      ServiceFunctionTypeSvc.getArray(function (data) {
+        //expand sf type into rows
+        _.each(data, function (sft) {
+          if (!_.isEmpty(sft['sft-service-function-name'])) {
+            _.each(sft['sft-service-function-name'], function (entry) {
+              entry['type'] = sft['type'];
+              $scope.sfts.push(entry);
+            });
+          }
+        });
+
+        $scope.tableParams.reload();
+      });
+    };
+
+    this.fetchData();
+  });
+
 });
\ No newline at end of file
index fef6e5fde0e1206b5ce7c25ee84e0ded055390b9..d2a123eda4cfe4893a67cba12ce7f2750db80792 100755 (executable)
@@ -1,28 +1,37 @@
-<a class="btn btn-info add-row" href="index.html#/sfc/servicefunction-create">
-    {{'SFC_FUNCTION_ADD' | translate}}
-</a>
+<div class="col-xs-12" style="padding: 0px">
+    <a class="btn btn-info add-row" href="index.html#/sfc/servicefunction-create" style="margin-bottom: 25px">
+        {{'SFC_FUNCTION_ADD' | translate}}
+    </a>
 
-<button type="button" ng-click="tableParams.sorting({})" class="btn btn-default pull-right">{{'SFC_CLEAR_SORTING' | translate}}
-</button>
+    <button type="button" ng-click="tableParams.sorting({})" class="btn btn-default pull-right">{{'SFC_CLEAR_SORTING' |
+        translate}}
+    </button>
 
-<table ng-table="tableParams" show-filter="true" class="footable table">
-    <!--<tr ng-hide="sfs.length">-->
-    <!--<td colspan="6" class="centerAlign">{{'NO_DATA_FOUND' | translate}}</td>-->
-    <!--</tr>-->
-    <tr ng-repeat="sf in $data track by $index" ng-model="sfs">
-        <td data-title="'SFC_FUNCTION_NAME' | translate" sortable="'name'" filter="{ 'name': 'text' }">
-            {{sf.name}}
-        </td>
-        <td data-title="'SFC_FUNCTION_TYPE' | translate" sortable="'type'" filter="{ 'type': 'select' }" filter-data="sfTypes()">
-            {{sf.type}}
-        </td>
-        <td data-title="'SFC_FUNCTION_IP' | translate" sortable="'valueOf()[\'ip-mgmt-address\']'" filter="{ 'ip-mgmt-address': 'text' }">
-            {{sf['ip-mgmt-address']}}
-        </td>
-        <td data-title="'SFC_FUNCTION_NSH_AWARE' | translate" sortable="'valueOf()[\'nsh-aware\']'" filter="{ 'nsh-aware': 'select' }" filter-data="sfNshAware()">
-            {{sf['nsh-aware']}}
-        </td>
-        <td data-title="'SFC_FUNCTION_DATA_PLANE_LOCATOR' | translate" sortable="'valueOf()[\'sf-data-plane-locator-string\']'" filter="{ 'sf-data-plane-locator-string' : 'text'}">
+    <tabset>
+        <tab heading="{{'SFC_SERVICE_FUNCTIONS' | translate}}">
+            <table ng-table="tableParams" show-filter="true" class="footable table" style="margin-top: 0px">
+                <!--<tr ng-hide="sfs.length">-->
+                <!--<td colspan="6" class="centerAlign">{{'NO_DATA_FOUND' | translate}}</td>-->
+                <!--</tr>-->
+                <tr ng-repeat="sf in $data track by $index" ng-model="sfs">
+                    <td data-title="'SFC_FUNCTION_NAME' | translate" sortable="'name'" filter="{ 'name': 'text' }">
+                        {{sf.name}}
+                    </td>
+                    <td data-title="'SFC_FUNCTION_TYPE' | translate" sortable="'type'" filter="{ 'type': 'select' }"
+                        filter-data="sfTypes()">
+                        {{sf.type}}
+                    </td>
+                    <td data-title="'SFC_FUNCTION_IP' | translate" sortable="'valueOf()[\'ip-mgmt-address\']'"
+                        filter="{ 'ip-mgmt-address': 'text' }">
+                        {{sf['ip-mgmt-address']}}
+                    </td>
+                    <td data-title="'SFC_FUNCTION_NSH_AWARE' | translate" sortable="'valueOf()[\'nsh-aware\']'"
+                        filter="{ 'nsh-aware': 'select' }" filter-data="sfNshAware()">
+                        {{sf['nsh-aware']}}
+                    </td>
+                    <td data-title="'SFC_FUNCTION_DATA_PLANE_LOCATOR' | translate"
+                        sortable="'valueOf()[\'sf-data-plane-locator-string\']'"
+                        filter="{ 'sf-data-plane-locator-string' : 'text'}">
             <span style="color: #1C94C4; cursor: pointer;" ng-repeat="loc in sf['sf-data-plane-locator']"
                   tooltip-placement="bottom"
                   tooltip-html-unsafe="
                       </div>">
                     {{loc['name']}}{{$last ? '' : ', '}}
                 </span></td>
-        <td data-title="'SFC_FUNCTION_ACTIONS' | translate">
-            <!--<a class="row-delete-sf" href="#">-->
-            <!--<i class="icon-edit"></i>-->
-            <!--</a>-->
-            <a ng-click="deleteSF(sf)">
-                <i class="icon-remove" style="cursor: pointer" popover-trigger="mouseenter"
-                   popover="{{ 'SFC_FUNCTION_DELETE' | translate }}"></i>
-            </a>
-            <a ng-click="editSF(sf.name)">
-                <i class="icon-edit" style="cursor: pointer" popover-trigger="mouseenter"
-                   popover="{{ 'SFC_FUNCTION_EDIT' | translate }}"></i>
-            </a>
-        </td>
-    </tr>
-</table>
\ No newline at end of file
+                    <td data-title="'SFC_FUNCTION_ACTIONS' | translate">
+                        <!--<a class="row-delete-sf" href="#">-->
+                        <!--<i class="icon-edit"></i>-->
+                        <!--</a>-->
+                        <a ng-click="deleteSF(sf)">
+                            <i class="icon-remove" style="cursor: pointer" popover-trigger="mouseenter"
+                               popover="{{ 'SFC_FUNCTION_DELETE' | translate }}"></i>
+                        </a>
+                        <a ng-click="editSF(sf.name)">
+                            <i class="icon-edit" style="cursor: pointer" popover-trigger="mouseenter"
+                               popover="{{ 'SFC_FUNCTION_EDIT' | translate }}"></i>
+                        </a>
+                    </td>
+                </tr>
+            </table>
+        </tab>
+
+        <tab heading="{{'SFC_SERVICE_FUNCTIONS_TYPES' | translate}}">
+            <table ng-controller="serviceFunctionTypeCtrl" ng-table="tableParams" show-filter="true"
+                   class="footable table" style="margin-top: 0px">
+                <!--<tr ng-hide="sfs.length">-->
+                <!--<td colspan="6" class="centerAlign">{{'NO_DATA_FOUND' | translate}}</td>-->
+                <!--</tr>-->
+                <tr ng-repeat="sft in $data track by $index" ng-model="sfts">
+                    <td data-title="'SFC_FUNCTION_TYPE' | translate" sortable="'type'" filter="{ 'type': 'select' }"
+                        filter-data="sfTypes()">
+                        {{sft['type']}}
+                    </td>
+                    <td data-title="'SFC_FUNCTION_NAME' | translate" sortable="'name'" filter="{ 'name' : 'text' }">
+                        {{sft['name']}}
+                    </td>
+                </tr>
+            </table>
+        </tab>
+    </tabset>
+</div>
\ No newline at end of file
index 66807bf05b99e5d93820b02881d37178f8466efc..adae520219896865733ebd22c75f07b7ddd3d4f3 100755 (executable)
@@ -35,7 +35,8 @@ define(['app/sfc/sfc.module'], function (sfc) {
     return sfObject = _.findWhere(sfs, {name: sfName});
   }
 
-  sfc.register.controller('serviceNodeCtrl', function ($scope, $state, ServiceFunctionSvc, ServiceForwarderSvc, ServiceNodeSvc, ServiceNodeTopologyBackend, ModalDeleteSvc) {
+  sfc.register.controller('serviceNodeCtrl', function ($scope, $rootScope, $state, ServiceFunctionSvc, ServiceForwarderSvc, ServiceNodeSvc, ServiceNodeTopologyBackend, ModalDeleteSvc) {
+
     $scope.deleteServiceNode = function deleteServiceNode(snName) {
       ModalDeleteSvc.open(snName, function (result) {
         if (result == 'delete') {
@@ -66,15 +67,18 @@ define(['app/sfc/sfc.module'], function (sfc) {
       return maxSf <= 10 ? "col-xs-12 col-md-6 col-lg-4" : "col-xs-12 col-md-12 col-lg-6";
     };
 
-    $scope.experimental = false;
-
-    $scope.toggleGraphData = function () {
-      if ($scope.experimental) {
+    function createGraphData() {
+      if ($rootScope.experimental) {
         $scope.snsGraph = ServiceNodeTopologyBackend.createGraphDataExperimentalSFF($scope.sns, $scope.sffs, $scope.sfs);
       }
       else {
         $scope.snsGraph = ServiceNodeTopologyBackend.createGraphData($scope.sns, $scope.sffs, $scope.sfs);
       }
+    }
+
+    $scope.toggleGraphData = function () {
+      $rootScope.experimental = $rootScope.experimental ? false : true;
+      createGraphData();
     };
 
     ServiceFunctionSvc.getArray(function (data) {
@@ -85,7 +89,7 @@ define(['app/sfc/sfc.module'], function (sfc) {
 
         ServiceNodeSvc.getArray(function (data) {
           $scope.sns = data;
-          $scope.snsGraph = ServiceNodeTopologyBackend.createGraphData($scope.sns, $scope.sffs, $scope.sfs);
+          createGraphData();
         });
       });
     });
index 5fa126b4b9f8f6ee13240a104522d55b2df75396..453df163ed21a0fcc24023c0166856a9c60c2fe1 100755 (executable)
@@ -1,22 +1,27 @@
-
-<a class="btn btn-info add-row" href="#/sfc/servicenode-create">
-    {{ 'SFC_NODE_ADD' | translate }}
-</a>
+<div class="col-xs-12" style="padding: 0px">
+    <a class="btn btn-info add-row" href="#/sfc/servicenode-create">
+        {{ 'SFC_NODE_ADD' | translate }}
+    </a>
 <span>
     <label for="toggleGraphData">Check to show data from SFF model (otherwise showing SN data)</label>
     <input type="checkbox" ng-model="experimental" ng-change="toggleGraphData()" id="toggleGraphData"/>
 </span>
 
-<div class="sfc-node-main">
-    <div ng-class="getSnsGraphClass(sns)" ng-repeat="nodeGraph in snsGraph">
-        <div>
-            <button type="button" class="btn btn-sm btn-danger"  ng-click="deleteServiceNode(nodeGraph.name)" popover-trigger="mouseenter" popover="{{ 'SFC_NODE_DELETE' | translate }}"><i class="icon-trash"></i></button>
-            <button type="button" class="btn btn-sm btn-orange"  ng-click="editServiceNode(nodeGraph.name)" popover-trigger="mouseenter" popover="{{ 'SFC_NODE_EDIT' | translate }}"><i class="icon-edit"></i></button>
+    <div class="sfc-node-main">
+        <div ng-class="getSnsGraphClass(sns)" ng-repeat="nodeGraph in snsGraph">
+            <div>
+                <button type="button" class="btn btn-sm btn-danger" ng-click="deleteServiceNode(nodeGraph.name)"
+                        popover-trigger="mouseenter" popover="{{ 'SFC_NODE_DELETE' | translate }}"><i
+                        class="icon-trash"></i></button>
+                <button type="button" class="btn btn-sm btn-orange" ng-click="editServiceNode(nodeGraph.name)"
+                        popover-trigger="mouseenter" popover="{{ 'SFC_NODE_EDIT' | translate }}"><i
+                        class="icon-edit"></i></button>
+            </div>
+            <service-nodes-topology tree-view-data="nodeGraph"></service-nodes-topology>
         </div>
-        <service-nodes-topology tree-view-data="nodeGraph"></service-nodes-topology>
     </div>
-</div>
 
-<script type="text/javascript">
-               $('.footable').footable();
-</script>
+    <script type="text/javascript">
+        $('.footable').footable();
+    </script>
+</div>
\ No newline at end of file
index 3ff280f3b688749c41093b9e94c8e43bf8c74689..678c07d671e0b04b9457dcb8f6cdeb459af2b385 100755 (executable)
@@ -1,45 +1,50 @@
-<div class="col-md-12" style="padding-right: 0px">
-    <button type="button" ng-click="tableParams.sorting({}); tableParamsSfName.sorting({}); tableParamsSffName.sorting({});" class="btn btn-default pull-right">{{'SFC_CLEAR_SORTING' | translate}}</button>
-</div>
+<div class="col-xs-12" style="padding: 0px">
 
-<div class="col-md-2" style="padding-left: 0px">
-    <table ng-table="tableParamsSfName" class="footable table">
-        <!--<tr ng-hide="sfs.length">-->
-        <!--<td colspan="3" class="centerAlign">{{'NO_DATA_FOUND' | translate}}</td>-->
-        <!--</tr>-->
-        <tr ng-repeat="item in $data track by $index"
-            ui-draggable="true" drag="'sf_' + item.name" class="draggable">
-            <td data-title="'SFC_FUNCTION_NAME' | translate" sortable="'name'">
+    <div class="col-md-12" style="padding-right: 0px">
+        <button type="button"
+                ng-click="tableParams.sorting({}); tableParamsSfName.sorting({}); tableParamsSffName.sorting({});"
+                class="btn btn-default pull-right">{{'SFC_CLEAR_SORTING' | translate}}
+        </button>
+    </div>
+
+    <div class="col-md-2" style="padding-left: 0px">
+        <table ng-table="tableParamsSfName" class="footable table">
+            <!--<tr ng-hide="sfs.length">-->
+            <!--<td colspan="3" class="centerAlign">{{'NO_DATA_FOUND' | translate}}</td>-->
+            <!--</tr>-->
+            <tr ng-repeat="item in $data track by $index"
+                ui-draggable="true" drag="'sf_' + item.name" class="draggable">
+                <td data-title="'SFC_FUNCTION_NAME' | translate" sortable="'name'">
                 <span style="color:black;"
                       tooltip-html-unsafe="{{'SFC_TOOLTIP_TYPE' | translate}} {{item.type}} <br/> {{'SFC_TOOLTIP_IP' | translate}} {{item['ip-mgmt-address']}}"
                       tooltip-placement="right">{{item.name}}</span>
-            </td>
-        </tr>
-    </table>
-    <table ng-table="tableParamsSffName" class="footable table">
-        <!--<tr ng-hide="sfs.length">-->
-        <!--<td colspan="3" class="centerAlign">{{'NO_DATA_FOUND' | translate}}</td>-->
-        <!--</tr>-->
-        <tr ng-repeat="item in $data track by $index"
-            ui-draggable="true" drag="'sff_' + item.name" class="draggable">
-            <td data-title="'SFC_FUNCTION_SFF' | translate" sortable="'name'">
-                {{item.name}}
-            </td>
-        </tr>
-    </table>
-</div>
+                </td>
+            </tr>
+        </table>
+        <table ng-table="tableParamsSffName" class="footable table">
+            <!--<tr ng-hide="sfs.length">-->
+            <!--<td colspan="3" class="centerAlign">{{'NO_DATA_FOUND' | translate}}</td>-->
+            <!--</tr>-->
+            <tr ng-repeat="item in $data track by $index"
+                ui-draggable="true" drag="'sff_' + item.name" class="draggable">
+                <td data-title="'SFC_FUNCTION_SFF' | translate" sortable="'name'">
+                    {{item.name}}
+                </td>
+            </tr>
+        </table>
+    </div>
 
-<div class="col-md-10" style="padding-right: 0px">
+    <div class="col-md-10" style="padding-right: 0px">
 
-    <table ng-table="tableParams" class="footable table">
-        <!--<tr ng-hide="sfps.length">-->
-        <!--<td colspan="1" class="centerAlign">No data found</td>-->
-        <!--</tr>-->
-        <tr ng-repeat="sfp in $data track by $index" id="{{sfp.name}}~!~{{$index}}">
-            <td data-title="'SFC_PATH' | translate" sortable="'name'" ui-on-Drop="onSFPdrop($data, sfp)"
-                ng-class="getSFPstate(sfp)" effect-me="sfpEffectMe[sfp.name]" style="position: relative">
-                <p>
-                    <span class="spanText"><b>{{sfp.name}}</b></span>
+        <table ng-table="tableParams" class="footable table">
+            <!--<tr ng-hide="sfps.length">-->
+            <!--<td colspan="1" class="centerAlign">No data found</td>-->
+            <!--</tr>-->
+            <tr ng-repeat="sfp in $data track by $index" id="{{sfp.name}}~!~{{$index}}">
+                <td data-title="'SFC_PATH' | translate" sortable="'name'" ui-on-Drop="onSFPdrop($data, sfp)"
+                    ng-class="getSFPstate(sfp)" effect-me="sfpEffectMe[sfp.name]" style="position: relative">
+                    <p>
+                        <span class="spanText"><b>{{sfp.name}}</b></span>
                     <span class="spanText" ng-show="sfp['path-id'] && sfp['starting-index']">
                         ({{ 'SFC_PATH_ID' | translate }}: <b>{{sfp['path-id']}}</b>, {{ 'SFC_PATH_STARTING_INDEX' | translate }}: <b>{{sfp['starting-index']}}</b>)
                     </span>
                                popover-trigger="mouseenter" popover="{{ 'SFC_PATH_PERSIST' | translate }}"></i>
                         </a>
                     </span>
-                    <span class="spanText" ng-show="isSFPstate(sfp, sfpState.EDITED)">({{'SFC_PATH_TEMPORARY' | translate}})</span>
+                        <span class="spanText" ng-show="isSFPstate(sfp, sfpState.EDITED)">({{'SFC_PATH_TEMPORARY' | translate}})</span>
 
                     <span class="pull-right">
                         <service-path-classifier sfp="sfp" id-suffix="{{$index}}"></service-path-classifier>
                         <service-path-context-metadata-pop-up sfp-state="sfpState" sfp="sfp" context-metadata="contextMetadata" id-suffix="{{$index}}"></service-path-context-metadata-pop-up>
                     </span>
-                </p>
 
-                <div class="sfc-sf-component"
-                     style="width: 18px;">
-                    <div style="width: 100%; height: 64px;">
-                        <div class="arrow-left-part"></div>
+                    </p>
+
+                    <div class="sfc-sf-component"
+                         style="width: 18px;">
+                        <div style="width: 100%; height: 64px;">
+                            <div class="arrow-left-part"></div>
+                        </div>
                     </div>
-                </div>
 
-                <div class="connected-apps-container dropcontainer"
-                     ui-sortable="sortableOptions"
-                     ng-model="sfp['service-path-hop']">
+                    <div class="connected-apps-container dropcontainer"
+                         ui-sortable="sortableOptions"
+                         ng-model="sfp['service-path-hop']">
 
-                    <div class="sfc-sf-component draggable"
-                         ng-repeat="s in sfp['service-path-hop'] track by $index">
+                        <div class="sfc-sf-component draggable"
+                             ng-repeat="s in sfp['service-path-hop'] track by $index">
 
-                        <div style="width: 100%; height: 64px;">
-                            <div class="arrow-right-part"></div>
-                            <div class="obr-box" ng-class="getHopClass(s)">
-                                <i class="icon-remove"
-                                   style="cursor: pointer; position: relative; top: 0px; left: 60px;"
-                                   ng-click="removeSFfromSFP(sfp, $index)"
-                                   popover-trigger="mouseenter" popover="{{ 'SFC_FUNCTION_DELETE' | translate }}">
-                                </i>
+                            <div style="width: 100%; height: 64px;">
+                                <div class="arrow-right-part"></div>
+                                <div class="obr-box" ng-class="getHopClass(s)">
+                                    <i class="icon-remove"
+                                       style="cursor: pointer; position: relative; top: 0px; left: 60px;"
+                                       ng-click="removeSFfromSFP(sfp, $index)"
+                                       popover-trigger="mouseenter" popover="{{ 'SFC_FUNCTION_DELETE' | translate }}">
+                                    </i>
+                                </div>
+                                <wbr>
+                                <div class="arrow-left-part"></div>
                             </div>
-                            <wbr>
-                            <div class="arrow-left-part"></div>
-                        </div>
 
-                        <div style="width: 100%; height: 36px; text-align: center;">
-                            <div style="display: inline-block;">
-                                <span ng-if="getHopClass(s) == 'sf'" style="color: #1C94C4; cursor: pointer;" tooltip-placement="bottom"
+                            <div style="width: 100%; height: 36px; text-align: center;">
+                                <div style="display: inline-block;">
+                                <span ng-if="getHopClass(s) == 'sf'" style="color: #1C94C4; cursor: pointer;"
+                                      tooltip-placement="bottom"
                                       tooltip-html-unsafe="
                                   {{'SFC_FUNCTION' | translate}} <br/> <br/>
                                   <div style='text-align: left'>
                                   ">
                                     {{s['service-function-name']}}
                                 </span>
-                                <span ng-if="getHopClass(s) == 'sff'" style="color: orange; cursor: pointer;" tooltip-placement="bottom"
+                                <span ng-if="getHopClass(s) == 'sff'" style="color: orange; cursor: pointer;"
+                                      tooltip-placement="bottom"
                                       tooltip-html-unsafe="
                                   {{'SFC_FUNCTION_SFF' | translate}} <br/> <br/>
                                   <div style='text-align: left'>
                                   ">
                                     {{s['service-function-forwarder']}}
                                 </span>
+                                </div>
                             </div>
-                        </div>
 
+                        </div>
                     </div>
-                </div>
 
-                <div class="sfc-sf-component"
-                     style="width: 22px;">
-                    <div style="width: 100%; height: 64px;">
-                        <div class="arrow-right-part"></div>
+                    <div class="sfc-sf-component"
+                         style="width: 22px;">
+                        <div style="width: 100%; height: 64px;">
+                            <div class="arrow-right-part"></div>
+                        </div>
                     </div>
-                </div>
-
-            </td>
-        </tr>
-    </table>
-</div>
 
+                </td>
+            </tr>
+        </table>
+    </div>
+</div>
\ No newline at end of file
index 71280defc3581f461309976e482ff5e1ce577633..a9299d9089d2dc41cb5fc096bfd664ff1ffc79c9 100755 (executable)
@@ -1,6 +1,6 @@
 define(['app/sfc/sfc.module'], function (sfc) {
 
-  sfc.register.controller('rootSfcCtrl', function ($rootScope) {
+  sfc.register.controller('rootSfcCtrl', function ($rootScope, SfcRestangularSvc, $localStorage) {
 
 //    // register watch for debugging - works only in firefox
 //    if (angular.isDefined($rootScope.watch)) {
@@ -54,6 +54,19 @@ define(['app/sfc/sfc.module'], function (sfc) {
     {
       "attachment-point-type": ["bridge", "interface"]
     };
+
+    $rootScope.logConstants =
+    {
+      "level": ['INFO', 'DEBUG', 'WARN', 'ERROR']
+    };
+
+    $rootScope.experimental = true;
+
+    $localStorage.$default({
+      restangularBaseUrl: SfcRestangularSvc.getCurrentBaseUrl()
+    });
+    SfcRestangularSvc.changeBaseUrl($localStorage.restangularBaseUrl);
+
   });
 
   sfc.register.controller('sfcForwarderSelect2Ctrl', function ($scope) {
index 3d0f5f507b679fd4970b3584536c422f0425b55f..786f3ebe822211a720656cb15e0272f26e636c59 100755 (executable)
@@ -6,7 +6,7 @@
 }
 
 div.tooltip {
-  a{
+  a {
     color: #428bca !important;
   }
   position: absolute;
@@ -38,42 +38,42 @@ div.tooltip {
   cursor: pointer;
 }
 
-.overlay{
+.overlay {
   //background-color:#EEE;
   background-image: none;
   border: none;
 }
 
 .node text {
-  font-size:12px;
-  font-family:sans-serif;
+  font-size: 12px;
+  font-family: sans-serif;
   fill: #ffffff;
   text-shadow: 2px 2px black;
 }
 
-.nodeLabelOutContainer{
+.nodeLabelOutContainer {
   width: 50%;
   height: 100%;
-  margin:auto;
+  margin: auto;
   display: table;
   table-layout: fixed;
 }
 
-.nodeLabelInContainer{
+.nodeLabelInContainer {
   display: table-cell;
   line-height: 1;
 }
 
-.nodeLabel{
-  font-size:12px;
-  font-family:sans-serif;
+.nodeLabel {
+  font-size: 12px;
+  font-family: sans-serif;
   color: white;
   background: #414042;
-//  -ms-word-break: break-all;
-//  -webkit-hyphens: auto;
-//  -moz-hyphens: auto;
-//  -ms-hyphens: auto;
-//  hyphens: auto;
+  //  -ms-word-break: break-all;
+  //  -webkit-hyphens: auto;
+  //  -moz-hyphens: auto;
+  //  -ms-hyphens: auto;
+  //  hyphens: auto;
   white-space: pre-wrap; /* css-3 */
   white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
   white-space: -pre-wrap; /* Opera 4-6 */
@@ -82,8 +82,10 @@ div.tooltip {
 }
 
 /* saf3+, chrome1+ */
-@media screen and (-webkit-min-device-pixel-ratio:0) {
-  .nodeLabel  { word-wrap: inherit  }
+@media screen and (-webkit-min-device-pixel-ratio: 0) {
+  .nodeLabel {
+    word-wrap: inherit
+  }
 }
 
 .link {
@@ -92,33 +94,33 @@ div.tooltip {
   stroke-width: 2.5px;
 }
 
-.sfc-node-main{
+.sfc-node-main {
   margin-top: 30px;
   text-align: center;
 }
 
-.dropcontainer{
+.dropcontainer {
   display: table-cell;
-  float:left;
+  float: left;
 }
 
-.editable-input{
+.editable-input {
   color: #1C94C4 !important;
   background-color: white !important;
-  font-size:12px;
+  font-size: 12px;
   width: 80px;
   text-align: center;
   cursor: text;
 }
 
-.editable-click, a.editable-click{
+.editable-click, a.editable-click {
   text-decoration: none;
   color: #428bca;
   border-bottom: none;
   cursor: text;
 }
 
-.place{
+.place {
   width: 104px;
   height: 100px;
   background-image: url(images/arrow-right-part-small.png), url(images/arrow-left-part-small.png);
@@ -140,9 +142,9 @@ div.tooltip {
 }
 
 .error {
-  background: rgba(255,0,0,0.53);
+  background: rgba(255, 0, 0, 0.53);
   border-radius: 0px;
-  float:right;
+  float: right;
 }
 
 .warning {
@@ -192,7 +194,7 @@ div.tooltip {
   float: left;
 }
 
-.obr-box{
+.obr-box {
   width: 64px;
   height: 64px;
   -webkit-touch-callout: none;
@@ -204,11 +206,11 @@ div.tooltip {
   float: left;
 }
 
-.obr-box.sf{
+.obr-box.sf {
   background: url(images/Device_switch_3062_unknown_64.png) 0 0;
 }
 
-.obr-box.sff{
+.obr-box.sff {
   background: url(images/Device_switch_3062_unknown_64_orange.png) 0 0;
 }
 
@@ -247,6 +249,7 @@ div.tooltip {
 //---UI BOOTSTRAP MODAL OVERRIDE---
 // .modal-open      - body class for killing the scroll
 // .modal           - container to scroll within
+// .modal-body      - should be scrollable
 
 .modal-open {
   overflow: auto;
@@ -256,16 +259,21 @@ div.tooltip {
   overflow: hidden;
 }
 
-.has-error .select2-choice{
+.modal-body {
+  overflow: auto;
+}
+
+
+.has-error .select2-choice {
   border-color: #a94442 !important;
   -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075) !important;
   box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075) !important;
 }
 
-.popUp{
+.popUp {
   width: 40%;
   left: 50%;
-//  top: 60px;
+  //  top: 60px;
   min-width: 450px;
   position: absolute;
   z-index: 15;
@@ -275,4 +283,95 @@ div.tooltip {
     right: 5px;
     color: #f1f1f1;
   }
+}
+
+.nav-tabs li a {
+  color: white !important;
+  background-color: transparent !important;
+  border-radius: 4px 4px 0 0 !important;
+}
+
+.nav-tabs {
+  border-bottom: none !important;
+}
+
+@-webkit-keyframes rotating {
+  from {
+    -webkit-transform: rotate(0deg);
+  }
+  to {
+    -webkit-transform: rotate(360deg);
+  }
+}
+
+@-moz-keyframes rotating {
+  from {
+    -moz-transform: rotate(0deg);
+  }
+  to {
+    -moz-transform: rotate(360deg);
+  }
+}
+
+@keyframes rotating {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@-ms-keyframes rotating {
+  from {
+    -ms-transform: rotate(0deg);
+  }
+  to {
+    -ms-transform: rotate(360deg);
+  }
+}
+
+@-o-keyframes rotating {
+  from {
+    -o-transform: rotate(0deg);
+  }
+  to {
+    -o-transform: rotate(360deg);
+  }
+}
+
+.rotating {
+  -moz-animation: rotating 1.5s linear infinite;
+  -webkit-animation: rotating 1.5s linear infinite;
+  -o-animation: rotating 1.5s linear infinite;
+  -ms-animation: rotating 1.5s linear infinite;
+  animation: rotating 1.5s linear infinite;
+}
+
+@media screen and ( max-height: 700px ){
+  .modal-body {
+    max-height: 355px;
+  }
+  
+  .modal-dialog{
+    height: 500px;
+  }
+  
+  .modal-content{
+    height: 100%;
+  }
+}
+
+@media screen and ( max-height: 540px ){
+  .modal-body {
+    max-height: 225px;
+  }
+
+  .modal-dialog{
+    height: 370px;
+  }
+
+  .modal-content{
+    height: 100%;
+  }
 }
\ No newline at end of file
index 0990c24548f08e925fb59c0ee0d9c0b1ee580fdd..1c84713ed65caff365726e2347db49cf083c0226 100755 (executable)
@@ -12,12 +12,13 @@ define([
   'xeditable',
   'angular-sanitize',
   'ui-select2',
-  'ng-table'], function () {
+  'ng-table',
+  'ngStorage'], function () {
 
   var sfc = angular.module('app.sfc',
     [
       'app.core', 'ui.router.state', 'restangular', 'ui.bootstrap', 'ui.unique', 'ui.sortable', 'ngDragDrop', 'xeditable',
-      'ngSanitize', 'ui.select2', 'pascalprecht.translate', 'ngTable'
+      'ngSanitize', 'ui.select2', 'pascalprecht.translate', 'ngTable', 'ngStorage'
     ]);
 
   sfc.register = sfc; // for adding services, controllers, directives etc. to angular module before bootstrap
@@ -35,7 +36,8 @@ define([
       'app/sfc/utils/modal.controller',
       'app/sfc/acl/acl.controller',
       'app/sfc/metadata/metadata.controller',
-      'app/sfc/servicelocator/servicelocator.controller'];
+      'app/sfc/servicelocator/servicelocator.controller',
+      'app/sfc/system/system.controller'];
     var services = [
       'app/core/core.services',
       'app/sfc/sfc.services',
@@ -48,7 +50,8 @@ define([
       'app/sfc/servicefunction/servicefunction.services',
       'app/sfc/servicepath/servicepath.services',
       'app/sfc/servicelocator/servicelocator.services',
-      'app/sfc/acl/acl.services'];
+      'app/sfc/acl/acl.services',
+      'app/sfc/system/system.services'];
     var directives = [
       'app/sfc/sfc.directives',
       'app/sfc/servicenode/servicenode.directives',
@@ -321,6 +324,17 @@ define([
         }
       }
     });
+
+    $stateProvider.state('main.sfc.system', {
+      url: '/system',
+      access: access.public,
+      views: {
+        'sfc': {
+          templateUrl: 'src/app/sfc/system/system.tpl.html',
+          controller: 'sfcSystemCtrl'
+        }
+      }
+    });
   });
 
   return sfc;
index 32b0e38c21670dca3fae0f752eb8a430501555ce..1f9d9a911a60f35d9c91a7158c5988a7b864bcee 100755 (executable)
@@ -112,7 +112,6 @@ define(['app/sfc/sfc.module'], function (sfc) {
       return SfcRestangularSvc.getCurrentInstance().one('operations');
     };
 
-
     SfcRestBaseSvc.prototype.postRpc = function (input, operationName, params) {
       var headers = {
         "Content-Type": "application/yang.data+json",
@@ -318,6 +317,22 @@ define(['app/sfc/sfc.module'], function (sfc) {
   });
 
 
+  // ******* ServiceFunctionTypeSvc *********
+  sfc.register.factory('ServiceFunctionTypeSvc', function (SfcRestBaseSvc) {
+    var modelUrl = 'service-function-type';
+    var containerName = 'service-function-types';
+    var listName = 'service-function-type';
+
+    // constructor
+    function ServiceFunctionTypeSvc() {
+    }
+
+    ServiceFunctionTypeSvc.prototype = new SfcRestBaseSvc(modelUrl, containerName, listName);
+
+    return new ServiceFunctionTypeSvc();
+  });
+
+
   // ******* ServiceChainSvc *********
   sfc.register.factory('ServiceChainSvc', function (SfcRestBaseSvc) {
 
@@ -637,4 +652,4 @@ define(['app/sfc/sfc.module'], function (sfc) {
   });
 
 
-}); // end define
\ No newline at end of file
+}); // end define
diff --git a/sfc-ui/src/main/resources/pages/src/app/sfc/system/system.controller.js b/sfc-ui/src/main/resources/pages/src/app/sfc/system/system.controller.js
new file mode 100644 (file)
index 0000000..df38ed5
--- /dev/null
@@ -0,0 +1,157 @@
+define(['app/sfc/sfc.module'], function (sfc) {
+
+  sfc.register.controller('sfcSystemCtrl', function ($scope, SfcSystemSvc, ngTableParams, $filter) {
+    var thisCtrl = this;
+
+    $scope.features = [];
+
+    var NgTableParams = ngTableParams;
+    $scope.tableParams = new NgTableParams({
+        page: 1,            // show first page
+        count: 10,          // count per page
+        sorting: {
+          name: 'asc'     // initial sorting
+        }
+      },
+      {
+        total: $scope.features.length,
+        getData: function ($defer, params) {
+          // use build-in angular filter
+          var filteredData = params.filter() ?
+            $filter('filter')($scope.features, params.filter()) :
+            $scope.features;
+
+          var orderedData = params.sorting() ?
+            $filter('orderBy')(filteredData, params.orderBy()) :
+            filteredData;
+
+          params.total(orderedData.length);
+          $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
+        }
+      });
+
+    this.fetchData = function () {
+      SfcSystemSvc.getFeatures(function (data) {
+        $scope.features = SfcSystemSvc.getSfcFeatures(data);
+        $scope.tableParams.reload();
+      });
+    };
+
+    this.reloadData = function (data) {
+      $scope.features = SfcSystemSvc.getSfcFeatures(data);
+      $scope.tableParams.reload();
+    };
+
+    this.fetchData();
+
+    $scope.isFeatureInstalled = function (feature) {
+      return feature['state'] === "Installed";
+    };
+
+    $scope.isFeatureReloading = function (feature) {
+      return feature['reloading'];
+    };
+
+    $scope.refreshRepository = function (feature) {
+      feature['reloading'] = true;
+      SfcSystemSvc.refreshRepository(feature['repository-url'], function (data) {
+        thisCtrl.reloadData(data);
+        feature['reloading'] = false;
+      });
+    };
+
+    $scope.uninstallFeature = function (feature) {
+      feature['reloading'] = true;
+      SfcSystemSvc.uninstallFeature(feature['name'], feature['version'], function (data) {
+        thisCtrl.reloadData(data);
+        feature['reloading'] = false;
+      });
+    };
+
+    $scope.installFeature = function (feature) {
+      feature['reloading'] = true;
+      SfcSystemSvc.installFeature(feature['name'], feature['version'], function (data) {
+        thisCtrl.reloadData(data);
+        feature['reloading'] = false;
+      });
+    };
+
+    $scope.clearSorting = function () {
+      $scope.$broadcast('clearTableSorting');
+    };
+
+    $scope.$on('clearTableSorting', function () {
+      $scope.tableParams.sorting({});
+    });
+  });
+
+  sfc.register.controller('sfcSystemLogCtrl', function ($scope, SfcSystemSvc, ngTableParams, $filter, $q, SfcSystemModalException) {
+    var thisCtrl = this;
+
+    $scope.logs = [];
+
+    var NgTableParams = ngTableParams;
+    $scope.tableParams = new NgTableParams({
+        page: 1,            // show first page
+        count: 25,          // count per page
+        sorting: {
+          received: 'desc'     // initial sorting
+        }
+      },
+      {
+        total: $scope.logs.length,
+        getData: function ($defer, params) {
+          // use build-in angular filter
+          var filteredData = params.filter() ?
+            $filter('filter')($scope.logs, params.filter()) :
+            $scope.logs;
+
+          var orderedData = params.sorting() ?
+            $filter('orderBy')(filteredData, params.orderBy()) :
+            filteredData;
+
+          params.total(orderedData.length);
+          $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
+        }
+      });
+
+    this.fetchData = function () {
+      SfcSystemSvc.getLogs(function (data) {
+        $scope.logs = data;
+        $scope.tableParams.reload();
+      });
+    };
+
+    this.reloadData = function () {
+      $scope.tableParams.reload();
+    };
+
+    this.fetchData();
+
+    $scope.logLevels = function () {
+      var def = $q.defer();
+      var data = [];
+      _.each($scope.logConstants.level, function (level) {
+        data.push({id: level, title: level});
+      });
+      def.resolve(data);
+      return def;
+    };
+
+    $scope.$on('clearTableSorting', function () {
+      $scope.tableParams.sorting({});
+    });
+
+    $scope.showException = function (log) {
+      SfcSystemModalException.open(log);
+    };
+  });
+
+  sfc.register.controller('sfcSystemModalExceptionCtrl', function ($modalInstance, $scope, log) {
+    $scope.log = log;
+
+    $scope.dismiss = function () {
+      $modalInstance.dismiss('close');
+    };
+  });
+});
\ No newline at end of file
diff --git a/sfc-ui/src/main/resources/pages/src/app/sfc/system/system.modal.exception.tpl.html b/sfc-ui/src/main/resources/pages/src/app/sfc/system/system.modal.exception.tpl.html
new file mode 100644 (file)
index 0000000..0d584cd
--- /dev/null
@@ -0,0 +1,13 @@
+<div class="modal-header btn-danger">
+    <h4 class="modal-title">{{'SFC_SYSTEM_MODAL_EXCEPTION_HEAD' | translate}}: '{{log['bundleName']}}'</h4>
+</div>
+
+<div class="modal-body" style="text-align: left;">
+    <pre style="font-size: 11px">{{log['exception']}}</pre>
+</div>
+
+<div class="modal-footer">
+    <button class="btn btn-danger" ng-click="dismiss()"><i class="icon-remove-sign"></i> {{'SFC_SYSTEM_MODAL_EXCEPTION_CLOSE'
+        | translate}}
+    </button>
+</div>
\ No newline at end of file
diff --git a/sfc-ui/src/main/resources/pages/src/app/sfc/system/system.services.js b/sfc-ui/src/main/resources/pages/src/app/sfc/system/system.services.js
new file mode 100644 (file)
index 0000000..504d283
--- /dev/null
@@ -0,0 +1,119 @@
+define(['app/sfc/sfc.module'], function (sfc) {
+
+  sfc.register.service('SfcSystemSvc', function (SfcRestangularSvc) {
+
+    var authorizationString = "karaf:karaf";
+    var contentType = "application/x-www-form-urlencoded";
+
+    var svc = {};
+
+    svc.getBasicAuthHeader = function () {
+      return btoa(authorizationString);
+    };
+
+    svc.getCurrentBaseUrl = function () {
+      var baseUrl = SfcRestangularSvc.getCurrentBaseUrl();
+      var indexOfRestconf = baseUrl.indexOf("restconf");
+
+      if (angular.isDefined(indexOfRestconf)) {
+        return baseUrl.substr(0, indexOfRestconf);
+      }
+
+      return null;
+    };
+
+    svc.baseSystemRest = function () {
+      return SfcRestangularSvc.getCurrentInstance().oneUrl('', svc.getCurrentBaseUrl() + "system/console/");
+    };
+
+    svc.getLogs = function (callback) {
+      return svc.baseSystemRest().customPOST("traces=true", 'logs', null, {'Authorization': 'Basic ' + svc.getBasicAuthHeader(), 'Content-type': contentType})
+        .then(function (result) {
+          if (angular.isDefined(result.data)) {
+            _.each(result.data, function (item) {
+              item['id'] = parseInt(item['id'], 10);
+              item['received'] = new Date(item['received']).toLocaleString();
+            });
+            callback(result.data);
+          }
+          else {
+            callback([]);
+          }
+        });
+    };
+
+    svc.getFeatures = function (callback) {
+      return svc.baseSystemRest().customPOST(null, 'features', null, {'Authorization': 'Basic ' + svc.getBasicAuthHeader()})
+        .then(function (result) {
+          callback(result);
+        });
+    };
+
+    svc.getSfcFeatures = function (data) {
+      var sfcFeatures = _.filter(data['features'], function (item) {
+        return item['name'].match(/sfc/);
+      });
+
+      _.each(sfcFeatures, function (feature) {
+        svc.expandFeatureRepository(feature, data['repositories']);
+      });
+
+      return sfcFeatures;
+    };
+
+    svc.expandFeatureRepository = function (feature, repositories) {
+      var featureRepository = _.findWhere(repositories, {name: feature['repository']});
+
+      if (angular.isDefined(featureRepository)) {
+        feature['repository-url'] = featureRepository['url'];
+      }
+    };
+
+    svc.refreshRepository = function (repositoryUrl, callback) {
+      return svc.baseSystemRest().customPOST({action: 'refreshRepository', url: repositoryUrl}, 'features', null,
+        {Authorization: 'Basic ' + svc.getBasicAuthHeader(), 'Content-type': contentType})
+        .then(function (result) {
+          callback(result);
+        });
+    };
+
+    svc.uninstallFeature = function (featureName, featureVersion, callback) {
+      return svc.baseSystemRest().customPOST("action=uninstallFeature" + "&feature=" + featureName + "&version=" + featureVersion, 'features', null,
+        {Authorization: 'Basic ' + svc.getBasicAuthHeader(), 'Content-type': contentType})
+        .then(function (result) {
+          callback(result);
+        });
+    };
+
+    svc.installFeature = function (featureName, featureVersion, callback) {
+      return svc.baseSystemRest().customPOST("action=installFeature" + "&feature=" + featureName + "&version=" + featureVersion, 'features', null,
+        {Authorization: 'Basic ' + svc.getBasicAuthHeader(), 'Content-type': contentType})
+        .then(function (result) {
+          callback(result);
+        });
+    };
+
+    return svc;
+  });
+
+  sfc.register.factory('SfcSystemModalException', function ($modal) {
+    var svc = {};
+    var modalInstance;
+
+    svc.open = function (log) {
+      modalInstance = $modal.open({
+        templateUrl: 'src/app/sfc/system/system.modal.exception.tpl.html',
+        controller: 'sfcSystemModalExceptionCtrl',
+        size: 'lg',
+        resolve: {
+          log: function () {
+            return log;
+          }
+        }
+      });
+    };
+
+    return svc;
+  });
+
+});
\ No newline at end of file
diff --git a/sfc-ui/src/main/resources/pages/src/app/sfc/system/system.tpl.html b/sfc-ui/src/main/resources/pages/src/app/sfc/system/system.tpl.html
new file mode 100644 (file)
index 0000000..c427208
--- /dev/null
@@ -0,0 +1,77 @@
+<div class="col-xs-12" style="padding: 0px">
+
+    <div class="col-xs-12" style="padding: 0px">
+        <button type="button" ng-click="clearSorting()" class="btn btn-default pull-right">
+            {{'SFC_CLEAR_SORTING' | translate}}
+        </button>
+    </div>
+
+    <tabset>
+        <tab heading="{{'SFC_SYSTEM_KARAF_FEATURES' | translate}}">
+
+            <table ng-table="tableParams" show-filter="true" class="footable table" style="font-size:12px; margin-top: 0">
+                <tr ng-repeat="feature in $data track by $index" ng-model="features">
+                    <td data-title="'SFC_SYSTEM_FEATURE_ID' | translate" sortable="'id'" filter="{ 'id': 'text' }">
+                        {{feature['id']}}
+                    </td>
+                    <td data-title="'SFC_SYSTEM_FEATURE_REPOSITORY_URL' | translate"
+                        sortable="'valueOf()[\'repository-url\']'" filter="{ 'repository-url': 'text' }">
+                        {{feature['repository-url']}}
+                    </td>
+                    <td data-title="'SFC_SYSTEM_FEATURE_STATUS' | translate" sortable="'state'"
+                        filter="{ 'state': 'text' }">
+                        <i ng-show="isFeatureInstalled(feature)" class="icon-circle" style="color:green"></i>
+                        <i ng-show="!isFeatureInstalled(feature)" class="icon-circle" style="color:red"></i>
+                        {{feature['state']}}
+                    </td>
+
+                    <td data-title="'SFC_FUNCTION_ACTIONS' | translate">
+                        <a ng-click="refreshRepository(feature)">
+                            <i class="icon-refresh" ng-class="{rotating: isFeatureReloading(feature)}"
+                               style="cursor: pointer; font-size: 14px" popover-trigger="mouseenter"
+                               popover="{{ 'SFC_SYSTEM_REPOSITORY_REFRESH' | translate }}"></i>
+                        </a>
+                        <a ng-show="isFeatureInstalled(feature)" ng-click="uninstallFeature(feature)">
+                            <i class="icon-eject" style="cursor: pointer; font-size: 14px" popover-trigger="mouseenter"
+                               popover="{{ 'SFC_SYSTEM_FEATURE_UNINSTALL' | translate }}"></i>
+                        </a>
+                        <a ng-show="!isFeatureInstalled(feature)" ng-click="installFeature(feature)">
+                            <i class="icon-play" style="cursor: pointer; font-size: 14px" popover-trigger="mouseenter"
+                               popover="{{ 'SFC_SYSTEM_FEATURE_INSTALL' | translate }}"></i>
+                        </a>
+                    </td>
+                </tr>
+            </table>
+        </tab>
+
+        <tab heading="{{'SFC_SYSTEM_KARAF_LOGS' | translate}}">
+            <table ng-controller="sfcSystemLogCtrl" ng-table="tableParams" show-filter="true" class="footable table"
+                   style="font-size:12px; margin-top: 0">
+                <tr ng-repeat="log in $data track by $index" ng-model="logs">
+                    <td data-title="'SFC_SYSTEM_LOG_RECEIVED' | translate" sortable="'received'"
+                        filter="{ 'received': 'text' }">
+                        {{log['received']}}
+                    </td>
+                    <td data-title="'SFC_SYSTEM_LOG_LEVEL' | translate" sortable="'level'" filter="{ 'level': 'select' }" filter-data="logLevels()">
+                        {{log['level']}}
+                    </td>
+                    <td data-title="'SFC_SYSTEM_LOG_MESSAGE' | translate" sortable="'message'"
+                        filter="{ 'message': 'text' }">
+                        {{log['message']}}
+                    </td>
+                    <td data-title="'SFC_SYSTEM_LOG_BUNDLE' | translate" sortable="'bundleName'"
+                        filter="{ 'bundleName': 'text' }">
+                        {{log['bundleName']}}
+                    </td>
+                    <td data-title="'SFC_SYSTEM_LOG_EXCEPTION' | translate">
+                        <a ng-if="log['exception']" ng-click="showException(log)">
+                            <i class="icon-list-alt"
+                               style="cursor: pointer; font-size: 14px" popover-trigger="mouseenter"
+                               popover="{{ 'SFC_SYSTEM_LOG_SHOW_EXCEPTION' | translate }}"></i>
+                        </a>
+                        <span class="spanText" ng-if="!log['exception']">-</span>
+                    </td>
+                </tr>
+            </table>
+        </tab>
+</div>
\ No newline at end of file
index 60c0a541d65ee0d587b3b1aa522ddae706f5e448..31db939d1a8162a7443cf6902d8c5dfae791e522 100755 (executable)
@@ -29,7 +29,8 @@ require.config({
     'ui-sortable' : '../vendor/angular-ui-sortable/sortable',
     'ngDragDrop' : '../vendor/angular-dragdrop/draganddrop',
     'xeditable' : '../vendor/angular-xeditable/dist/js/xeditable',
-    'ng-table': '../vendor/ng-table/ng-table'
+    'ng-table': '../vendor/ng-table/ng-table',
+    'ngStorage': '../vendor/ngStorage/ngStorage.min'
   },
 
   shim : {
@@ -54,6 +55,7 @@ require.config({
     'ngload' : ['angularAMD'],
     'ng-table': ['angular'],
     'ngDragDrop' : ['angular'],
+    'ngStorage' : ['angular'],
     'xeditable' : ['angular'],
     'jquery-ui' : ['jquery'],
     'jquery' : {
index fa6a8613174cfc4bad968a1a7136aedffeacedbf..ae71363e69c7210e731c4b61b76ea7a377277bf8 100644 (file)
@@ -2,9 +2,9 @@
  * angular-ui-bootstrap
  * http://angular-ui.github.io/bootstrap/
 
- * Version: 0.11.0 - 2014-05-01
+ * Version: 0.12.0 - 2014-11-16
  * License: MIT
  */
-angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.tpls",["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/day.html","template/datepicker/month.html","template/datepicker/popup.html","template/datepicker/year.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(a,b,c){function d(a){for(var b in a)if(void 0!==f.style[b])return a[b]}var e=function(d,f,g){g=g||{};var h=a.defer(),i=e[g.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(f)?d.addClass(f):angular.isFunction(f)?f(d):angular.isObject(f)&&d.css(f),i||h.resolve(d)}),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},f=document.createElement("trans"),g={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},h={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return e.transitionEndEventName=d(g),e.animationEndEventName=d(h),e}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(a){return{link:function(b,c,d){function e(b){function d(){j===e&&(j=void 0)}var e=a(c,b);return j&&j.cancel(),j=e,e.then(d,d),e}function f(){k?(k=!1,g()):(c.removeClass("collapse").addClass("collapsing"),e({height:c[0].scrollHeight+"px"}).then(g))}function g(){c.removeClass("collapsing"),c.addClass("collapse in"),c.css({height:"auto"})}function h(){if(k)k=!1,i(),c.css({height:0});else{c.css({height:c[0].scrollHeight+"px"});{c[0].offsetWidth}c.removeClass("collapse in").addClass("collapsing"),e({height:0}).then(i)}}function i(){c.removeClass("collapsing"),c.addClass("collapse")}var j,k=!0;b.$watch(d.collapse,function(a){a?h():f()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",function(){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){d.addGroup(a),a.$watch("isOpen",function(b){b&&d.closeOthers(a)}),a.toggleOpen=function(){a.isDisabled||(a.isOpen=!a.isOpen)}}}}).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,function(){}))}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(a,b,c,d){a.$watch(function(){return d[c.accordionTransclude]},function(a){a&&(b.html(""),b.append(a))})}}}),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(a,b){a.closeable="close"in b}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(a,b,c){b.addClass("ng-binding").data("$binding",c.bindHtmlUnsafe),a.$watch(c.bindHtmlUnsafe,function(a){b.html(a||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).controller("ButtonsController",["buttonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("btnRadio",function(){return{require:["btnRadio","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){var e=d[0],f=d[1];f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.btnRadio)))},b.bind(e.toggleEvent,function(){var d=b.hasClass(e.activeClass);(!d||angular.isDefined(c.uncheckable))&&a.$apply(function(){f.$setViewValue(d?null:a.$eval(c.btnRadio)),f.$render()})})}}}).directive("btnCheckbox",function(){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){var d=a.$eval(b);return angular.isDefined(d)?d:c}var h=d[0],i=d[1];i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.bind(h.toggleEvent,function(){a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$transition",function(a,b,c){function d(){e();var c=+a.interval;!isNaN(c)&&c>=0&&(g=b(f,c))}function e(){g&&(b.cancel(g),g=null)}function f(){h?(a.next(),d()):a.pause()}var g,h,i=this,j=i.slides=a.slides=[],k=-1;i.currentSlide=null;var l=!1;i.select=a.select=function(e,f){function g(){if(!l){if(i.currentSlide&&angular.isString(f)&&!a.noTransition&&e.$element){e.$element.addClass(f);{e.$element[0].offsetWidth}angular.forEach(j,function(a){angular.extend(a,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(e,{direction:f,active:!0,entering:!0}),angular.extend(i.currentSlide||{},{direction:f,leaving:!0}),a.$currentTransition=c(e.$element,{}),function(b,c){a.$currentTransition.then(function(){h(b,c)},function(){h(b,c)})}(e,i.currentSlide)}else h(e,i.currentSlide);i.currentSlide=e,k=m,d()}}function h(b,c){angular.extend(b,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(c||{},{direction:"",active:!1,leaving:!1,entering:!1}),a.$currentTransition=null}var m=j.indexOf(e);void 0===f&&(f=m>k?"next":"prev"),e&&e!==i.currentSlide&&(a.$currentTransition?(a.$currentTransition.cancel(),b(g)):g())},a.$on("$destroy",function(){l=!0}),i.indexOfSlide=function(a){return j.indexOf(a)},a.next=function(){var b=(k+1)%j.length;return a.$currentTransition?void 0:i.select(j[b],"next")},a.prev=function(){var b=0>k-1?j.length-1:k-1;return a.$currentTransition?void 0:i.select(j[b],"prev")},a.isActive=function(a){return i.currentSlide===a},a.$watch("interval",d),a.$on("$destroy",e),a.play=function(){h||(h=!0,d())},a.pause=function(){a.noPause||(h=!1,e())},i.addSlide=function(b,c){b.$element=c,j.push(b),1===j.length||b.active?(i.select(j[j.length-1]),1==j.length&&a.play()):b.active=!1},i.removeSlide=function(a){var b=j.indexOf(a);j.splice(b,1),j.length>0&&a.active?i.select(b>=j.length?j[b-1]:j[b]):k>b&&k--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",function(){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{active:"=?"},link:function(a,b,c,d){d.addSlide(a,b),a.$on("$destroy",function(){d.removeSlide(a)}),a.$watch("active",function(b){b&&d.select(a)})}}}),angular.module("ui.bootstrap.dateparser",[]).service("dateParser",["$locale","orderByFilter",function(a,b){function c(a,b,c){return 1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}this.parsers={};var d={yyyy:{regex:"\\d{4}",apply:function(a){this.year=+a}},yy:{regex:"\\d{2}",apply:function(a){this.year=+a+2e3}},y:{regex:"\\d{1,4}",apply:function(a){this.year=+a}},MMMM:{regex:a.DATETIME_FORMATS.MONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.MONTH.indexOf(b)}},MMM:{regex:a.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.SHORTMONTH.indexOf(b)}},MM:{regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1}},M:{regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1}},dd:{regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},d:{regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},EEEE:{regex:a.DATETIME_FORMATS.DAY.join("|")},EEE:{regex:a.DATETIME_FORMATS.SHORTDAY.join("|")}};this.createParser=function(a){var c=[],e=a.split("");return angular.forEach(d,function(b,d){var f=a.indexOf(d);if(f>-1){a=a.split(""),e[f]="("+b.regex+")",a[f]="$";for(var g=f+1,h=f+d.length;h>g;g++)e[g]="",a[g]="$";a=a.join(""),c.push({index:f,apply:b.apply})}}),{regex:new RegExp("^"+e.join("")+"$"),map:b(c,"index")}},this.parse=function(b,d){if(!angular.isString(b))return b;d=a.DATETIME_FORMATS[d]||d,this.parsers[d]||(this.parsers[d]=this.createParser(d));var e=this.parsers[d],f=e.regex,g=e.map,h=b.match(f);if(h&&h.length){for(var i,j={year:1900,month:0,date:1,hours:0},k=1,l=h.length;l>k;k++){var m=g[k-1];m.apply&&m.apply.call(j,h[k])}return c(j.year,j.month,j.date)&&(i=new Date(j.year,j.month,j.date,j.hours)),i}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].documentElement.scrollLeft)}},positionElements:function(a,b,c,d){var e,f,g,h,i=c.split("-"),j=i[0],k=i[1]||"center";e=d?this.offset(a):this.position(a),f=b.prop("offsetWidth"),g=b.prop("offsetHeight");var l={center:function(){return e.left+e.width/2-f/2},left:function(){return e.left},right:function(){return e.left+e.width}},m={center:function(){return e.top+e.height/2-g/2},top:function(){return e.top},bottom:function(){return e.top+e.height}};switch(j){case"right":h={top:m[k](),left:l[j]()};break;case"left":h={top:m[k](),left:e.left-f};break;case"bottom":h={top:m[j](),left:l[k]()};break;default:h={top:e.top-g,left:l[k]()}}return h}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.position"]).constant("datepickerConfig",{formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",datepickerMode:"day",minMode:"day",maxMode:"year",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null}).controller("DatepickerController",["$scope","$attrs","$parse","$interpolate","$timeout","$log","dateFilter","datepickerConfig",function(a,b,c,d,e,f,g,h){var i=this,j={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","minMode","maxMode","showWeeks","startingDay","yearRange"],function(c,e){i[c]=angular.isDefined(b[c])?8>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):h[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){i[d]=a?new Date(a):null,i.refreshView()}):i[d]=h[d]?new Date(h[d]):null}),a.datepickerMode=a.datepickerMode||h.datepickerMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),this.activeDate=angular.isDefined(b.initDate)?a.$parent.$eval(b.initDate):new Date,a.isActive=function(b){return 0===i.compare(b.date,i.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){j=a,j.$render=function(){i.render()}},this.render=function(){if(j.$modelValue){var a=new Date(j.$modelValue),b=!isNaN(a);b?this.activeDate=a:f.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'),j.$setValidity("date",b)}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=j.$modelValue?new Date(j.$modelValue):null;j.$setValidity("date-disabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=j.$modelValue?new Date(j.$modelValue):null;return{date:a,label:g(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===i.minMode){var c=j.$modelValue?new Date(j.$modelValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),j.$setViewValue(c),j.$render()}else i.activeDate=b,a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=i.activeDate.getFullYear()+a*(i.step.years||0),c=i.activeDate.getMonth()+a*(i.step.months||0);i.activeDate.setFullYear(b,c,1),i.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===i.maxMode&&1===b||a.datepickerMode===i.minMode&&-1===b||(a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var k=function(){e(function(){i.element[0].focus()},0,!1)};a.$on("datepicker.focus",k),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),b.stopPropagation(),"enter"===c||"space"===c){if(i.isDisabled(i.activeDate))return;a.select(i.activeDate),k()}else!b.ctrlKey||"up"!==c&&"down"!==c?(i.handleKeyDown(c,b),i.refreshView()):(a.toggleMode("up"===c?1:-1),k())}}]).directive("datepicker",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{datepickerMode:"=?",dateDisabled:"&"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}).directive("daypicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/day.html",require:"^datepicker",link:function(b,c,d,e){function f(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?i[b]:29}function g(a,b){var c=new Array(b),d=new Date(a),e=0;for(d.setHours(12);b>e;)c[e++]=new Date(d),d.setDate(d.getDate()+1);return c}function h(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}b.showWeeks=e.showWeeks,e.step={months:1},e.element=c;var i=[31,28,31,30,31,30,31,31,30,31,30,31];e._refreshView=function(){var c=e.activeDate.getFullYear(),d=e.activeDate.getMonth(),f=new Date(c,d,1),i=e.startingDay-f.getDay(),j=i>0?7-i:-i,k=new Date(f);j>0&&k.setDate(-j+1);for(var l=g(k,42),m=0;42>m;m++)l[m]=angular.extend(e.createDateObject(l[m],e.formatDay),{secondary:l[m].getMonth()!==d,uid:b.uniqueId+"-"+m});b.labels=new Array(7);for(var n=0;7>n;n++)b.labels[n]={abbr:a(l[n].date,e.formatDayHeader),full:a(l[n].date,"EEEE")};if(b.title=a(e.activeDate,e.formatDayTitle),b.rows=e.split(l,7),b.showWeeks){b.weekNumbers=[];for(var o=h(b.rows[0][0].date),p=b.rows.length;b.weekNumbers.push(o++)<p;);}},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},e.handleKeyDown=function(a){var b=e.activeDate.getDate();if("left"===a)b-=1;else if("up"===a)b-=7;else if("right"===a)b+=1;else if("down"===a)b+=7;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getMonth()+("pageup"===a?-1:1);e.activeDate.setMonth(c,1),b=Math.min(f(e.activeDate.getFullYear(),e.activeDate.getMonth()),b)}else"home"===a?b=1:"end"===a&&(b=f(e.activeDate.getFullYear(),e.activeDate.getMonth()));e.activeDate.setDate(b)},e.refreshView()}}}]).directive("monthpicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/month.html",require:"^datepicker",link:function(b,c,d,e){e.step={years:1},e.element=c,e._refreshView=function(){for(var c=new Array(12),d=e.activeDate.getFullYear(),f=0;12>f;f++)c[f]=angular.extend(e.createDateObject(new Date(d,f,1),e.formatMonth),{uid:b.uniqueId+"-"+f});b.title=a(e.activeDate,e.formatMonthTitle),b.rows=e.split(c,3)},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},e.handleKeyDown=function(a){var b=e.activeDate.getMonth();if("left"===a)b-=1;else if("up"===a)b-=3;else if("right"===a)b+=1;else if("down"===a)b+=3;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getFullYear()+("pageup"===a?-1:1);e.activeDate.setFullYear(c)}else"home"===a?b=0:"end"===a&&(b=11);e.activeDate.setMonth(b)},e.refreshView()}}}]).directive("yearpicker",["dateFilter",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/year.html",require:"^datepicker",link:function(a,b,c,d){function e(a){return parseInt((a-1)/f,10)*f+1}var f=d.yearRange;d.step={years:f},d.element=b,d._refreshView=function(){for(var b=new Array(f),c=0,g=e(d.activeDate.getFullYear());f>c;c++)b[c]=angular.extend(d.createDateObject(new Date(g+c,0,1),d.formatYear),{uid:a.uniqueId+"-"+c});a.title=[b[0].label,b[f-1].label].join(" - "),a.rows=d.split(b,5)},d.compare=function(a,b){return a.getFullYear()-b.getFullYear()},d.handleKeyDown=function(a){var b=d.activeDate.getFullYear();"left"===a?b-=1:"up"===a?b-=5:"right"===a?b+=1:"down"===a?b+=5:"pageup"===a||"pagedown"===a?b+=("pageup"===a?-1:1)*d.step.years:"home"===a?b=e(d.activeDate.getFullYear()):"end"===a&&(b=e(d.activeDate.getFullYear())+f-1),d.activeDate.setFullYear(b)},d.refreshView()}}}]).constant("datepickerPopupConfig",{datepickerPopup:"yyyy-MM-dd",currentText:"Today",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","dateParser","datepickerPopupConfig",function(a,b,c,d,e,f,g){return{restrict:"EA",require:"ngModel",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&"},link:function(h,i,j,k){function l(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function m(a){if(a){if(angular.isDate(a)&&!isNaN(a))return k.$setValidity("date",!0),a;if(angular.isString(a)){var b=f.parse(a,n)||new Date(a);return isNaN(b)?void k.$setValidity("date",!1):(k.$setValidity("date",!0),b)}return void k.$setValidity("date",!1)}return k.$setValidity("date",!0),null}var n,o=angular.isDefined(j.closeOnDateSelection)?h.$parent.$eval(j.closeOnDateSelection):g.closeOnDateSelection,p=angular.isDefined(j.datepickerAppendToBody)?h.$parent.$eval(j.datepickerAppendToBody):g.appendToBody;h.showButtonBar=angular.isDefined(j.showButtonBar)?h.$parent.$eval(j.showButtonBar):g.showButtonBar,h.getText=function(a){return h[a+"Text"]||g[a+"Text"]},j.$observe("datepickerPopup",function(a){n=a||g.datepickerPopup,k.$render()});var q=angular.element("<div datepicker-popup-wrap><div datepicker></div></div>");q.attr({"ng-model":"date","ng-change":"dateSelection()"});var r=angular.element(q.children()[0]);j.datepickerOptions&&angular.forEach(h.$parent.$eval(j.datepickerOptions),function(a,b){r.attr(l(b),a)}),angular.forEach(["minDate","maxDate"],function(a){j[a]&&(h.$parent.$watch(b(j[a]),function(b){h[a]=b}),r.attr(l(a),a))}),j.dateDisabled&&r.attr("date-disabled","dateDisabled({ date: date, mode: mode })"),k.$parsers.unshift(m),h.dateSelection=function(a){angular.isDefined(a)&&(h.date=a),k.$setViewValue(h.date),k.$render(),o&&(h.isOpen=!1,i[0].focus())},i.bind("input change keyup",function(){h.$apply(function(){h.date=k.$modelValue})}),k.$render=function(){var a=k.$viewValue?e(k.$viewValue,n):"";i.val(a),h.date=m(k.$modelValue)};var s=function(a){h.isOpen&&a.target!==i[0]&&h.$apply(function(){h.isOpen=!1})},t=function(a){h.keydown(a)};i.bind("keydown",t),h.keydown=function(a){27===a.which?(a.preventDefault(),a.stopPropagation(),h.close()):40!==a.which||h.isOpen||(h.isOpen=!0)},h.$watch("isOpen",function(a){a?(h.$broadcast("datepicker.focus"),h.position=p?d.offset(i):d.position(i),h.position.top=h.position.top+i.prop("offsetHeight"),c.bind("click",s)):c.unbind("click",s)}),h.select=function(a){if("today"===a){var b=new Date;angular.isDate(k.$modelValue)?(a=new Date(k.$modelValue),a.setFullYear(b.getFullYear(),b.getMonth(),b.getDate())):a=new Date(b.setHours(0,0,0,0))}h.dateSelection(a)},h.close=function(){h.isOpen=!1,i[0].focus()};var u=a(q)(h);p?c.find("body").append(u):i.after(u),h.$on("$destroy",function(){u.remove(),i.unbind("keydown",t),c.unbind("click",s)})}}}]).directive("datepickerPopupWrap",function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(a,b){b.bind("click",function(a){a.preventDefault(),a.stopPropagation()})}}}),angular.module("ui.bootstrap.dropdown",[]).constant("dropdownConfig",{openClass:"open"}).service("dropdownService",["$document",function(a){var b=null;this.open=function(e){b||(a.bind("click",c),a.bind("keydown",d)),b&&b!==e&&(b.isOpen=!1),b=e},this.close=function(e){b===e&&(b=null,a.unbind("click",c),a.unbind("keydown",d))};var c=function(a){a&&a.isDefaultPrevented()||b.$apply(function(){b.isOpen=!1})},d=function(a){27===a.which&&(b.focusToggleElement(),c())}}]).controller("DropdownController",["$scope","$attrs","$parse","dropdownConfig","dropdownService","$animate",function(a,b,c,d,e,f){var g,h=this,i=a.$new(),j=d.openClass,k=angular.noop,l=b.onToggle?c(b.onToggle):angular.noop;this.init=function(d){h.$element=d,b.isOpen&&(g=c(b.isOpen),k=g.assign,a.$watch(g,function(a){i.isOpen=!!a}))},this.toggle=function(a){return i.isOpen=arguments.length?!!a:!i.isOpen},this.isOpen=function(){return i.isOpen},i.focusToggleElement=function(){h.toggleElement&&h.toggleElement[0].focus()},i.$watch("isOpen",function(b,c){f[b?"addClass":"removeClass"](h.$element,j),b?(i.focusToggleElement(),e.open(i)):e.close(i),k(a,b),angular.isDefined(b)&&b!==c&&l(a,{open:!!b})}),a.$on("$locationChangeSuccess",function(){i.isOpen=!1}),a.$on("$destroy",function(){i.$destroy()})}]).directive("dropdown",function(){return{restrict:"CA",controller:"DropdownController",link:function(a,b,c,d){d.init(b)}}}).directive("dropdownToggle",function(){return{restrict:"CA",require:"?^dropdown",link:function(a,b,c,d){if(d){d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.modal",["ui.bootstrap.transition"]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c<a.length;c++)if(b==a[c].key)return a[c]},keys:function(){for(var b=[],c=0;c<a.length;c++)b.push(a[c].key);return b},top:function(){return a[a.length-1]},remove:function(b){for(var c=-1,d=0;d<a.length;d++)if(b==a[d].key){c=d;break}return a.splice(c,1)[0]},removeTop:function(){return a.splice(a.length-1,1)[0]},length:function(){return a.length}}}}}).directive("modalBackdrop",["$timeout",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/modal/backdrop.html",link:function(b){b.animate=!1,a(function(){b.animate=!0})}}}]).directive("modalWindow",["$modalStack","$timeout",function(a,b){return{restrict:"EA",scope:{index:"@",animate:"="},replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/modal/window.html"},link:function(c,d,e){d.addClass(e.windowClass||""),c.size=e.size,b(function(){c.animate=!0,d[0].focus()}),c.close=function(b){var c=a.getTop();c&&c.value.backdrop&&"static"!=c.value.backdrop&&b.target===b.currentTarget&&(b.preventDefault(),b.stopPropagation(),a.dismiss(c.key,"backdrop click"))}}}}]).factory("$modalStack",["$transition","$timeout","$document","$compile","$rootScope","$$stackedMap",function(a,b,c,d,e,f){function g(){for(var a=-1,b=n.keys(),c=0;c<b.length;c++)n.get(b[c]).value.backdrop&&(a=c);return a}function h(a){var b=c.find("body").eq(0),d=n.get(a).value;n.remove(a),j(d.modalDomEl,d.modalScope,300,function(){d.modalScope.$destroy(),b.toggleClass(m,n.length()>0),i()})}function i(){if(k&&-1==g()){var a=l;j(k,l,150,function(){a.$destroy(),a=null}),k=void 0,l=void 0}}function j(c,d,e,f){function g(){g.done||(g.done=!0,c.remove(),f&&f())}d.animate=!1;var h=a.transitionEndEventName;if(h){var i=b(g,e);c.bind(h,function(){b.cancel(i),g(),d.$apply()})}else b(g,0)}var k,l,m="modal-open",n=f.createNew(),o={};return e.$watch(g,function(a){l&&(l.index=a)}),c.bind("keydown",function(a){var b;27===a.which&&(b=n.top(),b&&b.value.keyboard&&(a.preventDefault(),e.$apply(function(){o.dismiss(b.key,"escape key press")})))}),o.open=function(a,b){n.add(a,{deferred:b.deferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard});var f=c.find("body").eq(0),h=g();h>=0&&!k&&(l=e.$new(!0),l.index=h,k=d("<div modal-backdrop></div>")(l),f.append(k));var i=angular.element("<div modal-window></div>");i.attr({"template-url":b.windowTemplateUrl,"window-class":b.windowClass,size:b.size,index:n.length()-1,animate:"animate"}).html(b.content);var j=d(i)(b.scope);n.top().value.modalDomEl=j,f.append(j),f.addClass(m)},o.close=function(a,b){var c=n.get(a).value;c&&(c.deferred.resolve(b),h(a))},o.dismiss=function(a,b){var c=n.get(a).value;c&&(c.deferred.reject(b),h(a))},o.dismissAll=function(a){for(var b=this.getTop();b;)this.dismiss(b.key,a),b=this.getTop()},o.getTop=function(){return n.top()},o}]).provider("$modal",function(){var a={options:{backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$http","$templateCache","$controller","$modalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?d.when(a.template):e.get(a.templateUrl,{cache:f}).then(function(a){return a.data})}function j(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a)))}),c}var k={};return k.open=function(b){var e=d.defer(),f=d.defer(),k={result:e.promise,opened:f.promise,close:function(a){h.close(k,a)},dismiss:function(a){h.dismiss(k,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var l=d.all([i(b)].concat(j(b.resolve)));return l.then(function(a){var d=(b.scope||c).$new();d.$close=k.close,d.$dismiss=k.dismiss;var f,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=k,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),f=g(b.controller,i)),h.open(k,{scope:d,deferred:e,content:a[0],backdrop:b.backdrop,keyboard:b.keyboard,windowClass:b.windowClass,windowTemplateUrl:b.windowTemplateUrl,size:b.size})},function(a){e.reject(a)}),l.then(function(){f.resolve(!0)},function(){f.reject(!1)}),k},k}]};return a}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse",function(a,b,c){var d=this,e={$setViewValue:angular.noop},f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(f,g){e=f,this.config=g,e.$render=function(){d.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){d.itemsPerPage=parseInt(b,10),a.totalPages=d.calculateTotalPages()}):this.itemsPerPage=g.itemsPerPage},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(e.$viewValue,10)||1},a.selectPage=function(b){a.page!==b&&b>0&&b<=a.totalPages&&(e.$setViewValue(b),e.$render())},a.getText=function(b){return a[b+"Text"]||d.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages},a.$watch("totalItems",function(){a.totalPages=d.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),a.page>b?a.selectPage(b):e.$render()})}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(a,b){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@"},require:["pagination","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(c,d,e,f){function g(a,b,c){return{number:a,text:b,active:c}}function h(a,b){var c=[],d=1,e=b,f=angular.isDefined(k)&&b>k;f&&(l?(d=Math.max(a-Math.floor(k/2),1),e=d+k-1,e>b&&(e=b,d=e-k+1)):(d=(Math.ceil(a/k)-1)*k+1,e=Math.min(d+k-1,b)));for(var h=d;e>=h;h++){var i=g(h,h,h===a);c.push(i)}if(f&&!l){if(d>1){var j=g(d-1,"...",!1);c.unshift(j)}if(b>e){var m=g(e+1,"...",!1);c.push(m)}}return c}var i=f[0],j=f[1];if(j){var k=angular.isDefined(e.maxSize)?c.$parent.$eval(e.maxSize):b.maxSize,l=angular.isDefined(e.rotate)?c.$parent.$eval(e.rotate):b.rotate;c.boundaryLinks=angular.isDefined(e.boundaryLinks)?c.$parent.$eval(e.boundaryLinks):b.boundaryLinks,c.directionLinks=angular.isDefined(e.directionLinks)?c.$parent.$eval(e.directionLinks):b.directionLinks,i.init(j,b),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){k=parseInt(a,10),i.render()});var m=i.render;i.render=function(){m(),c.page>0&&c.page<=c.totalPages&&(c.pages=h(c.page,c.totalPages))}}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next Â»",align:!0}).directive("pager",["pagerConfig",function(a){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@"},require:["pager","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(b,c,d,e){var f=e[0],g=e[1];g&&(b.align=angular.isDefined(d.align)?b.$parent.$eval(d.align):a.align,f.init(g,a))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function a(a){var b=/[A-Z]/g,c="-";
-return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0},c={mouseenter:"mouseleave",click:"click",focus:"blur"},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$parse","$document","$position","$interpolate",function(e,f,g,h,i,j,k){return function(e,l,m){function n(a){var b=a||o.trigger||m,d=c[b]||b;return{show:b,hide:d}}var o=angular.extend({},b,d),p=a(e),q=k.startSymbol(),r=k.endSymbol(),s="<div "+p+'-popup title="'+q+"tt_title"+r+'" content="'+q+"tt_content"+r+'" placement="'+q+"tt_placement"+r+'" animation="tt_animation" is-open="tt_isOpen"></div>';return{restrict:"EA",scope:!0,compile:function(){var a=f(s);return function(b,c,d){function f(){b.tt_isOpen?m():k()}function k(){(!y||b.$eval(d[l+"Enable"]))&&(b.tt_popupDelay?v||(v=g(p,b.tt_popupDelay,!1),v.then(function(a){a()})):p()())}function m(){b.$apply(function(){q()})}function p(){return v=null,u&&(g.cancel(u),u=null),b.tt_content?(r(),t.css({top:0,left:0,display:"block"}),w?i.find("body").append(t):c.after(t),z(),b.tt_isOpen=!0,b.$digest(),z):angular.noop}function q(){b.tt_isOpen=!1,g.cancel(v),v=null,b.tt_animation?u||(u=g(s,500)):s()}function r(){t&&s(),t=a(b,function(){}),b.$digest()}function s(){u=null,t&&(t.remove(),t=null)}var t,u,v,w=angular.isDefined(o.appendToBody)?o.appendToBody:!1,x=n(void 0),y=angular.isDefined(d[l+"Enable"]),z=function(){var a=j.positionElements(c,t,b.tt_placement,w);a.top+="px",a.left+="px",t.css(a)};b.tt_isOpen=!1,d.$observe(e,function(a){b.tt_content=a,!a&&b.tt_isOpen&&q()}),d.$observe(l+"Title",function(a){b.tt_title=a}),d.$observe(l+"Placement",function(a){b.tt_placement=angular.isDefined(a)?a:o.placement}),d.$observe(l+"PopupDelay",function(a){var c=parseInt(a,10);b.tt_popupDelay=isNaN(c)?o.popupDelay:c});var A=function(){c.unbind(x.show,k),c.unbind(x.hide,m)};d.$observe(l+"Trigger",function(a){A(),x=n(a),x.show===x.hide?c.bind(x.show,f):(c.bind(x.show,k),c.bind(x.hide,m))});var B=b.$eval(d[l+"Animation"]);b.tt_animation=angular.isDefined(B)?!!B:o.animation,d.$observe(l+"AppendToBody",function(a){w=angular.isDefined(a)?h(a)(b):w}),w&&b.$on("$locationChangeSuccess",function(){b.tt_isOpen&&q()}),b.$on("$destroy",function(){g.cancel(u),g.cancel(v),A(),s()})}}}}}]}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(a){return a("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("progressConfig",{animate:!0,max:100}).controller("ProgressController",["$scope","$attrs","progressConfig",function(a,b,c){var d=this,e=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max,this.addBar=function(b,c){e||c.css({transition:"none"}),this.bars.push(b),b.$watch("value",function(c){b.percent=+(100*c/a.max).toFixed(2)}),b.$on("$destroy",function(){c=null,d.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)}}]).directive("progress",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{},templateUrl:"template/progressbar/progress.html"}}).directive("bar",function(){return{restrict:"EA",replace:!0,transclude:!0,require:"^progress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b)}}}).directive("progressbar",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]))}}}),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","ratingConfig",function(a,b,c){var d={$setViewValue:angular.noop};this.init=function(e){d=e,d.$render=this.render,this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff;var f=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(f)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff},a[b]);return a},a.rate=function(b){!a.readonly&&b>=0&&b<=a.range.length&&(d.$setViewValue(b),d.$render())},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue}}]).directive("rating",function(){return{restrict:"EA",require:["rating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("TabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(b){b.active&&b!==a&&(b.active=!1,b.onDeselect())}),a.active=!0,a.onSelect()},b.addTab=function(a){c.push(a),1===c.length?a.active=!0:a.active&&b.select(a)},b.removeTab=function(a){var d=c.indexOf(a);if(a.active&&c.length>1){var e=d==c.length-1?d-1:d+1;b.select(c[e])}c.splice(d,1)}}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("tab",["$parse",function(a){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(b,c,d){return function(b,c,e,f){b.$watch("active",function(a){a&&f.select(b)}),b.disabled=!1,e.disabled&&b.$parent.$watch(a(e.disabled),function(a){b.disabled=!!a}),b.select=function(){b.disabled||(b.active=!0)},f.addTab(b),b.$on("$destroy",function(){f.removeTab(b)}),b.$transcludeFn=d}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}]).directive("tabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(b,c,d){var e=b.$eval(d.tabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0}).controller("TimepickerController",["$scope","$attrs","$parse","$log","$locale","timepickerConfig",function(a,b,c,d,e,f){function g(){var b=parseInt(a.hours,10),c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c?(a.showMeridian&&(12===b&&(b=0),a.meridian===p[1]&&(b+=12)),b):void 0}function h(){var b=parseInt(a.minutes,10);return b>=0&&60>b?b:void 0}function i(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a}function j(a){k(),o.$setViewValue(new Date(n)),l(a)}function k(){o.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function l(b){var c=n.getHours(),d=n.getMinutes();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:i(c),a.minutes="m"===b?d:i(d),a.meridian=n.getHours()<12?p[0]:p[1]}function m(a){var b=new Date(n.getTime()+6e4*a);n.setHours(b.getHours(),b.getMinutes()),j()}var n=new Date,o={$setViewValue:angular.noop},p=angular.isDefined(b.meridians)?a.$parent.$eval(b.meridians):f.meridians||e.DATETIME_FORMATS.AMPMS;this.init=function(c,d){o=c,o.$render=this.render;var e=d.eq(0),g=d.eq(1),h=angular.isDefined(b.mousewheel)?a.$parent.$eval(b.mousewheel):f.mousewheel;h&&this.setupMousewheelEvents(e,g),a.readonlyInput=angular.isDefined(b.readonlyInput)?a.$parent.$eval(b.readonlyInput):f.readonlyInput,this.setupInputEvents(e,g)};var q=f.hourStep;b.hourStep&&a.$parent.$watch(c(b.hourStep),function(a){q=parseInt(a,10)});var r=f.minuteStep;b.minuteStep&&a.$parent.$watch(c(b.minuteStep),function(a){r=parseInt(a,10)}),a.showMeridian=f.showMeridian,b.showMeridian&&a.$parent.$watch(c(b.showMeridian),function(b){if(a.showMeridian=!!b,o.$error.time){var c=g(),d=h();angular.isDefined(c)&&angular.isDefined(d)&&(n.setHours(c),j())}else l()}),this.setupMousewheelEvents=function(b,c){var d=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()})},this.setupInputEvents=function(b,c){if(a.readonlyInput)return a.updateHours=angular.noop,void(a.updateMinutes=angular.noop);var d=function(b,c){o.$setViewValue(null),o.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b),angular.isDefined(c)&&(a.invalidMinutes=c)};a.updateHours=function(){var a=g();angular.isDefined(a)?(n.setHours(a),j("h")):d(!0)},b.bind("blur",function(){!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=i(a.hours)})}),a.updateMinutes=function(){var a=h();angular.isDefined(a)?(n.setMinutes(a),j("m")):d(void 0,!0)},c.bind("blur",function(){!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=i(a.minutes)})})},this.render=function(){var a=o.$modelValue?new Date(o.$modelValue):null;isNaN(a)?(o.$setValidity("time",!1),d.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(a&&(n=a),k(),l())},a.incrementHours=function(){m(60*q)},a.decrementHours=function(){m(60*-q)},a.incrementMinutes=function(){m(r)},a.decrementMinutes=function(){m(-r)},a.toggleMeridian=function(){m(720*(n.getHours()<12?1:-1))}}]).directive("timepicker",function(){return{restrict:"EA",require:["timepicker","?^ngModel"],controller:"TimepickerController",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(a){var b=/^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(a,b,c,d,e,f,g){var h=[9,13,27,38,40];return{require:"ngModel",link:function(i,j,k,l){var m,n=i.$eval(k.typeaheadMinLength)||1,o=i.$eval(k.typeaheadWaitMs)||0,p=i.$eval(k.typeaheadEditable)!==!1,q=b(k.typeaheadLoading).assign||angular.noop,r=b(k.typeaheadOnSelect),s=k.typeaheadInputFormatter?b(k.typeaheadInputFormatter):void 0,t=k.typeaheadAppendToBody?i.$eval(k.typeaheadAppendToBody):!1,u=b(k.ngModel).assign,v=g.parse(k.typeahead),w=i.$new();i.$on("$destroy",function(){w.$destroy()});var x="typeahead-"+w.$id+"-"+Math.floor(1e4*Math.random());j.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":x});var y=angular.element("<div typeahead-popup></div>");y.attr({id:x,matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(k.typeaheadTemplateUrl)&&y.attr("template-url",k.typeaheadTemplateUrl);var z=function(){w.matches=[],w.activeIdx=-1,j.attr("aria-expanded",!1)},A=function(a){return x+"-option-"+a};w.$watch("activeIdx",function(a){0>a?j.removeAttr("aria-activedescendant"):j.attr("aria-activedescendant",A(a))});var B=function(a){var b={$viewValue:a};q(i,!0),c.when(v.source(i,b)).then(function(c){var d=a===l.$viewValue;if(d&&m)if(c.length>0){w.activeIdx=0,w.matches.length=0;for(var e=0;e<c.length;e++)b[v.itemName]=c[e],w.matches.push({id:A(e),label:v.viewMapper(w,b),model:c[e]});w.query=a,w.position=t?f.offset(j):f.position(j),w.position.top=w.position.top+j.prop("offsetHeight"),j.attr("aria-expanded",!0)}else z();d&&q(i,!1)},function(){z(),q(i,!1)})};z(),w.query=void 0;var C;l.$parsers.unshift(function(a){return m=!0,a&&a.length>=n?o>0?(C&&d.cancel(C),C=d(function(){B(a)},o)):B(a):(q(i,!1),z()),p?a:a?void l.$setValidity("editable",!1):(l.$setValidity("editable",!0),a)}),l.$formatters.push(function(a){var b,c,d={};return s?(d.$model=a,s(i,d)):(d[v.itemName]=a,b=v.viewMapper(i,d),d[v.itemName]=void 0,c=v.viewMapper(i,d),b!==c?b:a)}),w.select=function(a){var b,c,e={};e[v.itemName]=c=w.matches[a].model,b=v.modelMapper(i,e),u(i,b),l.$setValidity("editable",!0),r(i,{$item:c,$model:b,$label:v.viewMapper(i,e)}),z(),d(function(){j[0].focus()},0,!1)},j.bind("keydown",function(a){0!==w.matches.length&&-1!==h.indexOf(a.which)&&(a.preventDefault(),40===a.which?(w.activeIdx=(w.activeIdx+1)%w.matches.length,w.$digest()):38===a.which?(w.activeIdx=(w.activeIdx?w.activeIdx:w.matches.length)-1,w.$digest()):13===a.which||9===a.which?w.$apply(function(){w.select(w.activeIdx)}):27===a.which&&(a.stopPropagation(),z(),w.$digest()))}),j.bind("blur",function(){m=!1});var D=function(a){j[0]!==a.target&&(z(),w.$digest())};e.bind("click",D),i.$on("$destroy",function(){e.unbind("click",D)});var E=a(y)(w);t?e.find("body").append(E):j.after(E)}}}]).directive("typeaheadPopup",function(){return{restrict:"EA",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("typeaheadMatch",["$http","$templateCache","$compile","$parse",function(a,b,c,d){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(e,f,g){var h=d(g.templateUrl)(e.$parent)||"template/typeahead/typeahead-match.html";a.get(h,{cache:b}).success(function(a){f.replaceWith(c(a.trim())(e))})}}}]).filter("typeaheadHighlight",function(){function a(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c){return c?(""+b).replace(new RegExp(a(c),"gi"),"<strong>$&</strong>"):b}}),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion-group.html",'<div class="panel panel-default">\n  <div class="panel-heading">\n    <h4 class="panel-title">\n      <a class="accordion-toggle" ng-click="toggleOpen()" accordion-transclude="heading"><span ng-class="{\'text-muted\': isDisabled}">{{heading}}</span></a>\n    </h4>\n  </div>\n  <div class="panel-collapse" collapse="!isOpen">\n   <div class="panel-body" ng-transclude></div>\n  </div>\n</div>')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion.html",'<div class="panel-group" ng-transclude></div>')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(a){a.put("template/alert/alert.html",'<div class="alert" ng-class="{\'alert-{{type || \'warning\'}}\': true, \'alert-dismissable\': closeable}" role="alert">\n    <button ng-show="closeable" type="button" class="close" ng-click="close()">\n        <span aria-hidden="true">&times;</span>\n        <span class="sr-only">Close</span>\n    </button>\n    <div ng-transclude></div>\n</div>\n')}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(a){a.put("template/carousel/carousel.html",'<div ng-mouseenter="pause()" ng-mouseleave="play()" class="carousel" ng-swipe-right="prev()" ng-swipe-left="next()">\n    <ol class="carousel-indicators" ng-show="slides.length > 1">\n        <li ng-repeat="slide in slides track by $index" ng-class="{active: isActive(slide)}" ng-click="select(slide)"></li>\n    </ol>\n    <div class="carousel-inner" ng-transclude></div>\n    <a class="left carousel-control" ng-click="prev()" ng-show="slides.length > 1"><span class="glyphicon glyphicon-chevron-left"></span></a>\n    <a class="right carousel-control" ng-click="next()" ng-show="slides.length > 1"><span class="glyphicon glyphicon-chevron-right"></span></a>\n</div>\n')}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("template/carousel/slide.html","<div ng-class=\"{\n    'active': leaving || (active && !entering),\n    'prev': (next || active) && direction=='prev',\n    'next': (next || active) && direction=='next',\n    'right': direction=='prev',\n    'left': direction=='next'\n  }\" class=\"item text-center\" ng-transclude></div>\n")}]),angular.module("template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/datepicker.html",'<div ng-switch="datepickerMode" role="application" ng-keydown="keydown($event)">\n  <daypicker ng-switch-when="day" tabindex="0"></daypicker>\n  <monthpicker ng-switch-when="month" tabindex="0"></monthpicker>\n  <yearpicker ng-switch-when="year" tabindex="0"></yearpicker>\n</div>')}]),angular.module("template/datepicker/day.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/day.html",'<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n  <thead>\n    <tr>\n      <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n      <th colspan="{{5 + showWeeks}}"><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n      <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n    </tr>\n    <tr>\n      <th ng-show="showWeeks" class="text-center"></th>\n      <th ng-repeat="label in labels track by $index" class="text-center"><small aria-label="{{label.full}}">{{label.abbr}}</small></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr ng-repeat="row in rows track by $index">\n      <td ng-show="showWeeks" class="text-center h6"><em>{{ weekNumbers[$index] }}</em></td>\n      <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}">\n        <button type="button" style="width:100%;" class="btn btn-default btn-sm" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{\'text-muted\': dt.secondary, \'text-info\': dt.current}">{{dt.label}}</span></button>\n      </td>\n    </tr>\n  </tbody>\n</table>\n')}]),angular.module("template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/month.html",'<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n  <thead>\n    <tr>\n      <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n      <th><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n      <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr ng-repeat="row in rows track by $index">\n      <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}">\n        <button type="button" style="width:100%;" class="btn btn-default" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{\'text-info\': dt.current}">{{dt.label}}</span></button>\n      </td>\n    </tr>\n  </tbody>\n</table>\n')}]),angular.module("template/datepicker/popup.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/popup.html",'<ul class="dropdown-menu" ng-style="{display: (isOpen && \'block\') || \'none\', top: position.top+\'px\', left: position.left+\'px\'}" ng-keydown="keydown($event)">\n   <li ng-transclude></li>\n       <li ng-if="showButtonBar" style="padding:10px 9px 2px">\n               <span class="btn-group">\n                      <button type="button" class="btn btn-sm btn-info" ng-click="select(\'today\')">{{ getText(\'current\') }}</button>\n                    <button type="button" class="btn btn-sm btn-danger" ng-click="select(null)">{{ getText(\'clear\') }}</button>\n         </span>\n               <button type="button" class="btn btn-sm btn-success pull-right" ng-click="close()">{{ getText(\'close\') }}</button>\n  </li>\n</ul>\n')}]),angular.module("template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/year.html",'<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n  <thead>\n    <tr>\n      <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n      <th colspan="3"><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n      <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr ng-repeat="row in rows track by $index">\n      <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}">\n        <button type="button" style="width:100%;" class="btn btn-default" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{\'text-info\': dt.current}">{{dt.label}}</span></button>\n      </td>\n    </tr>\n  </tbody>\n</table>\n')}]),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(a){a.put("template/modal/backdrop.html",'<div class="modal-backdrop fade"\n     ng-class="{in: animate}"\n     ng-style="{\'z-index\': 1040 + (index && 1 || 0) + index*10}"\n></div>\n')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(a){a.put("template/modal/window.html",'<div tabindex="-1" role="dialog" class="modal fade" ng-class="{in: animate}" ng-style="{\'z-index\': 1050 + index*10, display: \'block\'}" ng-click="close($event)">\n    <div class="modal-dialog" ng-class="{\'modal-sm\': size == \'sm\', \'modal-lg\': size == \'lg\'}"><div class="modal-content" ng-transclude></div></div>\n</div>')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pager.html",'<ul class="pager">\n  <li ng-class="{disabled: noPrevious(), previous: align}"><a href ng-click="selectPage(page - 1)">{{getText(\'previous\')}}</a></li>\n  <li ng-class="{disabled: noNext(), next: align}"><a href ng-click="selectPage(page + 1)">{{getText(\'next\')}}</a></li>\n</ul>')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pagination.html",'<ul class="pagination">\n  <li ng-if="boundaryLinks" ng-class="{disabled: noPrevious()}"><a href ng-click="selectPage(1)">{{getText(\'first\')}}</a></li>\n  <li ng-if="directionLinks" ng-class="{disabled: noPrevious()}"><a href ng-click="selectPage(page - 1)">{{getText(\'previous\')}}</a></li>\n  <li ng-repeat="page in pages track by $index" ng-class="{active: page.active}"><a href ng-click="selectPage(page.number)">{{page.text}}</a></li>\n  <li ng-if="directionLinks" ng-class="{disabled: noNext()}"><a href ng-click="selectPage(page + 1)">{{getText(\'next\')}}</a></li>\n  <li ng-if="boundaryLinks" ng-class="{disabled: noNext()}"><a href ng-click="selectPage(totalPages)">{{getText(\'last\')}}</a></li>\n</ul>')}]),angular.module("template/tooltip/tooltip-html-unsafe-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-unsafe-popup.html",'<div class="tooltip {{placement}}" ng-class="{ in: isOpen(), fade: animation() }">\n  <div class="tooltip-arrow"></div>\n  <div class="tooltip-inner" bind-html-unsafe="content"></div>\n</div>\n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-popup.html",'<div class="tooltip {{placement}}" ng-class="{ in: isOpen(), fade: animation() }">\n  <div class="tooltip-arrow"></div>\n  <div class="tooltip-inner" ng-bind="content"></div>\n</div>\n')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover.html",'<div class="popover {{placement}}" ng-class="{ in: isOpen(), fade: animation() }">\n  <div class="arrow"></div>\n\n  <div class="popover-inner">\n      <h3 class="popover-title" ng-bind="title" ng-show="title"></h3>\n      <div class="popover-content" ng-bind="content"></div>\n  </div>\n</div>\n')}]),angular.module("template/progressbar/bar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/bar.html",'<div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: percent + \'%\'}" aria-valuetext="{{percent | number:0}}%" ng-transclude></div>')}]),angular.module("template/progressbar/progress.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progress.html",'<div class="progress" ng-transclude></div>')}]),angular.module("template/progressbar/progressbar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progressbar.html",'<div class="progress">\n  <div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: percent + \'%\'}" aria-valuetext="{{percent | number:0}}%" ng-transclude></div>\n</div>')}]),angular.module("template/rating/rating.html",[]).run(["$templateCache",function(a){a.put("template/rating/rating.html",'<span ng-mouseleave="reset()" ng-keydown="onKeydown($event)" tabindex="0" role="slider" aria-valuemin="0" aria-valuemax="{{range.length}}" aria-valuenow="{{value}}">\n    <i ng-repeat="r in range track by $index" ng-mouseenter="enter($index + 1)" ng-click="rate($index + 1)" class="glyphicon" ng-class="$index < value && (r.stateOn || \'glyphicon-star\') || (r.stateOff || \'glyphicon-star-empty\')">\n        <span class="sr-only">({{ $index < value ? \'*\' : \' \' }})</span>\n    </i>\n</span>')}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tab.html",'<li ng-class="{active: active, disabled: disabled}">\n  <a ng-click="select()" tab-heading-transclude>{{heading}}</a>\n</li>\n')}]),angular.module("template/tabs/tabset-titles.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset-titles.html","<ul class=\"nav {{type && 'nav-' + type}}\" ng-class=\"{'nav-stacked': vertical}\">\n</ul>\n")}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset.html",'\n<div>\n  <ul class="nav nav-{{type || \'tabs\'}}" ng-class="{\'nav-stacked\': vertical, \'nav-justified\': justified}" ng-transclude></ul>\n  <div class="tab-content">\n    <div class="tab-pane" \n         ng-repeat="tab in tabs" \n         ng-class="{active: tab.active}"\n         tab-content-transclude="tab">\n    </div>\n  </div>\n</div>\n')}]),angular.module("template/timepicker/timepicker.html",[]).run(["$templateCache",function(a){a.put("template/timepicker/timepicker.html",'<table>\n        <tbody>\n               <tr class="text-center">\n                      <td><a ng-click="incrementHours()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n                 <td>&nbsp;</td>\n                       <td><a ng-click="incrementMinutes()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n                       <td ng-show="showMeridian"></td>\n              </tr>\n         <tr>\n                  <td style="width:50px;" class="form-group" ng-class="{\'has-error\': invalidHours}">\n                          <input type="text" ng-model="hours" ng-change="updateHours()" class="form-control text-center" ng-mousewheel="incrementHours()" ng-readonly="readonlyInput" maxlength="2">\n                    </td>\n                 <td>:</td>\n                    <td style="width:50px;" class="form-group" ng-class="{\'has-error\': invalidMinutes}">\n                                <input type="text" ng-model="minutes" ng-change="updateMinutes()" class="form-control text-center" ng-readonly="readonlyInput" maxlength="2">\n                 </td>\n                 <td ng-show="showMeridian"><button type="button" class="btn btn-default text-center" ng-click="toggleMeridian()">{{meridian}}</button></td>\n           </tr>\n         <tr class="text-center">\n                      <td><a ng-click="decrementHours()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n                       <td>&nbsp;</td>\n                       <td><a ng-click="decrementMinutes()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n                     <td ng-show="showMeridian"></td>\n              </tr>\n </tbody>\n</table>\n')}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-match.html",'<a tabindex="-1" bind-html-unsafe="match.label | typeaheadHighlight:query"></a>')}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-popup.html",'<ul class="dropdown-menu" ng-if="isOpen()" ng-style="{top: position.top+\'px\', left: position.left+\'px\'}" style="display: block;" role="listbox" aria-hidden="{{!isOpen()}}">\n    <li ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index)" role="option" id="{{match.id}}">\n        <div typeahead-match index="$index" match="match" query="query" template-url="templateUrl"></div>\n    </li>\n</ul>')
-}]);
\ No newline at end of file
+angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.tpls",["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/day.html","template/datepicker/month.html","template/datepicker/popup.html","template/datepicker/year.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(a,b,c){function d(a){for(var b in a)if(void 0!==f.style[b])return a[b]}var e=function(d,f,g){g=g||{};var h=a.defer(),i=e[g.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(f)?d.addClass(f):angular.isFunction(f)?f(d):angular.isObject(f)&&d.css(f),i||h.resolve(d)}),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},f=document.createElement("trans"),g={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},h={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return e.transitionEndEventName=d(g),e.animationEndEventName=d(h),e}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(a){return{link:function(b,c,d){function e(b){function d(){j===e&&(j=void 0)}var e=a(c,b);return j&&j.cancel(),j=e,e.then(d,d),e}function f(){k?(k=!1,g()):(c.removeClass("collapse").addClass("collapsing"),e({height:c[0].scrollHeight+"px"}).then(g))}function g(){c.removeClass("collapsing"),c.addClass("collapse in"),c.css({height:"auto"})}function h(){if(k)k=!1,i(),c.css({height:0});else{c.css({height:c[0].scrollHeight+"px"});{c[0].offsetWidth}c.removeClass("collapse in").addClass("collapsing"),e({height:0}).then(i)}}function i(){c.removeClass("collapsing"),c.addClass("collapse")}var j,k=!0;b.$watch(d.collapse,function(a){a?h():f()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",function(){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){d.addGroup(a),a.$watch("isOpen",function(b){b&&d.closeOthers(a)}),a.toggleOpen=function(){a.isDisabled||(a.isOpen=!a.isOpen)}}}}).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,function(){}))}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(a,b,c,d){a.$watch(function(){return d[c.accordionTransclude]},function(a){a&&(b.html(""),b.append(a))})}}}),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(a,b){a.closeable="close"in b,this.close=a.close}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}).directive("dismissOnTimeout",["$timeout",function(a){return{require:"alert",link:function(b,c,d,e){a(function(){e.close()},parseInt(d.dismissOnTimeout,10))}}}]),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(a,b,c){b.addClass("ng-binding").data("$binding",c.bindHtmlUnsafe),a.$watch(c.bindHtmlUnsafe,function(a){b.html(a||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).controller("ButtonsController",["buttonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("btnRadio",function(){return{require:["btnRadio","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){var e=d[0],f=d[1];f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.btnRadio)))},b.bind(e.toggleEvent,function(){var d=b.hasClass(e.activeClass);(!d||angular.isDefined(c.uncheckable))&&a.$apply(function(){f.$setViewValue(d?null:a.$eval(c.btnRadio)),f.$render()})})}}}).directive("btnCheckbox",function(){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){var d=a.$eval(b);return angular.isDefined(d)?d:c}var h=d[0],i=d[1];i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.bind(h.toggleEvent,function(){a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$interval","$transition",function(a,b,c,d){function e(){f();var b=+a.interval;!isNaN(b)&&b>0&&(h=c(g,b))}function f(){h&&(c.cancel(h),h=null)}function g(){var b=+a.interval;i&&!isNaN(b)&&b>0?a.next():a.pause()}var h,i,j=this,k=j.slides=a.slides=[],l=-1;j.currentSlide=null;var m=!1;j.select=a.select=function(c,f){function g(){if(!m){if(j.currentSlide&&angular.isString(f)&&!a.noTransition&&c.$element){c.$element.addClass(f);{c.$element[0].offsetWidth}angular.forEach(k,function(a){angular.extend(a,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(c,{direction:f,active:!0,entering:!0}),angular.extend(j.currentSlide||{},{direction:f,leaving:!0}),a.$currentTransition=d(c.$element,{}),function(b,c){a.$currentTransition.then(function(){h(b,c)},function(){h(b,c)})}(c,j.currentSlide)}else h(c,j.currentSlide);j.currentSlide=c,l=i,e()}}function h(b,c){angular.extend(b,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(c||{},{direction:"",active:!1,leaving:!1,entering:!1}),a.$currentTransition=null}var i=k.indexOf(c);void 0===f&&(f=i>l?"next":"prev"),c&&c!==j.currentSlide&&(a.$currentTransition?(a.$currentTransition.cancel(),b(g)):g())},a.$on("$destroy",function(){m=!0}),j.indexOfSlide=function(a){return k.indexOf(a)},a.next=function(){var b=(l+1)%k.length;return a.$currentTransition?void 0:j.select(k[b],"next")},a.prev=function(){var b=0>l-1?k.length-1:l-1;return a.$currentTransition?void 0:j.select(k[b],"prev")},a.isActive=function(a){return j.currentSlide===a},a.$watch("interval",e),a.$on("$destroy",f),a.play=function(){i||(i=!0,e())},a.pause=function(){a.noPause||(i=!1,f())},j.addSlide=function(b,c){b.$element=c,k.push(b),1===k.length||b.active?(j.select(k[k.length-1]),1==k.length&&a.play()):b.active=!1},j.removeSlide=function(a){var b=k.indexOf(a);k.splice(b,1),k.length>0&&a.active?j.select(b>=k.length?k[b-1]:k[b]):l>b&&l--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",function(){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{active:"=?"},link:function(a,b,c,d){d.addSlide(a,b),a.$on("$destroy",function(){d.removeSlide(a)}),a.$watch("active",function(b){b&&d.select(a)})}}}),angular.module("ui.bootstrap.dateparser",[]).service("dateParser",["$locale","orderByFilter",function(a,b){function c(a){var c=[],d=a.split("");return angular.forEach(e,function(b,e){var f=a.indexOf(e);if(f>-1){a=a.split(""),d[f]="("+b.regex+")",a[f]="$";for(var g=f+1,h=f+e.length;h>g;g++)d[g]="",a[g]="$";a=a.join(""),c.push({index:f,apply:b.apply})}}),{regex:new RegExp("^"+d.join("")+"$"),map:b(c,"index")}}function d(a,b,c){return 1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}this.parsers={};var e={yyyy:{regex:"\\d{4}",apply:function(a){this.year=+a}},yy:{regex:"\\d{2}",apply:function(a){this.year=+a+2e3}},y:{regex:"\\d{1,4}",apply:function(a){this.year=+a}},MMMM:{regex:a.DATETIME_FORMATS.MONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.MONTH.indexOf(b)}},MMM:{regex:a.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.SHORTMONTH.indexOf(b)}},MM:{regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1}},M:{regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1}},dd:{regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},d:{regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},EEEE:{regex:a.DATETIME_FORMATS.DAY.join("|")},EEE:{regex:a.DATETIME_FORMATS.SHORTDAY.join("|")}};this.parse=function(b,e){if(!angular.isString(b)||!e)return b;e=a.DATETIME_FORMATS[e]||e,this.parsers[e]||(this.parsers[e]=c(e));var f=this.parsers[e],g=f.regex,h=f.map,i=b.match(g);if(i&&i.length){for(var j,k={year:1900,month:0,date:1,hours:0},l=1,m=i.length;m>l;l++){var n=h[l-1];n.apply&&n.apply.call(k,i[l])}return d(k.year,k.month,k.date)&&(j=new Date(k.year,k.month,k.date,k.hours)),j}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].documentElement.scrollLeft)}},positionElements:function(a,b,c,d){var e,f,g,h,i=c.split("-"),j=i[0],k=i[1]||"center";e=d?this.offset(a):this.position(a),f=b.prop("offsetWidth"),g=b.prop("offsetHeight");var l={center:function(){return e.left+e.width/2-f/2},left:function(){return e.left},right:function(){return e.left+e.width}},m={center:function(){return e.top+e.height/2-g/2},top:function(){return e.top},bottom:function(){return e.top+e.height}};switch(j){case"right":h={top:m[k](),left:l[j]()};break;case"left":h={top:m[k](),left:e.left-f};break;case"bottom":h={top:m[j](),left:l[k]()};break;default:h={top:e.top-g,left:l[k]()}}return h}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.position"]).constant("datepickerConfig",{formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",datepickerMode:"day",minMode:"day",maxMode:"year",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null}).controller("DatepickerController",["$scope","$attrs","$parse","$interpolate","$timeout","$log","dateFilter","datepickerConfig",function(a,b,c,d,e,f,g,h){var i=this,j={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","minMode","maxMode","showWeeks","startingDay","yearRange"],function(c,e){i[c]=angular.isDefined(b[c])?8>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):h[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){i[d]=a?new Date(a):null,i.refreshView()}):i[d]=h[d]?new Date(h[d]):null}),a.datepickerMode=a.datepickerMode||h.datepickerMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),this.activeDate=angular.isDefined(b.initDate)?a.$parent.$eval(b.initDate):new Date,a.isActive=function(b){return 0===i.compare(b.date,i.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){j=a,j.$render=function(){i.render()}},this.render=function(){if(j.$modelValue){var a=new Date(j.$modelValue),b=!isNaN(a);b?this.activeDate=a:f.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'),j.$setValidity("date",b)}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=j.$modelValue?new Date(j.$modelValue):null;j.$setValidity("date-disabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=j.$modelValue?new Date(j.$modelValue):null;return{date:a,label:g(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===i.minMode){var c=j.$modelValue?new Date(j.$modelValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),j.$setViewValue(c),j.$render()}else i.activeDate=b,a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=i.activeDate.getFullYear()+a*(i.step.years||0),c=i.activeDate.getMonth()+a*(i.step.months||0);i.activeDate.setFullYear(b,c,1),i.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===i.maxMode&&1===b||a.datepickerMode===i.minMode&&-1===b||(a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var k=function(){e(function(){i.element[0].focus()},0,!1)};a.$on("datepicker.focus",k),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),b.stopPropagation(),"enter"===c||"space"===c){if(i.isDisabled(i.activeDate))return;a.select(i.activeDate),k()}else!b.ctrlKey||"up"!==c&&"down"!==c?(i.handleKeyDown(c,b),i.refreshView()):(a.toggleMode("up"===c?1:-1),k())}}]).directive("datepicker",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{datepickerMode:"=?",dateDisabled:"&"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}).directive("daypicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/day.html",require:"^datepicker",link:function(b,c,d,e){function f(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?i[b]:29}function g(a,b){var c=new Array(b),d=new Date(a),e=0;for(d.setHours(12);b>e;)c[e++]=new Date(d),d.setDate(d.getDate()+1);return c}function h(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}b.showWeeks=e.showWeeks,e.step={months:1},e.element=c;var i=[31,28,31,30,31,30,31,31,30,31,30,31];e._refreshView=function(){var c=e.activeDate.getFullYear(),d=e.activeDate.getMonth(),f=new Date(c,d,1),i=e.startingDay-f.getDay(),j=i>0?7-i:-i,k=new Date(f);j>0&&k.setDate(-j+1);for(var l=g(k,42),m=0;42>m;m++)l[m]=angular.extend(e.createDateObject(l[m],e.formatDay),{secondary:l[m].getMonth()!==d,uid:b.uniqueId+"-"+m});b.labels=new Array(7);for(var n=0;7>n;n++)b.labels[n]={abbr:a(l[n].date,e.formatDayHeader),full:a(l[n].date,"EEEE")};if(b.title=a(e.activeDate,e.formatDayTitle),b.rows=e.split(l,7),b.showWeeks){b.weekNumbers=[];for(var o=h(b.rows[0][0].date),p=b.rows.length;b.weekNumbers.push(o++)<p;);}},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},e.handleKeyDown=function(a){var b=e.activeDate.getDate();if("left"===a)b-=1;else if("up"===a)b-=7;else if("right"===a)b+=1;else if("down"===a)b+=7;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getMonth()+("pageup"===a?-1:1);e.activeDate.setMonth(c,1),b=Math.min(f(e.activeDate.getFullYear(),e.activeDate.getMonth()),b)}else"home"===a?b=1:"end"===a&&(b=f(e.activeDate.getFullYear(),e.activeDate.getMonth()));e.activeDate.setDate(b)},e.refreshView()}}}]).directive("monthpicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/month.html",require:"^datepicker",link:function(b,c,d,e){e.step={years:1},e.element=c,e._refreshView=function(){for(var c=new Array(12),d=e.activeDate.getFullYear(),f=0;12>f;f++)c[f]=angular.extend(e.createDateObject(new Date(d,f,1),e.formatMonth),{uid:b.uniqueId+"-"+f});b.title=a(e.activeDate,e.formatMonthTitle),b.rows=e.split(c,3)},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},e.handleKeyDown=function(a){var b=e.activeDate.getMonth();if("left"===a)b-=1;else if("up"===a)b-=3;else if("right"===a)b+=1;else if("down"===a)b+=3;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getFullYear()+("pageup"===a?-1:1);e.activeDate.setFullYear(c)}else"home"===a?b=0:"end"===a&&(b=11);e.activeDate.setMonth(b)},e.refreshView()}}}]).directive("yearpicker",["dateFilter",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/year.html",require:"^datepicker",link:function(a,b,c,d){function e(a){return parseInt((a-1)/f,10)*f+1}var f=d.yearRange;d.step={years:f},d.element=b,d._refreshView=function(){for(var b=new Array(f),c=0,g=e(d.activeDate.getFullYear());f>c;c++)b[c]=angular.extend(d.createDateObject(new Date(g+c,0,1),d.formatYear),{uid:a.uniqueId+"-"+c});a.title=[b[0].label,b[f-1].label].join(" - "),a.rows=d.split(b,5)},d.compare=function(a,b){return a.getFullYear()-b.getFullYear()},d.handleKeyDown=function(a){var b=d.activeDate.getFullYear();"left"===a?b-=1:"up"===a?b-=5:"right"===a?b+=1:"down"===a?b+=5:"pageup"===a||"pagedown"===a?b+=("pageup"===a?-1:1)*d.step.years:"home"===a?b=e(d.activeDate.getFullYear()):"end"===a&&(b=e(d.activeDate.getFullYear())+f-1),d.activeDate.setFullYear(b)},d.refreshView()}}}]).constant("datepickerPopupConfig",{datepickerPopup:"yyyy-MM-dd",currentText:"Today",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","dateParser","datepickerPopupConfig",function(a,b,c,d,e,f,g){return{restrict:"EA",require:"ngModel",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&"},link:function(h,i,j,k){function l(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function m(a){if(a){if(angular.isDate(a)&&!isNaN(a))return k.$setValidity("date",!0),a;if(angular.isString(a)){var b=f.parse(a,n)||new Date(a);return isNaN(b)?void k.$setValidity("date",!1):(k.$setValidity("date",!0),b)}return void k.$setValidity("date",!1)}return k.$setValidity("date",!0),null}var n,o=angular.isDefined(j.closeOnDateSelection)?h.$parent.$eval(j.closeOnDateSelection):g.closeOnDateSelection,p=angular.isDefined(j.datepickerAppendToBody)?h.$parent.$eval(j.datepickerAppendToBody):g.appendToBody;h.showButtonBar=angular.isDefined(j.showButtonBar)?h.$parent.$eval(j.showButtonBar):g.showButtonBar,h.getText=function(a){return h[a+"Text"]||g[a+"Text"]},j.$observe("datepickerPopup",function(a){n=a||g.datepickerPopup,k.$render()});var q=angular.element("<div datepicker-popup-wrap><div datepicker></div></div>");q.attr({"ng-model":"date","ng-change":"dateSelection()"});var r=angular.element(q.children()[0]);j.datepickerOptions&&angular.forEach(h.$parent.$eval(j.datepickerOptions),function(a,b){r.attr(l(b),a)}),h.watchData={},angular.forEach(["minDate","maxDate","datepickerMode"],function(a){if(j[a]){var c=b(j[a]);if(h.$parent.$watch(c,function(b){h.watchData[a]=b}),r.attr(l(a),"watchData."+a),"datepickerMode"===a){var d=c.assign;h.$watch("watchData."+a,function(a,b){a!==b&&d(h.$parent,a)})}}}),j.dateDisabled&&r.attr("date-disabled","dateDisabled({ date: date, mode: mode })"),k.$parsers.unshift(m),h.dateSelection=function(a){angular.isDefined(a)&&(h.date=a),k.$setViewValue(h.date),k.$render(),o&&(h.isOpen=!1,i[0].focus())},i.bind("input change keyup",function(){h.$apply(function(){h.date=k.$modelValue})}),k.$render=function(){var a=k.$viewValue?e(k.$viewValue,n):"";i.val(a),h.date=m(k.$modelValue)};var s=function(a){h.isOpen&&a.target!==i[0]&&h.$apply(function(){h.isOpen=!1})},t=function(a){h.keydown(a)};i.bind("keydown",t),h.keydown=function(a){27===a.which?(a.preventDefault(),a.stopPropagation(),h.close()):40!==a.which||h.isOpen||(h.isOpen=!0)},h.$watch("isOpen",function(a){a?(h.$broadcast("datepicker.focus"),h.position=p?d.offset(i):d.position(i),h.position.top=h.position.top+i.prop("offsetHeight"),c.bind("click",s)):c.unbind("click",s)}),h.select=function(a){if("today"===a){var b=new Date;angular.isDate(k.$modelValue)?(a=new Date(k.$modelValue),a.setFullYear(b.getFullYear(),b.getMonth(),b.getDate())):a=new Date(b.setHours(0,0,0,0))}h.dateSelection(a)},h.close=function(){h.isOpen=!1,i[0].focus()};var u=a(q)(h);q.remove(),p?c.find("body").append(u):i.after(u),h.$on("$destroy",function(){u.remove(),i.unbind("keydown",t),c.unbind("click",s)})}}}]).directive("datepickerPopupWrap",function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(a,b){b.bind("click",function(a){a.preventDefault(),a.stopPropagation()})}}}),angular.module("ui.bootstrap.dropdown",[]).constant("dropdownConfig",{openClass:"open"}).service("dropdownService",["$document",function(a){var b=null;this.open=function(e){b||(a.bind("click",c),a.bind("keydown",d)),b&&b!==e&&(b.isOpen=!1),b=e},this.close=function(e){b===e&&(b=null,a.unbind("click",c),a.unbind("keydown",d))};var c=function(a){if(b){var c=b.getToggleElement();a&&c&&c[0].contains(a.target)||b.$apply(function(){b.isOpen=!1})}},d=function(a){27===a.which&&(b.focusToggleElement(),c())}}]).controller("DropdownController",["$scope","$attrs","$parse","dropdownConfig","dropdownService","$animate",function(a,b,c,d,e,f){var g,h=this,i=a.$new(),j=d.openClass,k=angular.noop,l=b.onToggle?c(b.onToggle):angular.noop;this.init=function(d){h.$element=d,b.isOpen&&(g=c(b.isOpen),k=g.assign,a.$watch(g,function(a){i.isOpen=!!a}))},this.toggle=function(a){return i.isOpen=arguments.length?!!a:!i.isOpen},this.isOpen=function(){return i.isOpen},i.getToggleElement=function(){return h.toggleElement},i.focusToggleElement=function(){h.toggleElement&&h.toggleElement[0].focus()},i.$watch("isOpen",function(b,c){f[b?"addClass":"removeClass"](h.$element,j),b?(i.focusToggleElement(),e.open(i)):e.close(i),k(a,b),angular.isDefined(b)&&b!==c&&l(a,{open:!!b})}),a.$on("$locationChangeSuccess",function(){i.isOpen=!1}),a.$on("$destroy",function(){i.$destroy()})}]).directive("dropdown",function(){return{controller:"DropdownController",link:function(a,b,c,d){d.init(b)}}}).directive("dropdownToggle",function(){return{require:"?^dropdown",link:function(a,b,c,d){if(d){d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.modal",["ui.bootstrap.transition"]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c<a.length;c++)if(b==a[c].key)return a[c]},keys:function(){for(var b=[],c=0;c<a.length;c++)b.push(a[c].key);return b},top:function(){return a[a.length-1]},remove:function(b){for(var c=-1,d=0;d<a.length;d++)if(b==a[d].key){c=d;break}return a.splice(c,1)[0]},removeTop:function(){return a.splice(a.length-1,1)[0]},length:function(){return a.length}}}}}).directive("modalBackdrop",["$timeout",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/modal/backdrop.html",link:function(b,c,d){b.backdropClass=d.backdropClass||"",b.animate=!1,a(function(){b.animate=!0})}}}]).directive("modalWindow",["$modalStack","$timeout",function(a,b){return{restrict:"EA",scope:{index:"@",animate:"="},replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/modal/window.html"},link:function(c,d,e){d.addClass(e.windowClass||""),c.size=e.size,b(function(){c.animate=!0,d[0].querySelectorAll("[autofocus]").length||d[0].focus()}),c.close=function(b){var c=a.getTop();c&&c.value.backdrop&&"static"!=c.value.backdrop&&b.target===b.currentTarget&&(b.preventDefault(),b.stopPropagation(),a.dismiss(c.key,"backdrop click"))}}}}]).directive("modalTransclude",function(){return{link:function(a,b,c,d,e){e(a.$parent,function(a){b.empty(),b.append(a)})}}}).factory("$modalStack",["$transition","$timeout","$document","$compile","$rootScope","$$stackedMap",function(a,b,c,d,e,f){function g(){for(var a=-1,b=n.keys(),c=0;c<b.length;c++)n.get(b[c]).value.backdrop&&(a=c);return a}function h(a){var b=c.find("body").eq(0),d=n.get(a).value;n.remove(a),j(d.modalDomEl,d.modalScope,300,function(){d.modalScope.$destroy(),b.toggleClass(m,n.length()>0),i()})}function i(){if(k&&-1==g()){var a=l;j(k,l,150,function(){a.$destroy(),a=null}),k=void 0,l=void 0}}function j(c,d,e,f){function g(){g.done||(g.done=!0,c.remove(),f&&f())}d.animate=!1;var h=a.transitionEndEventName;if(h){var i=b(g,e);c.bind(h,function(){b.cancel(i),g(),d.$apply()})}else b(g)}var k,l,m="modal-open",n=f.createNew(),o={};return e.$watch(g,function(a){l&&(l.index=a)}),c.bind("keydown",function(a){var b;27===a.which&&(b=n.top(),b&&b.value.keyboard&&(a.preventDefault(),e.$apply(function(){o.dismiss(b.key,"escape key press")})))}),o.open=function(a,b){n.add(a,{deferred:b.deferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard});var f=c.find("body").eq(0),h=g();if(h>=0&&!k){l=e.$new(!0),l.index=h;var i=angular.element("<div modal-backdrop></div>");i.attr("backdrop-class",b.backdropClass),k=d(i)(l),f.append(k)}var j=angular.element("<div modal-window></div>");j.attr({"template-url":b.windowTemplateUrl,"window-class":b.windowClass,size:b.size,index:n.length()-1,animate:"animate"}).html(b.content);var o=d(j)(b.scope);n.top().value.modalDomEl=o,f.append(o),f.addClass(m)},o.close=function(a,b){var c=n.get(a);c&&(c.value.deferred.resolve(b),h(a))},o.dismiss=function(a,b){var c=n.get(a);c&&(c.value.deferred.reject(b),h(a))},o.dismissAll=function(a){for(var b=this.getTop();b;)this.dismiss(b.key,a),b=this.getTop()},o.getTop=function(){return n.top()},o}]).provider("$modal",function(){var a={options:{backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$http","$templateCache","$controller","$modalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?d.when(a.template):e.get(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl,{cache:f}).then(function(a){return a.data})}function j(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a)))}),c}var k={};return k.open=function(b){var e=d.defer(),f=d.defer(),k={result:e.promise,opened:f.promise,close:function(a){h.close(k,a)},dismiss:function(a){h.dismiss(k,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var l=d.all([i(b)].concat(j(b.resolve)));return l.then(function(a){var d=(b.scope||c).$new();d.$close=k.close,d.$dismiss=k.dismiss;var f,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=k,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),f=g(b.controller,i),b.controllerAs&&(d[b.controllerAs]=f)),h.open(k,{scope:d,deferred:e,content:a[0],backdrop:b.backdrop,keyboard:b.keyboard,backdropClass:b.backdropClass,windowClass:b.windowClass,windowTemplateUrl:b.windowTemplateUrl,size:b.size})},function(a){e.reject(a)}),l.then(function(){f.resolve(!0)},function(){f.reject(!1)}),k},k}]};return a}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse",function(a,b,c){var d=this,e={$setViewValue:angular.noop},f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(f,g){e=f,this.config=g,e.$render=function(){d.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){d.itemsPerPage=parseInt(b,10),a.totalPages=d.calculateTotalPages()}):this.itemsPerPage=g.itemsPerPage},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(e.$viewValue,10)||1},a.selectPage=function(b){a.page!==b&&b>0&&b<=a.totalPages&&(e.$setViewValue(b),e.$render())},a.getText=function(b){return a[b+"Text"]||d.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages},a.$watch("totalItems",function(){a.totalPages=d.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),a.page>b?a.selectPage(b):e.$render()})}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(a,b){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@"},require:["pagination","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(c,d,e,f){function g(a,b,c){return{number:a,text:b,active:c}}function h(a,b){var c=[],d=1,e=b,f=angular.isDefined(k)&&b>k;f&&(l?(d=Math.max(a-Math.floor(k/2),1),e=d+k-1,e>b&&(e=b,d=e-k+1)):(d=(Math.ceil(a/k)-1)*k+1,e=Math.min(d+k-1,b)));for(var h=d;e>=h;h++){var i=g(h,h,h===a);c.push(i)}if(f&&!l){if(d>1){var j=g(d-1,"...",!1);c.unshift(j)}if(b>e){var m=g(e+1,"...",!1);c.push(m)}}return c}var i=f[0],j=f[1];if(j){var k=angular.isDefined(e.maxSize)?c.$parent.$eval(e.maxSize):b.maxSize,l=angular.isDefined(e.rotate)?c.$parent.$eval(e.rotate):b.rotate;c.boundaryLinks=angular.isDefined(e.boundaryLinks)?c.$parent.$eval(e.boundaryLinks):b.boundaryLinks,c.directionLinks=angular.isDefined(e.directionLinks)?c.$parent.$eval(e.directionLinks):b.directionLinks,i.init(j,b),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){k=parseInt(a,10),i.render()
+});var m=i.render;i.render=function(){m(),c.page>0&&c.page<=c.totalPages&&(c.pages=h(c.page,c.totalPages))}}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next Â»",align:!0}).directive("pager",["pagerConfig",function(a){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@"},require:["pager","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(b,c,d,e){var f=e[0],g=e[1];g&&(b.align=angular.isDefined(d.align)?b.$parent.$eval(d.align):a.align,f.init(g,a))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0},c={mouseenter:"mouseleave",click:"click",focus:"blur"},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$position","$interpolate",function(e,f,g,h,i,j){return function(e,k,l){function m(a){var b=a||n.trigger||l,d=c[b]||b;return{show:b,hide:d}}var n=angular.extend({},b,d),o=a(e),p=j.startSymbol(),q=j.endSymbol(),r="<div "+o+'-popup title="'+p+"title"+q+'" content="'+p+"content"+q+'" placement="'+p+"placement"+q+'" animation="animation" is-open="isOpen"></div>';return{restrict:"EA",compile:function(){var a=f(r);return function(b,c,d){function f(){D.isOpen?l():j()}function j(){(!C||b.$eval(d[k+"Enable"]))&&(s(),D.popupDelay?z||(z=g(o,D.popupDelay,!1),z.then(function(a){a()})):o()())}function l(){b.$apply(function(){p()})}function o(){return z=null,y&&(g.cancel(y),y=null),D.content?(q(),w.css({top:0,left:0,display:"block"}),A?h.find("body").append(w):c.after(w),E(),D.isOpen=!0,D.$digest(),E):angular.noop}function p(){D.isOpen=!1,g.cancel(z),z=null,D.animation?y||(y=g(r,500)):r()}function q(){w&&r(),x=D.$new(),w=a(x,angular.noop)}function r(){y=null,w&&(w.remove(),w=null),x&&(x.$destroy(),x=null)}function s(){t(),u()}function t(){var a=d[k+"Placement"];D.placement=angular.isDefined(a)?a:n.placement}function u(){var a=d[k+"PopupDelay"],b=parseInt(a,10);D.popupDelay=isNaN(b)?n.popupDelay:b}function v(){var a=d[k+"Trigger"];F(),B=m(a),B.show===B.hide?c.bind(B.show,f):(c.bind(B.show,j),c.bind(B.hide,l))}var w,x,y,z,A=angular.isDefined(n.appendToBody)?n.appendToBody:!1,B=m(void 0),C=angular.isDefined(d[k+"Enable"]),D=b.$new(!0),E=function(){var a=i.positionElements(c,w,D.placement,A);a.top+="px",a.left+="px",w.css(a)};D.isOpen=!1,d.$observe(e,function(a){D.content=a,!a&&D.isOpen&&p()}),d.$observe(k+"Title",function(a){D.title=a});var F=function(){c.unbind(B.show,j),c.unbind(B.hide,l)};v();var G=b.$eval(d[k+"Animation"]);D.animation=angular.isDefined(G)?!!G:n.animation;var H=b.$eval(d[k+"AppendToBody"]);A=angular.isDefined(H)?H:A,A&&b.$on("$locationChangeSuccess",function(){D.isOpen&&p()}),b.$on("$destroy",function(){g.cancel(y),g.cancel(z),F(),r(),D=null})}}}}}]}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(a){return a("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("progressConfig",{animate:!0,max:100}).controller("ProgressController",["$scope","$attrs","progressConfig",function(a,b,c){var d=this,e=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max,this.addBar=function(b,c){e||c.css({transition:"none"}),this.bars.push(b),b.$watch("value",function(c){b.percent=+(100*c/a.max).toFixed(2)}),b.$on("$destroy",function(){c=null,d.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)}}]).directive("progress",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{},templateUrl:"template/progressbar/progress.html"}}).directive("bar",function(){return{restrict:"EA",replace:!0,transclude:!0,require:"^progress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b)}}}).directive("progressbar",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]))}}}),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","ratingConfig",function(a,b,c){var d={$setViewValue:angular.noop};this.init=function(e){d=e,d.$render=this.render,this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff;var f=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(f)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff},a[b]);return a},a.rate=function(b){!a.readonly&&b>=0&&b<=a.range.length&&(d.$setViewValue(b),d.$render())},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue}}]).directive("rating",function(){return{restrict:"EA",require:["rating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("TabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(b){b.active&&b!==a&&(b.active=!1,b.onDeselect())}),a.active=!0,a.onSelect()},b.addTab=function(a){c.push(a),1===c.length?a.active=!0:a.active&&b.select(a)},b.removeTab=function(a){var e=c.indexOf(a);if(a.active&&c.length>1&&!d){var f=e==c.length-1?e-1:e+1;b.select(c[f])}c.splice(e,1)};var d;a.$on("$destroy",function(){d=!0})}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("tab",["$parse",function(a){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(b,c,d){return function(b,c,e,f){b.$watch("active",function(a){a&&f.select(b)}),b.disabled=!1,e.disabled&&b.$parent.$watch(a(e.disabled),function(a){b.disabled=!!a}),b.select=function(){b.disabled||(b.active=!0)},f.addTab(b),b.$on("$destroy",function(){f.removeTab(b)}),b.$transcludeFn=d}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}]).directive("tabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(b,c,d){var e=b.$eval(d.tabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0}).controller("TimepickerController",["$scope","$attrs","$parse","$log","$locale","timepickerConfig",function(a,b,c,d,e,f){function g(){var b=parseInt(a.hours,10),c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c?(a.showMeridian&&(12===b&&(b=0),a.meridian===p[1]&&(b+=12)),b):void 0}function h(){var b=parseInt(a.minutes,10);return b>=0&&60>b?b:void 0}function i(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a}function j(a){k(),o.$setViewValue(new Date(n)),l(a)}function k(){o.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function l(b){var c=n.getHours(),d=n.getMinutes();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:i(c),a.minutes="m"===b?d:i(d),a.meridian=n.getHours()<12?p[0]:p[1]}function m(a){var b=new Date(n.getTime()+6e4*a);n.setHours(b.getHours(),b.getMinutes()),j()}var n=new Date,o={$setViewValue:angular.noop},p=angular.isDefined(b.meridians)?a.$parent.$eval(b.meridians):f.meridians||e.DATETIME_FORMATS.AMPMS;this.init=function(c,d){o=c,o.$render=this.render;var e=d.eq(0),g=d.eq(1),h=angular.isDefined(b.mousewheel)?a.$parent.$eval(b.mousewheel):f.mousewheel;h&&this.setupMousewheelEvents(e,g),a.readonlyInput=angular.isDefined(b.readonlyInput)?a.$parent.$eval(b.readonlyInput):f.readonlyInput,this.setupInputEvents(e,g)};var q=f.hourStep;b.hourStep&&a.$parent.$watch(c(b.hourStep),function(a){q=parseInt(a,10)});var r=f.minuteStep;b.minuteStep&&a.$parent.$watch(c(b.minuteStep),function(a){r=parseInt(a,10)}),a.showMeridian=f.showMeridian,b.showMeridian&&a.$parent.$watch(c(b.showMeridian),function(b){if(a.showMeridian=!!b,o.$error.time){var c=g(),d=h();angular.isDefined(c)&&angular.isDefined(d)&&(n.setHours(c),j())}else l()}),this.setupMousewheelEvents=function(b,c){var d=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()})},this.setupInputEvents=function(b,c){if(a.readonlyInput)return a.updateHours=angular.noop,void(a.updateMinutes=angular.noop);var d=function(b,c){o.$setViewValue(null),o.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b),angular.isDefined(c)&&(a.invalidMinutes=c)};a.updateHours=function(){var a=g();angular.isDefined(a)?(n.setHours(a),j("h")):d(!0)},b.bind("blur",function(){!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=i(a.hours)})}),a.updateMinutes=function(){var a=h();angular.isDefined(a)?(n.setMinutes(a),j("m")):d(void 0,!0)},c.bind("blur",function(){!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=i(a.minutes)})})},this.render=function(){var a=o.$modelValue?new Date(o.$modelValue):null;isNaN(a)?(o.$setValidity("time",!1),d.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(a&&(n=a),k(),l())},a.incrementHours=function(){m(60*q)},a.decrementHours=function(){m(60*-q)},a.incrementMinutes=function(){m(r)},a.decrementMinutes=function(){m(-r)},a.toggleMeridian=function(){m(720*(n.getHours()<12?1:-1))}}]).directive("timepicker",function(){return{restrict:"EA",require:["timepicker","?^ngModel"],controller:"TimepickerController",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(a,b,c,d,e,f,g){var h=[9,13,27,38,40];return{require:"ngModel",link:function(i,j,k,l){var m,n=i.$eval(k.typeaheadMinLength)||1,o=i.$eval(k.typeaheadWaitMs)||0,p=i.$eval(k.typeaheadEditable)!==!1,q=b(k.typeaheadLoading).assign||angular.noop,r=b(k.typeaheadOnSelect),s=k.typeaheadInputFormatter?b(k.typeaheadInputFormatter):void 0,t=k.typeaheadAppendToBody?i.$eval(k.typeaheadAppendToBody):!1,u=i.$eval(k.typeaheadFocusFirst)!==!1,v=b(k.ngModel).assign,w=g.parse(k.typeahead),x=i.$new();i.$on("$destroy",function(){x.$destroy()});var y="typeahead-"+x.$id+"-"+Math.floor(1e4*Math.random());j.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":y});var z=angular.element("<div typeahead-popup></div>");z.attr({id:y,matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(k.typeaheadTemplateUrl)&&z.attr("template-url",k.typeaheadTemplateUrl);var A=function(){x.matches=[],x.activeIdx=-1,j.attr("aria-expanded",!1)},B=function(a){return y+"-option-"+a};x.$watch("activeIdx",function(a){0>a?j.removeAttr("aria-activedescendant"):j.attr("aria-activedescendant",B(a))});var C=function(a){var b={$viewValue:a};q(i,!0),c.when(w.source(i,b)).then(function(c){var d=a===l.$viewValue;if(d&&m)if(c.length>0){x.activeIdx=u?0:-1,x.matches.length=0;for(var e=0;e<c.length;e++)b[w.itemName]=c[e],x.matches.push({id:B(e),label:w.viewMapper(x,b),model:c[e]});x.query=a,x.position=t?f.offset(j):f.position(j),x.position.top=x.position.top+j.prop("offsetHeight"),j.attr("aria-expanded",!0)}else A();d&&q(i,!1)},function(){A(),q(i,!1)})};A(),x.query=void 0;var D,E=function(a){D=d(function(){C(a)},o)},F=function(){D&&d.cancel(D)};l.$parsers.unshift(function(a){return m=!0,a&&a.length>=n?o>0?(F(),E(a)):C(a):(q(i,!1),F(),A()),p?a:a?void l.$setValidity("editable",!1):(l.$setValidity("editable",!0),a)}),l.$formatters.push(function(a){var b,c,d={};return s?(d.$model=a,s(i,d)):(d[w.itemName]=a,b=w.viewMapper(i,d),d[w.itemName]=void 0,c=w.viewMapper(i,d),b!==c?b:a)}),x.select=function(a){var b,c,e={};e[w.itemName]=c=x.matches[a].model,b=w.modelMapper(i,e),v(i,b),l.$setValidity("editable",!0),r(i,{$item:c,$model:b,$label:w.viewMapper(i,e)}),A(),d(function(){j[0].focus()},0,!1)},j.bind("keydown",function(a){0!==x.matches.length&&-1!==h.indexOf(a.which)&&(-1!=x.activeIdx||13!==a.which&&9!==a.which)&&(a.preventDefault(),40===a.which?(x.activeIdx=(x.activeIdx+1)%x.matches.length,x.$digest()):38===a.which?(x.activeIdx=(x.activeIdx>0?x.activeIdx:x.matches.length)-1,x.$digest()):13===a.which||9===a.which?x.$apply(function(){x.select(x.activeIdx)}):27===a.which&&(a.stopPropagation(),A(),x.$digest()))}),j.bind("blur",function(){m=!1});var G=function(a){j[0]!==a.target&&(A(),x.$digest())};e.bind("click",G),i.$on("$destroy",function(){e.unbind("click",G),t&&H.remove()});var H=a(z)(x);t?e.find("body").append(H):j.after(H)}}}]).directive("typeaheadPopup",function(){return{restrict:"EA",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("typeaheadMatch",["$http","$templateCache","$compile","$parse",function(a,b,c,d){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(e,f,g){var h=d(g.templateUrl)(e.$parent)||"template/typeahead/typeahead-match.html";a.get(h,{cache:b}).success(function(a){f.replaceWith(c(a.trim())(e))})}}}]).filter("typeaheadHighlight",function(){function a(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c){return c?(""+b).replace(new RegExp(a(c),"gi"),"<strong>$&</strong>"):b}}),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion-group.html",'<div class="panel panel-default">\n  <div class="panel-heading">\n    <h4 class="panel-title">\n      <a href class="accordion-toggle" ng-click="toggleOpen()" accordion-transclude="heading"><span ng-class="{\'text-muted\': isDisabled}">{{heading}}</span></a>\n    </h4>\n  </div>\n  <div class="panel-collapse" collapse="!isOpen">\n         <div class="panel-body" ng-transclude></div>\n  </div>\n</div>\n')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion.html",'<div class="panel-group" ng-transclude></div>')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(a){a.put("template/alert/alert.html",'<div class="alert" ng-class="[\'alert-\' + (type || \'warning\'), closeable ? \'alert-dismissable\' : null]" role="alert">\n    <button ng-show="closeable" type="button" class="close" ng-click="close()">\n        <span aria-hidden="true">&times;</span>\n        <span class="sr-only">Close</span>\n    </button>\n    <div ng-transclude></div>\n</div>\n')}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(a){a.put("template/carousel/carousel.html",'<div ng-mouseenter="pause()" ng-mouseleave="play()" class="carousel" ng-swipe-right="prev()" ng-swipe-left="next()">\n    <ol class="carousel-indicators" ng-show="slides.length > 1">\n        <li ng-repeat="slide in slides track by $index" ng-class="{active: isActive(slide)}" ng-click="select(slide)"></li>\n    </ol>\n    <div class="carousel-inner" ng-transclude></div>\n    <a class="left carousel-control" ng-click="prev()" ng-show="slides.length > 1"><span class="glyphicon glyphicon-chevron-left"></span></a>\n    <a class="right carousel-control" ng-click="next()" ng-show="slides.length > 1"><span class="glyphicon glyphicon-chevron-right"></span></a>\n</div>\n')}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("template/carousel/slide.html","<div ng-class=\"{\n    'active': leaving || (active && !entering),\n    'prev': (next || active) && direction=='prev',\n    'next': (next || active) && direction=='next',\n    'right': direction=='prev',\n    'left': direction=='next'\n  }\" class=\"item text-center\" ng-transclude></div>\n")}]),angular.module("template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/datepicker.html",'<div ng-switch="datepickerMode" role="application" ng-keydown="keydown($event)">\n  <daypicker ng-switch-when="day" tabindex="0"></daypicker>\n  <monthpicker ng-switch-when="month" tabindex="0"></monthpicker>\n  <yearpicker ng-switch-when="year" tabindex="0"></yearpicker>\n</div>')}]),angular.module("template/datepicker/day.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/day.html",'<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n  <thead>\n    <tr>\n      <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n      <th colspan="{{5 + showWeeks}}"><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n      <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n    </tr>\n    <tr>\n      <th ng-show="showWeeks" class="text-center"></th>\n      <th ng-repeat="label in labels track by $index" class="text-center"><small aria-label="{{label.full}}">{{label.abbr}}</small></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr ng-repeat="row in rows track by $index">\n      <td ng-show="showWeeks" class="text-center h6"><em>{{ weekNumbers[$index] }}</em></td>\n      <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}">\n        <button type="button" style="width:100%;" class="btn btn-default btn-sm" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{\'text-muted\': dt.secondary, \'text-info\': dt.current}">{{dt.label}}</span></button>\n      </td>\n    </tr>\n  </tbody>\n</table>\n')}]),angular.module("template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/month.html",'<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n  <thead>\n    <tr>\n      <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n      <th><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n      <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr ng-repeat="row in rows track by $index">\n      <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}">\n        <button type="button" style="width:100%;" class="btn btn-default" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{\'text-info\': dt.current}">{{dt.label}}</span></button>\n      </td>\n    </tr>\n  </tbody>\n</table>\n')}]),angular.module("template/datepicker/popup.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/popup.html",'<ul class="dropdown-menu" ng-style="{display: (isOpen && \'block\') || \'none\', top: position.top+\'px\', left: position.left+\'px\'}" ng-keydown="keydown($event)">\n      <li ng-transclude></li>\n       <li ng-if="showButtonBar" style="padding:10px 9px 2px">\n               <span class="btn-group pull-left">\n                    <button type="button" class="btn btn-sm btn-info" ng-click="select(\'today\')">{{ getText(\'current\') }}</button>\n                    <button type="button" class="btn btn-sm btn-danger" ng-click="select(null)">{{ getText(\'clear\') }}</button>\n         </span>\n               <button type="button" class="btn btn-sm btn-success pull-right" ng-click="close()">{{ getText(\'close\') }}</button>\n  </li>\n</ul>\n')}]),angular.module("template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/year.html",'<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n  <thead>\n    <tr>\n      <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n      <th colspan="3"><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n      <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr ng-repeat="row in rows track by $index">\n      <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}">\n        <button type="button" style="width:100%;" class="btn btn-default" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{\'text-info\': dt.current}">{{dt.label}}</span></button>\n      </td>\n    </tr>\n  </tbody>\n</table>\n')}]),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(a){a.put("template/modal/backdrop.html",'<div class="modal-backdrop fade {{ backdropClass }}"\n     ng-class="{in: animate}"\n     ng-style="{\'z-index\': 1040 + (index && 1 || 0) + index*10}"\n></div>\n')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(a){a.put("template/modal/window.html",'<div tabindex="-1" role="dialog" class="modal fade" ng-class="{in: animate}" ng-style="{\'z-index\': 1050 + index*10, display: \'block\'}" ng-click="close($event)">\n    <div class="modal-dialog" ng-class="{\'modal-sm\': size == \'sm\', \'modal-lg\': size == \'lg\'}"><div class="modal-content" modal-transclude></div></div>\n</div>')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pager.html",'<ul class="pager">\n  <li ng-class="{disabled: noPrevious(), previous: align}"><a href ng-click="selectPage(page - 1)">{{getText(\'previous\')}}</a></li>\n  <li ng-class="{disabled: noNext(), next: align}"><a href ng-click="selectPage(page + 1)">{{getText(\'next\')}}</a></li>\n</ul>')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pagination.html",'<ul class="pagination">\n  <li ng-if="boundaryLinks" ng-class="{disabled: noPrevious()}"><a href ng-click="selectPage(1)">{{getText(\'first\')}}</a></li>\n  <li ng-if="directionLinks" ng-class="{disabled: noPrevious()}"><a href ng-click="selectPage(page - 1)">{{getText(\'previous\')}}</a></li>\n  <li ng-repeat="page in pages track by $index" ng-class="{active: page.active}"><a href ng-click="selectPage(page.number)">{{page.text}}</a></li>\n  <li ng-if="directionLinks" ng-class="{disabled: noNext()}"><a href ng-click="selectPage(page + 1)">{{getText(\'next\')}}</a></li>\n  <li ng-if="boundaryLinks" ng-class="{disabled: noNext()}"><a href ng-click="selectPage(totalPages)">{{getText(\'last\')}}</a></li>\n</ul>')}]),angular.module("template/tooltip/tooltip-html-unsafe-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-unsafe-popup.html",'<div class="tooltip {{placement}}" ng-class="{ in: isOpen(), fade: animation() }">\n  <div class="tooltip-arrow"></div>\n  <div class="tooltip-inner" bind-html-unsafe="content"></div>\n</div>\n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-popup.html",'<div class="tooltip {{placement}}" ng-class="{ in: isOpen(), fade: animation() }">\n  <div class="tooltip-arrow"></div>\n  <div class="tooltip-inner" ng-bind="content"></div>\n</div>\n')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover.html",'<div class="popover {{placement}}" ng-class="{ in: isOpen(), fade: animation() }">\n  <div class="arrow"></div>\n\n  <div class="popover-inner">\n      <h3 class="popover-title" ng-bind="title" ng-show="title"></h3>\n      <div class="popover-content" ng-bind="content"></div>\n  </div>\n</div>\n')}]),angular.module("template/progressbar/bar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/bar.html",'<div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: percent + \'%\'}" aria-valuetext="{{percent | number:0}}%" ng-transclude></div>')}]),angular.module("template/progressbar/progress.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progress.html",'<div class="progress" ng-transclude></div>')}]),angular.module("template/progressbar/progressbar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progressbar.html",'<div class="progress">\n  <div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: percent + \'%\'}" aria-valuetext="{{percent | number:0}}%" ng-transclude></div>\n</div>')}]),angular.module("template/rating/rating.html",[]).run(["$templateCache",function(a){a.put("template/rating/rating.html",'<span ng-mouseleave="reset()" ng-keydown="onKeydown($event)" tabindex="0" role="slider" aria-valuemin="0" aria-valuemax="{{range.length}}" aria-valuenow="{{value}}">\n    <i ng-repeat="r in range track by $index" ng-mouseenter="enter($index + 1)" ng-click="rate($index + 1)" class="glyphicon" ng-class="$index < value && (r.stateOn || \'glyphicon-star\') || (r.stateOff || \'glyphicon-star-empty\')">\n        <span class="sr-only">({{ $index < value ? \'*\' : \' \' }})</span>\n    </i>\n</span>')}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tab.html",'<li ng-class="{active: active, disabled: disabled}">\n  <a href ng-click="select()" tab-heading-transclude>{{heading}}</a>\n</li>\n')}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset.html",'<div>\n  <ul class="nav nav-{{type || \'tabs\'}}" ng-class="{\'nav-stacked\': vertical, \'nav-justified\': justified}" ng-transclude></ul>\n  <div class="tab-content">\n    <div class="tab-pane" \n         ng-repeat="tab in tabs" \n         ng-class="{active: tab.active}"\n         tab-content-transclude="tab">\n    </div>\n  </div>\n</div>\n')}]),angular.module("template/timepicker/timepicker.html",[]).run(["$templateCache",function(a){a.put("template/timepicker/timepicker.html",'<table>\n  <tbody>\n               <tr class="text-center">\n                      <td><a ng-click="incrementHours()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n                 <td>&nbsp;</td>\n                       <td><a ng-click="incrementMinutes()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n                       <td ng-show="showMeridian"></td>\n              </tr>\n         <tr>\n                  <td style="width:50px;" class="form-group" ng-class="{\'has-error\': invalidHours}">\n                          <input type="text" ng-model="hours" ng-change="updateHours()" class="form-control text-center" ng-mousewheel="incrementHours()" ng-readonly="readonlyInput" maxlength="2">\n                    </td>\n                 <td>:</td>\n                    <td style="width:50px;" class="form-group" ng-class="{\'has-error\': invalidMinutes}">\n                                <input type="text" ng-model="minutes" ng-change="updateMinutes()" class="form-control text-center" ng-readonly="readonlyInput" maxlength="2">\n                 </td>\n                 <td ng-show="showMeridian"><button type="button" class="btn btn-default text-center" ng-click="toggleMeridian()">{{meridian}}</button></td>\n           </tr>\n         <tr class="text-center">\n                      <td><a ng-click="decrementHours()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n                       <td>&nbsp;</td>\n                       <td><a ng-click="decrementMinutes()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n                     <td ng-show="showMeridian"></td>\n              </tr>\n </tbody>\n</table>\n')}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-match.html",'<a tabindex="-1" bind-html-unsafe="match.label | typeaheadHighlight:query"></a>')
+}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-popup.html",'<ul class="dropdown-menu" ng-show="isOpen()" ng-style="{top: position.top+\'px\', left: position.left+\'px\'}" style="display: block;" role="listbox" aria-hidden="{{!isOpen()}}">\n    <li ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index)" role="option" id="{{match.id}}">\n        <div typeahead-match index="$index" match="match" query="query" template-url="templateUrl"></div>\n    </li>\n</ul>\n')}]);
\ No newline at end of file
diff --git a/sfc-ui/src/main/resources/pages/vendor/angular-cookies/angular-cookies.min.js.map b/sfc-ui/src/main/resources/pages/vendor/angular-cookies/angular-cookies.min.js.map
new file mode 100644 (file)
index 0000000..1d3c5d3
--- /dev/null
@@ -0,0 +1,8 @@
+{
+"version":3,
+"file":"angular-cookies.min.js",
+"lineCount":7,
+"mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAmBtCD,CAAAE,OAAA,CAAe,WAAf,CAA4B,CAAC,IAAD,CAA5B,CAAAC,QAAA,CA4BW,UA5BX,CA4BuB,CAAC,YAAD,CAAe,UAAf,CAA2B,QAAS,CAACC,CAAD,CAAaC,CAAb,CAAuB,CAAA,IACxEC,EAAU,EAD8D,CAExEC,EAAc,EAF0D,CAGxEC,CAHwE,CAIxEC,EAAU,CAAA,CAJ8D,CAKxEC,EAAOV,CAAAU,KALiE,CAMxEC,EAAcX,CAAAW,YAGlBN,EAAAO,UAAA,CAAmB,QAAQ,EAAG,CAC5B,IAAIC,EAAiBR,CAAAC,QAAA,EACjBE,EAAJ,EAA0BK,CAA1B,GACEL,CAGA,CAHqBK,CAGrB,CAFAH,CAAA,CAAKG,CAAL,CAAqBN,CAArB,CAEA,CADAG,CAAA,CAAKG,CAAL,CAAqBP,CAArB,CACA,CAAIG,CAAJ,EAAaL,CAAAU,OAAA,EAJf,CAF4B,CAA9B,CAAA,EAUAL,EAAA,CAAU,CAAA,CAKVL,EAAAW,OAAA,CASAC,QAAa,EAAG,CAAA,IACVC,CADU,CAEVC,CAFU,CAIVC,CAGJ,KAAKF,CAAL,GAAaV,EAAb,CACMI,CAAA,CAAYL,CAAA,CAAQW,CAAR,CAAZ,CAAJ,EACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBhB,CAAvB,CAKJ,KAAIgB,CAAJ,GAAYX,EAAZ,CACEY,CAKA,CALQZ,CAAA,CAAQW,CAAR,CAKR,CAJKjB,CAAAoB,SAAA,CAAiBF,CAAjB,CAIL,GAHEA,CACA,CADQ,EACR,CADaA,CACb,CAAAZ,CAAA,CAAQW,CAAR,CAAA,CAAgBC,CAElB,EAAIA,CAAJ,GAAcX,CAAA,CAAYU,CAAZ,CAAd,GACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBC,CAAvB,CACA,CAAAC,CAAA,CAAU,CAAA,CAFZ,CAOF,IAAIA,CAAJ,CAIE,IAAKF,CAAL,GAFAI,EAEaf,CAFID,CAAAC,QAAA,EAEJA,CAAAA,CAAb,CACMA,CAAA,CAAQW,CAAR,CAAJ,GAAsBI,CAAA,CAAeJ,CAAf,CAAtB,GAEMN,CAAA,CAAYU,CAAA,CAAeJ,CAAf,CAAZ,CAAJ,CACE,OAAOX,CAAA,CAAQW,CAAR,CADT,CAGEX,CAAA,CAAQW,CAAR,CAHF,CAGkBI,CAAA,CAAeJ,CAAf,CALpB,CAhCU,CAThB,CAEA,OAAOX,EA1BqE,CAA3D,CA5BvB,CAAAH,QAAA,CA0HW,cA1HX;AA0H2B,CAAC,UAAD,CAAa,QAAQ,CAACmB,CAAD,CAAW,CAErD,MAAO,KAWAC,QAAQ,CAACC,CAAD,CAAM,CAEjB,MAAO,CADHN,CACG,CADKI,CAAA,CAASE,CAAT,CACL,EAAQxB,CAAAyB,SAAA,CAAiBP,CAAjB,CAAR,CAAkCA,CAFxB,CAXd,KA0BAQ,QAAQ,CAACF,CAAD,CAAMN,CAAN,CAAa,CACxBI,CAAA,CAASE,CAAT,CAAA,CAAgBxB,CAAA2B,OAAA,CAAeT,CAAf,CADQ,CA1BrB,QAuCGU,QAAQ,CAACJ,CAAD,CAAM,CACpB,OAAOF,CAAA,CAASE,CAAT,CADa,CAvCjB,CAF8C,CAAhC,CA1H3B,CAnBsC,CAArC,CAAA,CA8LEzB,MA9LF,CA8LUA,MAAAC,QA9LV;",
+"sources":["angular-cookies.js"],
+"names":["window","angular","undefined","module","factory","$rootScope","$browser","cookies","lastCookies","lastBrowserCookies","runEval","copy","isUndefined","addPollFn","currentCookies","$apply","$watch","push","name","value","updated","isString","browserCookies","$cookies","get","key","fromJson","put","toJson","remove"]
+}
index 07bcb7786f2dc65082bb5894b1de7b912de2ee1c..7de17dabf703488844c67531d18e8a77634c297e 100644 (file)
@@ -5,23 +5,10 @@
  * Time: 11:27
  * To change this template use File | Settings | File Templates.
  */
-
-(function(){
-
-function isDnDsSupported(){
-    return 'draggable' in document.createElement("span");
-}
-
-if(!isDnDsSupported()){
-    return;
-}
-
 if (window.jQuery && (-1 == window.jQuery.event.props.indexOf("dataTransfer"))) {
     window.jQuery.event.props.push("dataTransfer");
 }
 
-var currentData;
-
 angular.module("ngDragDrop",[])
     .directive("uiDraggable", [
         '$parse',
@@ -37,13 +24,7 @@ angular.module("ngDragDrop",[])
                 element.attr("draggable", false);
 
                 attrs.$observe("uiDraggable", function (newValue) {
-                    if(newValue){
-                        element.attr("draggable", newValue);
-                    }
-                    else{
-                        element.removeAttr("draggable");
-                    }
-
+                    element.attr("draggable", newValue);
                 });
 
                 if (attrs.drag) {
@@ -62,41 +43,13 @@ angular.module("ngDragDrop",[])
                     });
                 }
 
-                function dragendHandler(e) {
-                    setTimeout(function() {
-                      element.unbind('$destroy', dragendHandler);
-                    }, 0);
-                    var sendChannel = attrs.dragChannel || "defaultchannel";
-                    $rootScope.$broadcast("ANGULAR_DRAG_END", sendChannel);
-                    if (e.dataTransfer && e.dataTransfer.dropEffect !== "none") {
-                        if (attrs.onDropSuccess) {
-                            var fn = $parse(attrs.onDropSuccess);
-                            scope.$apply(function () {
-                                fn(scope, {$event: e});
-                            });
-                        } else {
-                            if (attrs.onDropFailure) {
-                                var fn = $parse(attrs.onDropFailure);
-                                scope.$apply(function () {
-                                    fn(scope, {$event: e});
-                                });
-                            }
-                        }
-                    }
-                }
-
-                element.bind("dragend", dragendHandler);
-
                 element.bind("dragstart", function (e) {
                     var isDragAllowed = !isDragHandleUsed || -1 != dragHandles.indexOf(dragTarget);
 
                     if (isDragAllowed) {
+                        var sendData = angular.toJson(dragData);
                         var sendChannel = attrs.dragChannel || "defaultchannel";
-                        var sendData = angular.toJson({ data: dragData, channel: sendChannel });
                         var dragImage = attrs.dragImage || null;
-
-                        element.bind('$destroy', dragendHandler);
-
                         if (dragImage) {
                             var dragImageFn = $parse(attrs.dragImage);
                             scope.$apply(function() {
@@ -109,8 +62,7 @@ angular.module("ngDragDrop",[])
                             });
                         }
 
-                        e.dataTransfer.setData("Text", sendData);
-                        currentData = angular.fromJson(sendData);
+                        e.dataTransfer.setData("text/plain", sendData);
                         e.dataTransfer.effectAllowed = "copyMove";
                         $rootScope.$broadcast("ANGULAR_DRAG_START", sendChannel);
                     }
@@ -118,6 +70,21 @@ angular.module("ngDragDrop",[])
                         e.preventDefault();
                     }
                 });
+
+                element.bind("dragend", function (e) {
+                    var sendChannel = attrs.dragChannel || "defaultchannel";
+                    $rootScope.$broadcast("ANGULAR_DRAG_END", sendChannel);
+                    if (e.dataTransfer && e.dataTransfer.dropEffect !== "none") {
+                        if (attrs.onDropSuccess) {
+                            var fn = $parse(attrs.onDropSuccess);
+                            scope.$apply(function () {
+                                fn(scope, {$event: e});
+                            });
+                        }
+                    }
+                });
+
+
             };
         }
     ])
@@ -127,7 +94,7 @@ angular.module("ngDragDrop",[])
         function ($parse, $rootScope) {
             return function (scope, element, attr) {
                 var dragging = 0; //Ref. http://stackoverflow.com/a/10906204
-                var dropChannel = attr.dropChannel || "defaultchannel" ;
+                var dropChannel = "defaultchannel";
                 var dragChannel = "";
                 var dragEnterClass = attr.dragEnterClass || "on-drag-enter";
                 var dragHoverClass = attr.dragHoverClass || "on-drag-hover";
@@ -154,7 +121,7 @@ angular.module("ngDragDrop",[])
 
                 function onDragEnter(e) {
                     dragging++;
-                    $rootScope.$broadcast("ANGULAR_HOVER", dragChannel);
+                    $rootScope.$broadcast("ANGULAR_HOVER", dropChannel);
                     element.addClass(dragHoverClass);
                 }
 
@@ -165,16 +132,13 @@ angular.module("ngDragDrop",[])
                     if (e.stopPropagation) {
                         e.stopPropagation(); // Necessary. Allows us to drop.
                     }
-
-                    var sendData = e.dataTransfer.getData("Text");
-                    sendData = angular.fromJson(sendData);
-
+                    var data = e.dataTransfer.getData("text/plain");
+                    data = angular.fromJson(data);
                     var fn = $parse(attr.uiOnDrop);
                     scope.$apply(function () {
-                        fn(scope, {$data: sendData.data, $event: e, $channel: sendData.channel});
+                        fn(scope, {$data: data, $event: e});
                     });
                     element.removeClass(dragEnterClass);
-                    dragging = 0;
                 }
 
                 function isDragChannelAccepted(dragChannel, dropChannel) {
@@ -187,16 +151,9 @@ angular.module("ngDragDrop",[])
                     return channelMatchPattern.test("," + dropChannel + ",");
                 }
 
-                var deregisterDragStart = $rootScope.$on("ANGULAR_DRAG_START", function (event, channel) {
+                $rootScope.$on("ANGULAR_DRAG_START", function (event, channel) {
                     dragChannel = channel;
-                    if (isDragChannelAccepted(channel, dropChannel)) {
-                        if (attr.dropValidate) {
-                            var validateFn = $parse(attr.dropValidate);
-                            var valid = validateFn(scope, {$data: currentData.data, $channel: currentData.channel});
-                            if (!valid) {
-                                return;
-                            }
-                        }
+                    if (isDragChannelAccepted(dragChannel, dropChannel)) {
 
                         element.bind("dragover", onDragOver);
                         element.bind("dragenter", onDragEnter);
@@ -210,7 +167,7 @@ angular.module("ngDragDrop",[])
 
 
 
-                var deregisterDragEnd = $rootScope.$on("ANGULAR_DRAG_END", function (e, channel) {
+                $rootScope.$on("ANGULAR_DRAG_END", function (e, channel) {
                     dragChannel = "";
                     if (isDragChannelAccepted(channel, dropChannel)) {
 
@@ -225,20 +182,13 @@ angular.module("ngDragDrop",[])
                 });
 
 
-                var deregisterDragHover = $rootScope.$on("ANGULAR_HOVER", function (e, channel) {
+                $rootScope.$on("ANGULAR_HOVER", function (e, channel) {
                     if (isDragChannelAccepted(channel, dropChannel)) {
                       element.removeClass(dragHoverClass);
                     }
                 });
 
 
-                scope.$on('$destroy', function () {
-                    deregisterDragStart();
-                    deregisterDragEnd();
-                    deregisterDragHover();
-                });
-
-
                 attr.$observe('dropChannel', function (value) {
                     if (value) {
                         dropChannel = value;
@@ -249,5 +199,3 @@ angular.module("ngDragDrop",[])
             };
         }
     ]);
-
-}());
diff --git a/sfc-ui/src/main/resources/pages/vendor/ngStorage/ngStorage.min.js b/sfc-ui/src/main/resources/pages/vendor/ngStorage/ngStorage.min.js
new file mode 100644 (file)
index 0000000..f5526bb
--- /dev/null
@@ -0,0 +1 @@
+/*! ngStorage 0.3.0 | Copyright (c) 2013 Gias Kay Lee | MIT License */"use strict";!function(){function a(a){return["$rootScope","$window",function(b,c){for(var d,e,f,g=c[a]||(console.warn("This browser does not support Web Storage!"),{}),h={$default:function(a){for(var b in a)angular.isDefined(h[b])||(h[b]=a[b]);return h},$reset:function(a){for(var b in h)"$"===b[0]||delete h[b];return h.$default(a)}},i=0;i<g.length;i++)(f=g.key(i))&&"ngStorage-"===f.slice(0,10)&&(h[f.slice(10)]=angular.fromJson(g.getItem(f)));return d=angular.copy(h),b.$watch(function(){e||(e=setTimeout(function(){if(e=null,!angular.equals(h,d)){angular.forEach(h,function(a,b){angular.isDefined(a)&&"$"!==b[0]&&g.setItem("ngStorage-"+b,angular.toJson(a)),delete d[b]});for(var a in d)g.removeItem("ngStorage-"+a);d=angular.copy(h)}},100))}),"localStorage"===a&&c.addEventListener&&c.addEventListener("storage",function(a){"ngStorage-"===a.key.slice(0,10)&&(a.newValue?h[a.key.slice(10)]=angular.fromJson(a.newValue):delete h[a.key.slice(10)],d=angular.copy(h),b.$apply())}),h}]}angular.module("ngStorage",[]).factory("$localStorage",a("localStorage")).factory("$sessionStorage",a("sessionStorage"))}();
\ No newline at end of file