Moved UI into its own Django app.

This commit is contained in:
Chris Church 2013-05-08 11:41:00 -04:00
parent 839d681b70
commit eff2e65c9a
170 changed files with 88490 additions and 0 deletions

View File

@ -150,6 +150,7 @@ INSTALLED_APPS = (
'djcelery',
'kombu.transport.django',
'lib.main',
'lib.ui',
)
INTERNAL_IPS = ('127.0.0.1',)

0
lib/ui/__init__.py Normal file
View File

1
lib/ui/models.py Normal file
View File

@ -0,0 +1 @@
# Empty models file.

View File

@ -0,0 +1,223 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* ansible-ui.css
*
* custom styles for ansible-ui
*
*/
html {
background-color: #36454F;
}
body {
color: #36454F;
padding-top: 40px;
}
.container-fluid {
min-height: 700px ;
}
.navbar-fixed-top .container {
width: 100%;
}
.navbar-inverse .navbar-inner {
background-color: #36454F;
background-image: -moz-linear-gradient(top, #36454F, #36454F);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#36454F), to(#36454F));
background-image: -webkit-linear-gradient(top, #36454F, #36454F);
background-image: -o-linear-gradient(top, #36454F, #36454F);
background-image: linear-gradient(to bottom, #36454F, #36454F);
background-repeat: repeat-x;
border-color: #36454F;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#36454F', endColorstr='#36454F', GradientType=0);
}
.navbar-inverse .nav > li > a {
color: #A9A9A9;
}
.navbar-inverse .nav > li > a:hover,
.navbar-inverse .nav > li > a:focus {
color: #2078be;
}
.navbar .brand {
margin-left: 15px;
}
.navbar .brand img {
width: 130px;
}
/*.modal-header {
border-bottom: 1px solid #000;
padding-top: 15px;
padding-bottom: 15px;
}*/
a:hover {
text-decoration: none;
}
.site-footer {
width: 100%;
margin-top: 60px;
background-color: #36454F;
color: #A9A9A9;
padding-top: 20px;
}
.copyright {
margin-top: 40px;
font-size: 11px;
font-weight: normal;
text-align: center;
}
.site-footer a,
.site-footer a:active,
.site-footer a:hover,
.site-footer a:visited {
color: #A9A9A9;
font-size: 18px;
margin-right: 15px;
}
.site-footer .social {
display: inline-block;
margin-left: 50px;
}
.site-footer .logo {
display: inline-block;
text-align: left;
font-size: 12px;
margin-right: 20px;
}
.site-footer .logo img {
max-width: 165px;
}
.site-footer .logo .tag-line {
line-height: normal;
margin-top: 5px;
margin-left: 15px;
}
.error {
font-size: 12px;
color: #FF0000;
}
.xsmall {
font-size: 12px;
}
legend {
font-size: medium;
font-weight: bold;
}
.navigation {
margin: 15px 0 15px 0;
}
.page-number {
display: inline-block;
margin: 0;
padding: 0;
}
.page-number-small {
display: inline-block;
font-size: 11px;
margin-left: 10px;
}
.footer-navigation {
border-top: 1px solid #000;
margin: 20px 0 20px 0;
padding-top: 20px;
}
.lookup-navigation {
margin: 15px 0 0 0;
/*padding-top: 20px;*/
}
.related-footer {
padding-bottom: 0;
margin: 20px 0 0 0;
}
.page-size {
line-size: normal;
font-size: 10.5px;
}
.page-size-label {
margin-left: 15px;
font-size: 10.5px;
}
.accordion-heading {
font-weight: bold;
color: #0088cc;
}
.accordion-heading i {
margin-right: 5px;
}
.search-widget .spin {
display: inline-block;
font-size: 18px;
margin-left: 15px;
}
.nav-path {
padding: 5px 0 10px 0;
margin-bottom: 25px;
margin-right: 5px;
border: 1px solid #d8d8d8;
font-size: 14px;
font-weight: bold;
background-color: #f5f5f5;
border-radius: 6px;
box-shadow: 3px 3px 4px 0 #808080;
}
.nav-path ul {
padding-left: 0;
margin-left: 10px;
padding-bottom: 0;
margin-bottom: 0;
}
.greeting {
padding-right: 22px;
}
.breadcrumb .active {
color: #36454F;
}
.nav-tabs > li > a {
font-weight: bold;
}
input[type="text"].field-mini-height {
font-size: 10.5px;
height: 12px;
}
select.field-mini-height {
height: 22px;
font-size: 10.5px;
}

1109
lib/ui/static/css/bootstrap-responsive.css vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

6158
lib/ui/static/css/bootstrap.css vendored Normal file

File diff suppressed because it is too large Load Diff

9
lib/ui/static/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

540
lib/ui/static/css/font-awesome.css vendored Executable file
View File

@ -0,0 +1,540 @@
/*!
* Font Awesome 3.0.2
* the iconic font designed for use with Twitter Bootstrap
* -------------------------------------------------------
* The full suite of pictographic icons, examples, and documentation
* can be found at: http://fortawesome.github.com/Font-Awesome/
*
* License
* -------------------------------------------------------
* - The Font Awesome font is licensed under the SIL Open Font License - http://scripts.sil.org/OFL
* - Font Awesome CSS, LESS, and SASS files are licensed under the MIT License -
* http://opensource.org/licenses/mit-license.html
* - The Font Awesome pictograms are licensed under the CC BY 3.0 License - http://creativecommons.org/licenses/by/3.0/
* - Attribution is no longer required in Font Awesome 3.0, but much appreciated:
* "Font Awesome by Dave Gandy - http://fortawesome.github.com/Font-Awesome"
* Contact
* -------------------------------------------------------
* Email: dave@davegandy.com
* Twitter: http://twitter.com/fortaweso_me
* Work: Lead Product Designer @ http://kyruus.com
*/
@font-face {
font-family: 'FontAwesome';
src: url('../font/fontawesome-webfont.eot?v=3.0.1');
src: url('../font/fontawesome-webfont.eot?#iefix&v=3.0.1') format('embedded-opentype'),
url('../font/fontawesome-webfont.woff?v=3.0.1') format('woff'),
url('../font/fontawesome-webfont.ttf?v=3.0.1') format('truetype');
font-weight: normal;
font-style: normal;
}
/* Font Awesome styles
------------------------------------------------------- */
[class^="icon-"],
[class*=" icon-"] {
font-family: FontAwesome;
font-weight: normal;
font-style: normal;
text-decoration: inherit;
-webkit-font-smoothing: antialiased;
/* sprites.less reset */
display: inline;
width: auto;
height: auto;
line-height: normal;
vertical-align: baseline;
background-image: none;
background-position: 0% 0%;
background-repeat: repeat;
margin-top: 0;
}
/* more sprites.less reset */
.icon-white,
.nav-pills > .active > a > [class^="icon-"],
.nav-pills > .active > a > [class*=" icon-"],
.nav-list > .active > a > [class^="icon-"],
.nav-list > .active > a > [class*=" icon-"],
.navbar-inverse .nav > .active > a > [class^="icon-"],
.navbar-inverse .nav > .active > a > [class*=" icon-"],
.dropdown-menu > li > a:hover > [class^="icon-"],
.dropdown-menu > li > a:hover > [class*=" icon-"],
.dropdown-menu > .active > a > [class^="icon-"],
.dropdown-menu > .active > a > [class*=" icon-"],
.dropdown-submenu:hover > a > [class^="icon-"],
.dropdown-submenu:hover > a > [class*=" icon-"] {
background-image: none;
}
[class^="icon-"]:before,
[class*=" icon-"]:before {
text-decoration: inherit;
display: inline-block;
speak: none;
}
/* makes sure icons active on rollover in links */
a [class^="icon-"],
a [class*=" icon-"] {
display: inline-block;
}
/* makes the font 33% larger relative to the icon container */
.icon-large:before {
vertical-align: -10%;
font-size: 1.3333333333333333em;
}
.btn [class^="icon-"],
.nav [class^="icon-"],
.btn [class*=" icon-"],
.nav [class*=" icon-"] {
display: inline;
/* keeps button heights with and without icons the same */
}
.btn [class^="icon-"].icon-large,
.nav [class^="icon-"].icon-large,
.btn [class*=" icon-"].icon-large,
.nav [class*=" icon-"].icon-large {
line-height: .9em;
}
.btn [class^="icon-"].icon-spin,
.nav [class^="icon-"].icon-spin,
.btn [class*=" icon-"].icon-spin,
.nav [class*=" icon-"].icon-spin {
display: inline-block;
}
.nav-tabs [class^="icon-"],
.nav-pills [class^="icon-"],
.nav-tabs [class*=" icon-"],
.nav-pills [class*=" icon-"] {
/* keeps button heights with and without icons the same */
}
.nav-tabs [class^="icon-"],
.nav-pills [class^="icon-"],
.nav-tabs [class*=" icon-"],
.nav-pills [class*=" icon-"],
.nav-tabs [class^="icon-"].icon-large,
.nav-pills [class^="icon-"].icon-large,
.nav-tabs [class*=" icon-"].icon-large,
.nav-pills [class*=" icon-"].icon-large {
line-height: .9em;
}
li [class^="icon-"],
.nav li [class^="icon-"],
li [class*=" icon-"],
.nav li [class*=" icon-"] {
display: inline-block;
width: 1.25em;
text-align: center;
}
li [class^="icon-"].icon-large,
.nav li [class^="icon-"].icon-large,
li [class*=" icon-"].icon-large,
.nav li [class*=" icon-"].icon-large {
/* increased font size for icon-large */
width: 1.5625em;
}
ul.icons {
list-style-type: none;
text-indent: -0.75em;
}
ul.icons li [class^="icon-"],
ul.icons li [class*=" icon-"] {
width: .75em;
}
.icon-muted {
color: #eeeeee;
}
.icon-border {
border: solid 1px #eeeeee;
padding: .2em .25em .15em;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.icon-2x {
font-size: 2em;
}
.icon-2x.icon-border {
border-width: 2px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.icon-3x {
font-size: 3em;
}
.icon-3x.icon-border {
border-width: 3px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
.icon-4x {
font-size: 4em;
}
.icon-4x.icon-border {
border-width: 4px;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
}
.pull-right {
float: right;
}
.pull-left {
float: left;
}
[class^="icon-"].pull-left,
[class*=" icon-"].pull-left {
margin-right: .3em;
}
[class^="icon-"].pull-right,
[class*=" icon-"].pull-right {
margin-left: .3em;
}
.btn [class^="icon-"].pull-left.icon-2x,
.btn [class*=" icon-"].pull-left.icon-2x,
.btn [class^="icon-"].pull-right.icon-2x,
.btn [class*=" icon-"].pull-right.icon-2x {
margin-top: .18em;
}
.btn [class^="icon-"].icon-spin.icon-large,
.btn [class*=" icon-"].icon-spin.icon-large {
line-height: .8em;
}
.btn.btn-small [class^="icon-"].pull-left.icon-2x,
.btn.btn-small [class*=" icon-"].pull-left.icon-2x,
.btn.btn-small [class^="icon-"].pull-right.icon-2x,
.btn.btn-small [class*=" icon-"].pull-right.icon-2x {
margin-top: .25em;
}
.btn.btn-large [class^="icon-"],
.btn.btn-large [class*=" icon-"] {
margin-top: 0;
}
.btn.btn-large [class^="icon-"].pull-left.icon-2x,
.btn.btn-large [class*=" icon-"].pull-left.icon-2x,
.btn.btn-large [class^="icon-"].pull-right.icon-2x,
.btn.btn-large [class*=" icon-"].pull-right.icon-2x {
margin-top: .05em;
}
.btn.btn-large [class^="icon-"].pull-left.icon-2x,
.btn.btn-large [class*=" icon-"].pull-left.icon-2x {
margin-right: .2em;
}
.btn.btn-large [class^="icon-"].pull-right.icon-2x,
.btn.btn-large [class*=" icon-"].pull-right.icon-2x {
margin-left: .2em;
}
.icon-spin {
display: inline-block;
-moz-animation: spin 2s infinite linear;
-o-animation: spin 2s infinite linear;
-webkit-animation: spin 2s infinite linear;
animation: spin 2s infinite linear;
}
@-moz-keyframes spin {
0% { -moz-transform: rotate(0deg); }
100% { -moz-transform: rotate(359deg); }
}
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(359deg); }
}
@-o-keyframes spin {
0% { -o-transform: rotate(0deg); }
100% { -o-transform: rotate(359deg); }
}
@-ms-keyframes spin {
0% { -ms-transform: rotate(0deg); }
100% { -ms-transform: rotate(359deg); }
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(359deg); }
}
@-moz-document url-prefix() {
.icon-spin {
height: .9em;
}
.btn .icon-spin {
height: auto;
}
.icon-spin.icon-large {
height: 1.25em;
}
.btn .icon-spin.icon-large {
height: .75em;
}
}
/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
readers do not read off random characters that represent icons */
.icon-glass:before { content: "\f000"; }
.icon-music:before { content: "\f001"; }
.icon-search:before { content: "\f002"; }
.icon-envelope:before { content: "\f003"; }
.icon-heart:before { content: "\f004"; }
.icon-star:before { content: "\f005"; }
.icon-star-empty:before { content: "\f006"; }
.icon-user:before { content: "\f007"; }
.icon-film:before { content: "\f008"; }
.icon-th-large:before { content: "\f009"; }
.icon-th:before { content: "\f00a"; }
.icon-th-list:before { content: "\f00b"; }
.icon-ok:before { content: "\f00c"; }
.icon-remove:before { content: "\f00d"; }
.icon-zoom-in:before { content: "\f00e"; }
.icon-zoom-out:before { content: "\f010"; }
.icon-off:before { content: "\f011"; }
.icon-signal:before { content: "\f012"; }
.icon-cog:before { content: "\f013"; }
.icon-trash:before { content: "\f014"; }
.icon-home:before { content: "\f015"; }
.icon-file:before { content: "\f016"; }
.icon-time:before { content: "\f017"; }
.icon-road:before { content: "\f018"; }
.icon-download-alt:before { content: "\f019"; }
.icon-download:before { content: "\f01a"; }
.icon-upload:before { content: "\f01b"; }
.icon-inbox:before { content: "\f01c"; }
.icon-play-circle:before { content: "\f01d"; }
.icon-repeat:before { content: "\f01e"; }
/* \f020 doesn't work in Safari. all shifted one down */
.icon-refresh:before { content: "\f021"; }
.icon-list-alt:before { content: "\f022"; }
.icon-lock:before { content: "\f023"; }
.icon-flag:before { content: "\f024"; }
.icon-headphones:before { content: "\f025"; }
.icon-volume-off:before { content: "\f026"; }
.icon-volume-down:before { content: "\f027"; }
.icon-volume-up:before { content: "\f028"; }
.icon-qrcode:before { content: "\f029"; }
.icon-barcode:before { content: "\f02a"; }
.icon-tag:before { content: "\f02b"; }
.icon-tags:before { content: "\f02c"; }
.icon-book:before { content: "\f02d"; }
.icon-bookmark:before { content: "\f02e"; }
.icon-print:before { content: "\f02f"; }
.icon-camera:before { content: "\f030"; }
.icon-font:before { content: "\f031"; }
.icon-bold:before { content: "\f032"; }
.icon-italic:before { content: "\f033"; }
.icon-text-height:before { content: "\f034"; }
.icon-text-width:before { content: "\f035"; }
.icon-align-left:before { content: "\f036"; }
.icon-align-center:before { content: "\f037"; }
.icon-align-right:before { content: "\f038"; }
.icon-align-justify:before { content: "\f039"; }
.icon-list:before { content: "\f03a"; }
.icon-indent-left:before { content: "\f03b"; }
.icon-indent-right:before { content: "\f03c"; }
.icon-facetime-video:before { content: "\f03d"; }
.icon-picture:before { content: "\f03e"; }
.icon-pencil:before { content: "\f040"; }
.icon-map-marker:before { content: "\f041"; }
.icon-adjust:before { content: "\f042"; }
.icon-tint:before { content: "\f043"; }
.icon-edit:before { content: "\f044"; }
.icon-share:before { content: "\f045"; }
.icon-check:before { content: "\f046"; }
.icon-move:before { content: "\f047"; }
.icon-step-backward:before { content: "\f048"; }
.icon-fast-backward:before { content: "\f049"; }
.icon-backward:before { content: "\f04a"; }
.icon-play:before { content: "\f04b"; }
.icon-pause:before { content: "\f04c"; }
.icon-stop:before { content: "\f04d"; }
.icon-forward:before { content: "\f04e"; }
.icon-fast-forward:before { content: "\f050"; }
.icon-step-forward:before { content: "\f051"; }
.icon-eject:before { content: "\f052"; }
.icon-chevron-left:before { content: "\f053"; }
.icon-chevron-right:before { content: "\f054"; }
.icon-plus-sign:before { content: "\f055"; }
.icon-minus-sign:before { content: "\f056"; }
.icon-remove-sign:before { content: "\f057"; }
.icon-ok-sign:before { content: "\f058"; }
.icon-question-sign:before { content: "\f059"; }
.icon-info-sign:before { content: "\f05a"; }
.icon-screenshot:before { content: "\f05b"; }
.icon-remove-circle:before { content: "\f05c"; }
.icon-ok-circle:before { content: "\f05d"; }
.icon-ban-circle:before { content: "\f05e"; }
.icon-arrow-left:before { content: "\f060"; }
.icon-arrow-right:before { content: "\f061"; }
.icon-arrow-up:before { content: "\f062"; }
.icon-arrow-down:before { content: "\f063"; }
.icon-share-alt:before { content: "\f064"; }
.icon-resize-full:before { content: "\f065"; }
.icon-resize-small:before { content: "\f066"; }
.icon-plus:before { content: "\f067"; }
.icon-minus:before { content: "\f068"; }
.icon-asterisk:before { content: "\f069"; }
.icon-exclamation-sign:before { content: "\f06a"; }
.icon-gift:before { content: "\f06b"; }
.icon-leaf:before { content: "\f06c"; }
.icon-fire:before { content: "\f06d"; }
.icon-eye-open:before { content: "\f06e"; }
.icon-eye-close:before { content: "\f070"; }
.icon-warning-sign:before { content: "\f071"; }
.icon-plane:before { content: "\f072"; }
.icon-calendar:before { content: "\f073"; }
.icon-random:before { content: "\f074"; }
.icon-comment:before { content: "\f075"; }
.icon-magnet:before { content: "\f076"; }
.icon-chevron-up:before { content: "\f077"; }
.icon-chevron-down:before { content: "\f078"; }
.icon-retweet:before { content: "\f079"; }
.icon-shopping-cart:before { content: "\f07a"; }
.icon-folder-close:before { content: "\f07b"; }
.icon-folder-open:before { content: "\f07c"; }
.icon-resize-vertical:before { content: "\f07d"; }
.icon-resize-horizontal:before { content: "\f07e"; }
.icon-bar-chart:before { content: "\f080"; }
.icon-twitter-sign:before { content: "\f081"; }
.icon-facebook-sign:before { content: "\f082"; }
.icon-camera-retro:before { content: "\f083"; }
.icon-key:before { content: "\f084"; }
.icon-cogs:before { content: "\f085"; }
.icon-comments:before { content: "\f086"; }
.icon-thumbs-up:before { content: "\f087"; }
.icon-thumbs-down:before { content: "\f088"; }
.icon-star-half:before { content: "\f089"; }
.icon-heart-empty:before { content: "\f08a"; }
.icon-signout:before { content: "\f08b"; }
.icon-linkedin-sign:before { content: "\f08c"; }
.icon-pushpin:before { content: "\f08d"; }
.icon-external-link:before { content: "\f08e"; }
.icon-signin:before { content: "\f090"; }
.icon-trophy:before { content: "\f091"; }
.icon-github-sign:before { content: "\f092"; }
.icon-upload-alt:before { content: "\f093"; }
.icon-lemon:before { content: "\f094"; }
.icon-phone:before { content: "\f095"; }
.icon-check-empty:before { content: "\f096"; }
.icon-bookmark-empty:before { content: "\f097"; }
.icon-phone-sign:before { content: "\f098"; }
.icon-twitter:before { content: "\f099"; }
.icon-facebook:before { content: "\f09a"; }
.icon-github:before { content: "\f09b"; }
.icon-unlock:before { content: "\f09c"; }
.icon-credit-card:before { content: "\f09d"; }
.icon-rss:before { content: "\f09e"; }
.icon-hdd:before { content: "\f0a0"; }
.icon-bullhorn:before { content: "\f0a1"; }
.icon-bell:before { content: "\f0a2"; }
.icon-certificate:before { content: "\f0a3"; }
.icon-hand-right:before { content: "\f0a4"; }
.icon-hand-left:before { content: "\f0a5"; }
.icon-hand-up:before { content: "\f0a6"; }
.icon-hand-down:before { content: "\f0a7"; }
.icon-circle-arrow-left:before { content: "\f0a8"; }
.icon-circle-arrow-right:before { content: "\f0a9"; }
.icon-circle-arrow-up:before { content: "\f0aa"; }
.icon-circle-arrow-down:before { content: "\f0ab"; }
.icon-globe:before { content: "\f0ac"; }
.icon-wrench:before { content: "\f0ad"; }
.icon-tasks:before { content: "\f0ae"; }
.icon-filter:before { content: "\f0b0"; }
.icon-briefcase:before { content: "\f0b1"; }
.icon-fullscreen:before { content: "\f0b2"; }
.icon-group:before { content: "\f0c0"; }
.icon-link:before { content: "\f0c1"; }
.icon-cloud:before { content: "\f0c2"; }
.icon-beaker:before { content: "\f0c3"; }
.icon-cut:before { content: "\f0c4"; }
.icon-copy:before { content: "\f0c5"; }
.icon-paper-clip:before { content: "\f0c6"; }
.icon-save:before { content: "\f0c7"; }
.icon-sign-blank:before { content: "\f0c8"; }
.icon-reorder:before { content: "\f0c9"; }
.icon-list-ul:before { content: "\f0ca"; }
.icon-list-ol:before { content: "\f0cb"; }
.icon-strikethrough:before { content: "\f0cc"; }
.icon-underline:before { content: "\f0cd"; }
.icon-table:before { content: "\f0ce"; }
.icon-magic:before { content: "\f0d0"; }
.icon-truck:before { content: "\f0d1"; }
.icon-pinterest:before { content: "\f0d2"; }
.icon-pinterest-sign:before { content: "\f0d3"; }
.icon-google-plus-sign:before { content: "\f0d4"; }
.icon-google-plus:before { content: "\f0d5"; }
.icon-money:before { content: "\f0d6"; }
.icon-caret-down:before { content: "\f0d7"; }
.icon-caret-up:before { content: "\f0d8"; }
.icon-caret-left:before { content: "\f0d9"; }
.icon-caret-right:before { content: "\f0da"; }
.icon-columns:before { content: "\f0db"; }
.icon-sort:before { content: "\f0dc"; }
.icon-sort-down:before { content: "\f0dd"; }
.icon-sort-up:before { content: "\f0de"; }
.icon-envelope-alt:before { content: "\f0e0"; }
.icon-linkedin:before { content: "\f0e1"; }
.icon-undo:before { content: "\f0e2"; }
.icon-legal:before { content: "\f0e3"; }
.icon-dashboard:before { content: "\f0e4"; }
.icon-comment-alt:before { content: "\f0e5"; }
.icon-comments-alt:before { content: "\f0e6"; }
.icon-bolt:before { content: "\f0e7"; }
.icon-sitemap:before { content: "\f0e8"; }
.icon-umbrella:before { content: "\f0e9"; }
.icon-paste:before { content: "\f0ea"; }
.icon-lightbulb:before { content: "\f0eb"; }
.icon-exchange:before { content: "\f0ec"; }
.icon-cloud-download:before { content: "\f0ed"; }
.icon-cloud-upload:before { content: "\f0ee"; }
.icon-user-md:before { content: "\f0f0"; }
.icon-stethoscope:before { content: "\f0f1"; }
.icon-suitcase:before { content: "\f0f2"; }
.icon-bell-alt:before { content: "\f0f3"; }
.icon-coffee:before { content: "\f0f4"; }
.icon-food:before { content: "\f0f5"; }
.icon-file-alt:before { content: "\f0f6"; }
.icon-building:before { content: "\f0f7"; }
.icon-hospital:before { content: "\f0f8"; }
.icon-ambulance:before { content: "\f0f9"; }
.icon-medkit:before { content: "\f0fa"; }
.icon-fighter-jet:before { content: "\f0fb"; }
.icon-beer:before { content: "\f0fc"; }
.icon-h-sign:before { content: "\f0fd"; }
.icon-plus-sign-alt:before { content: "\f0fe"; }
.icon-double-angle-left:before { content: "\f100"; }
.icon-double-angle-right:before { content: "\f101"; }
.icon-double-angle-up:before { content: "\f102"; }
.icon-double-angle-down:before { content: "\f103"; }
.icon-angle-left:before { content: "\f104"; }
.icon-angle-right:before { content: "\f105"; }
.icon-angle-up:before { content: "\f106"; }
.icon-angle-down:before { content: "\f107"; }
.icon-desktop:before { content: "\f108"; }
.icon-laptop:before { content: "\f109"; }
.icon-tablet:before { content: "\f10a"; }
.icon-mobile-phone:before { content: "\f10b"; }
.icon-circle-blank:before { content: "\f10c"; }
.icon-quote-left:before { content: "\f10d"; }
.icon-quote-right:before { content: "\f10e"; }
.icon-spinner:before { content: "\f110"; }
.icon-circle:before { content: "\f111"; }
.icon-reply:before { content: "\f112"; }
.icon-github-alt:before { content: "\f113"; }
.icon-folder-close-alt:before { content: "\f114"; }
.icon-folder-open-alt:before { content: "\f115"; }

33
lib/ui/static/css/font-awesome.min.css vendored Executable file

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,284 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata></metadata>
<defs>
<font id="fontawesomeregular" horiz-adv-x="1536" >
<font-face units-per-em="1792" ascent="1536" descent="-256" />
<missing-glyph horiz-adv-x="448" />
<glyph unicode=" " horiz-adv-x="448" />
<glyph unicode="&#x09;" horiz-adv-x="448" />
<glyph unicode="&#xa0;" horiz-adv-x="448" />
<glyph unicode="&#xa8;" horiz-adv-x="1792" />
<glyph unicode="&#xa9;" horiz-adv-x="1792" />
<glyph unicode="&#xae;" horiz-adv-x="1792" />
<glyph unicode="&#xb4;" horiz-adv-x="1792" />
<glyph unicode="&#xc6;" horiz-adv-x="1792" />
<glyph unicode="&#x2000;" horiz-adv-x="768" />
<glyph unicode="&#x2001;" />
<glyph unicode="&#x2002;" horiz-adv-x="768" />
<glyph unicode="&#x2003;" />
<glyph unicode="&#x2004;" horiz-adv-x="512" />
<glyph unicode="&#x2005;" horiz-adv-x="384" />
<glyph unicode="&#x2006;" horiz-adv-x="256" />
<glyph unicode="&#x2007;" horiz-adv-x="256" />
<glyph unicode="&#x2008;" horiz-adv-x="192" />
<glyph unicode="&#x2009;" horiz-adv-x="307" />
<glyph unicode="&#x200a;" horiz-adv-x="85" />
<glyph unicode="&#x202f;" horiz-adv-x="307" />
<glyph unicode="&#x205f;" horiz-adv-x="384" />
<glyph unicode="&#x2122;" horiz-adv-x="1792" />
<glyph unicode="&#x221e;" horiz-adv-x="1792" />
<glyph unicode="&#x2260;" horiz-adv-x="1792" />
<glyph unicode="&#xe000;" horiz-adv-x="500" d="M0 0z" />
<glyph unicode="&#xf000;" horiz-adv-x="1792" d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" />
<glyph unicode="&#xf001;" d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89 t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf002;" horiz-adv-x="1664" d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5 t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
<glyph unicode="&#xf003;" horiz-adv-x="1792" d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13 t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf004;" horiz-adv-x="1792" d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600 q-18 -18 -44 -18z" />
<glyph unicode="&#xf005;" horiz-adv-x="1664" d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455 l502 -73q56 -9 56 -46z" />
<glyph unicode="&#xf006;" horiz-adv-x="1664" d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" />
<glyph unicode="&#xf007;" horiz-adv-x="1408" d="M1408 131q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81 t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
<glyph unicode="&#xf008;" horiz-adv-x="1920" d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128 q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45 t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128 q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19 t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf009;" horiz-adv-x="1664" d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38 h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
<glyph unicode="&#xf00a;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf00b;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf00c;" horiz-adv-x="1792" d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" />
<glyph unicode="&#xf00d;" horiz-adv-x="1408" d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68 t-28 -68l-294 -294l294 -294q28 -28 28 -68z" />
<glyph unicode="&#xf00e;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224 q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5 t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
<glyph unicode="&#xf010;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z " />
<glyph unicode="&#xf011;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5 t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" />
<glyph unicode="&#xf012;" horiz-adv-x="1792" d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" />
<glyph unicode="&#xf013;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38 q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13 l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22 q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" />
<glyph unicode="&#xf014;" horiz-adv-x="1408" d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832 q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
<glyph unicode="&#xf015;" horiz-adv-x="1664" d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5 l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" />
<glyph unicode="&#xf016;" horiz-adv-x="1280" d="M128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280zM768 896h299l-299 299v-299zM1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h544q40 0 88 -20t76 -48l408 -408q28 -28 48 -76t20 -88z" />
<glyph unicode="&#xf017;" d="M1088 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-384q-13 0 -22.5 9.5t-9.5 22.5v448q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-352h288q13 0 22.5 -9.5t9.5 -22.5zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5 t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5 t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf018;" horiz-adv-x="1920" d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256 q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" />
<glyph unicode="&#xf019;" horiz-adv-x="1664" d="M1339 729q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39zM1632 512q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-1600q-14 0 -23 9t-9 23v576q0 14 9 23 t23 9h192q14 0 23 -9t9 -23v-352h1152v352q0 14 9 23t23 9h192z" />
<glyph unicode="&#xf01a;" d="M1120 608q0 -12 -10 -24l-319 -319q-9 -9 -23 -9t-23 9l-320 320q-9 9 -9 23q0 13 9.5 22.5t22.5 9.5h192v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352h192q14 0 23 -9t9 -23zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5 t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5 t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf01b;" d="M1120 672q0 -13 -9.5 -22.5t-22.5 -9.5h-192v-352q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q9 9 23 9t23 -9l320 -320q9 -9 9 -23zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5 t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf01c;" d="M1023 576h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8t-2.5 -8h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552 q25 -61 25 -123z" />
<glyph unicode="&#xf01d;" d="M1152 640q0 -37 -33 -56l-512 -288q-14 -8 -31 -8t-32 9q-32 18 -32 55v576q0 37 32 55q31 20 63 1l512 -288q33 -19 33 -56zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5 t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf01e;" d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q169 0 304 99.5t185 261.5q7 23 30 23h199 q16 0 25 -12q10 -13 7 -27q-39 -175 -147.5 -312t-266 -213t-336.5 -76q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" />
<glyph unicode="&#xf021;" d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117 q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5 q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" />
<glyph unicode="&#xf022;" horiz-adv-x="1792" d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5 t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47 t47 -113z" />
<glyph unicode="&#xf023;" horiz-adv-x="1152" d="M704 512q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5q0 -37 19 -67t51 -47l-69 -229q-5 -15 5 -28t26 -13h192q16 0 26 13t5 28l-69 229q32 17 51 47t19 67zM320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68 t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf024;" horiz-adv-x="1792" d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf025;" horiz-adv-x="1664" d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78 t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5 t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" />
<glyph unicode="&#xf026;" horiz-adv-x="768" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" />
<glyph unicode="&#xf027;" horiz-adv-x="1152" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" />
<glyph unicode="&#xf028;" horiz-adv-x="1664" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5 t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289 t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" />
<glyph unicode="&#xf029;" horiz-adv-x="1408" d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" />
<glyph unicode="&#xf02a;" horiz-adv-x="1792" d="M672 1408v-1536h-64v1536h64zM1408 1408v-1536h-64v1536h64zM1568 1408v-1536h-64v1536h64zM576 1408v-1536h-64v1536h64zM1280 1408v-1536h-256v1536h256zM896 1408v-1536h-128v1536h128zM448 1408v-1536h-128v1536h128zM1792 1408v-1536h-128v1536h128zM256 1408v-1536 h-256v1536h256z" />
<glyph unicode="&#xf02b;" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91z" />
<glyph unicode="&#xf02c;" horiz-adv-x="1920" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" />
<glyph unicode="&#xf02d;" horiz-adv-x="1664" d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23 q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906 q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5 t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" />
<glyph unicode="&#xf02e;" horiz-adv-x="1280" d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
<glyph unicode="&#xf02f;" horiz-adv-x="1664" d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68 v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" />
<glyph unicode="&#xf030;" horiz-adv-x="1920" d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136 q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
<glyph unicode="&#xf031;" horiz-adv-x="1664" d="M725 977l-170 -450q73 -1 153.5 -2t119 -1.5t52.5 -0.5l29 2q-32 95 -92 241q-53 132 -92 211zM21 -128h-21l2 79q22 7 80 18q89 16 110 31q20 16 48 68l237 616l280 724h75h53l11 -21l205 -480q103 -242 124 -297q39 -102 96 -235q26 -58 65 -164q24 -67 65 -149 q22 -49 35 -57q22 -19 69 -23q47 -6 103 -27q6 -39 6 -57q0 -14 -1 -26q-80 0 -192 8q-93 8 -189 8q-79 0 -135 -2l-200 -11l-58 -2q0 45 4 78l131 28q56 13 68 23q12 12 12 27t-6 32l-47 114l-92 228l-450 2q-29 -65 -104 -274q-23 -64 -23 -84q0 -31 17 -43 q26 -21 103 -32q3 0 13.5 -2t30 -5t40.5 -6q1 -28 1 -58q0 -17 -2 -27q-66 0 -349 20l-48 -8q-81 -14 -167 -14z" />
<glyph unicode="&#xf032;" horiz-adv-x="1408" d="M555 15q76 -32 140 -32q131 0 216 41t122 113q38 70 38 181q0 114 -41 180q-58 94 -141 126q-80 32 -247 32q-74 0 -101 -10v-144l-1 -173l3 -270q0 -15 12 -44zM541 761q43 -7 109 -7q175 0 264 65t89 224q0 112 -85 187q-84 75 -255 75q-52 0 -130 -13q0 -44 2 -77 q7 -122 6 -279l-1 -98q0 -43 1 -77zM0 -128l2 94q45 9 68 12q77 12 123 31q17 27 21 51q9 66 9 194l-2 497q-5 256 -9 404q-1 87 -11 109q-1 4 -12 12q-18 12 -69 15q-30 2 -114 13l-4 83l260 6l380 13l45 1q5 0 14 0.5t14 0.5q1 0 21.5 -0.5t40.5 -0.5h74q88 0 191 -27 q43 -13 96 -39q57 -29 102 -76q44 -47 65 -104t21 -122q0 -70 -32 -128t-95 -105q-26 -20 -150 -77q177 -41 267 -146q92 -106 92 -236q0 -76 -29 -161q-21 -62 -71 -117q-66 -72 -140 -108q-73 -36 -203 -60q-82 -15 -198 -11l-197 4q-84 2 -298 -11q-33 -3 -272 -11z" />
<glyph unicode="&#xf033;" horiz-adv-x="1024" d="M0 -126l17 85q4 1 77 20q76 19 116 39q29 37 41 101l27 139l56 268l12 64q8 44 17 84.5t16 67t12.5 46.5t9 30.5t3.5 11.5l29 157l16 63l22 135l8 50v38q-41 22 -144 28q-28 2 -38 4l19 103l317 -14q39 -2 73 -2q66 0 214 9q33 2 68 4.5t36 2.5q-2 -19 -6 -38 q-7 -29 -13 -51q-55 -19 -109 -31q-64 -16 -101 -31q-12 -31 -24 -88q-9 -44 -13 -82q-44 -199 -66 -306l-61 -311l-38 -158l-43 -235l-12 -45q-2 -7 1 -27q64 -15 119 -21q36 -5 66 -10q-1 -29 -7 -58q-7 -31 -9 -41q-18 0 -23 -1q-24 -2 -42 -2q-9 0 -28 3q-19 4 -145 17 l-198 2q-41 1 -174 -11q-74 -7 -98 -9z" />
<glyph unicode="&#xf034;" horiz-adv-x="1792" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l215 -1h293l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -42.5 2t-103.5 -1t-111 -1 q-34 0 -67 -5q-10 -97 -8 -136l1 -152v-332l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-88 0 -233 -14q-48 -4 -70 -4q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q8 192 6 433l-5 428q-1 62 -0.5 118.5t0.5 102.5t-2 57t-6 15q-6 5 -14 6q-38 6 -148 6q-43 0 -100 -13.5t-73 -24.5q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1744 128q33 0 42 -18.5t-11 -44.5 l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80z" />
<glyph unicode="&#xf035;" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l446 -1h318l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -58.5 2t-138.5 -1t-128 -1 q-94 0 -127 -5q-10 -97 -8 -136l1 -152v52l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-82 0 -233 -13q-45 -5 -70 -5q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q6 137 6 433l-5 44q0 265 -2 278q-2 11 -6 15q-6 5 -14 6q-38 6 -148 6q-50 0 -168.5 -14t-132.5 -24q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1505 113q26 -20 26 -49t-26 -49l-162 -126 q-26 -20 -44.5 -11t-18.5 42v80h-1024v-80q0 -33 -18.5 -42t-44.5 11l-162 126q-26 20 -26 49t26 49l162 126q26 20 44.5 11t18.5 -42v-80h1024v80q0 33 18.5 42t44.5 -11z" />
<glyph unicode="&#xf036;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf037;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19 h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf038;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf039;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf03a;" horiz-adv-x="1792" d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5 t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344 q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192 q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" />
<glyph unicode="&#xf03b;" horiz-adv-x="1792" d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
<glyph unicode="&#xf03c;" horiz-adv-x="1792" d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
<glyph unicode="&#xf03d;" horiz-adv-x="1920" d="M1900 1278q20 -8 20 -30v-1216q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-585 586v-307q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-307l585 586q16 15 35 7z" />
<glyph unicode="&#xf03e;" horiz-adv-x="1920" d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216 q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf040;" d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38 q53 0 91 -38l235 -234q37 -39 37 -91z" />
<glyph unicode="&#xf041;" horiz-adv-x="1024" d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" />
<glyph unicode="&#xf042;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM256 640q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5v1024q-104 0 -198.5 -40.5 t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5z" />
<glyph unicode="&#xf043;" horiz-adv-x="1024" d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362 q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" />
<glyph unicode="&#xf044;" horiz-adv-x="1792" d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92 l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" />
<glyph unicode="&#xf045;" horiz-adv-x="1664" d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832 q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5 t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" />
<glyph unicode="&#xf046;" horiz-adv-x="1664" d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832 q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110 q24 -24 24 -57t-24 -57z" />
<glyph unicode="&#xf047;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45 t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
<glyph unicode="&#xf048;" horiz-adv-x="1024" d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19z" />
<glyph unicode="&#xf049;" horiz-adv-x="1792" d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z" />
<glyph unicode="&#xf04a;" horiz-adv-x="1664" d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19z" />
<glyph unicode="&#xf04b;" horiz-adv-x="1408" d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" />
<glyph unicode="&#xf04c;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf04d;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf04e;" horiz-adv-x="1664" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
<glyph unicode="&#xf050;" horiz-adv-x="1792" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710 q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
<glyph unicode="&#xf051;" horiz-adv-x="1024" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19z" />
<glyph unicode="&#xf052;" horiz-adv-x="1538" d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" />
<glyph unicode="&#xf053;" horiz-adv-x="1152" d="M742 -37l-652 651q-37 37 -37 90.5t37 90.5l652 651q37 37 90.5 37t90.5 -37l75 -75q37 -37 37 -90.5t-37 -90.5l-486 -486l486 -485q37 -38 37 -91t-37 -90l-75 -75q-37 -37 -90.5 -37t-90.5 37z" />
<glyph unicode="&#xf054;" horiz-adv-x="1152" d="M1099 704q0 -52 -37 -91l-652 -651q-37 -37 -90 -37t-90 37l-76 75q-37 39 -37 91q0 53 37 90l486 486l-486 485q-37 39 -37 91q0 53 37 90l76 75q36 38 90 38t90 -38l652 -651q37 -37 37 -90z" />
<glyph unicode="&#xf055;" d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf056;" d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
<glyph unicode="&#xf057;" d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19 q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf058;" d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf059;" d="M896 160v192q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-192q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1152 832q0 97 -58.5 172t-144.5 111.5t-181 36.5t-181 -36.5t-144.5 -111.5t-58.5 -172v-11v-13t1 -11.5t3 -11.5t5.5 -8t9 -7 t13.5 -2h192q14 0 23 9t9 23q0 12 11 27q19 31 50.5 50t66.5 19q39 0 83 -21.5t44 -57.5q0 -33 -26.5 -58t-63.5 -44t-74.5 -41.5t-64 -63.5t-26.5 -98v-11v-13t1 -11.5t3 -11.5t5.5 -8t9 -7t13.5 -2h192q17 0 24 10.5t8 24.5t13.5 33t37.5 32q60 33 70 39q62 44 98.5 108 t36.5 137zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf05a;" d="M1024 160v64q0 14 -9 23t-23 9h-96v480q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h96v-384h-96q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 928v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23 t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf05b;" d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109 q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143 q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf05c;" d="M1125 448q0 -27 -18 -45l-102 -102q-18 -18 -45 -18t-45 18l-147 147l-147 -147q-18 -18 -45 -18t-45 18l-102 102q-18 18 -18 45t18 45l147 147l-147 147q-18 18 -18 45t18 45l102 102q18 18 45 18t45 -18l147 -147l147 147q18 18 45 18t45 -18l102 -102q18 -18 18 -45 t-18 -45l-147 -147l147 -147q18 -18 18 -45zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5 t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf05d;" d="M1189 768q0 -27 -18 -45l-320 -320l-102 -102q-18 -18 -45 -18t-45 18l-102 102l-192 192q-18 18 -18 45t18 45l102 102q18 18 45 18t45 -18l147 -147l275 275q18 18 45 18t45 -18l102 -102q18 -18 18 -45zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5 t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf05e;" d="M1280 640q0 139 -71 260l-701 -701q121 -71 260 -71q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM327 380l701 701q-121 71 -260 71q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5q0 -139 71 -260zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf060;" d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5 t32.5 -90.5z" />
<glyph unicode="&#xf061;" d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" />
<glyph unicode="&#xf062;" horiz-adv-x="1664" d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651 q37 -39 37 -91z" />
<glyph unicode="&#xf063;" horiz-adv-x="1664" d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
<glyph unicode="&#xf064;" horiz-adv-x="1792" d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22 t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" />
<glyph unicode="&#xf065;" d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332 q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf066;" d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45 t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" />
<glyph unicode="&#xf067;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf068;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf069;" horiz-adv-x="1664" d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154 q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" />
<glyph unicode="&#xf06a;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192 q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" />
<glyph unicode="&#xf06b;" d="M928 180v716h-320v-716q0 -25 18.5 -38.5t45.5 -13.5h192q27 0 45.5 13.5t18.5 38.5zM472 1024h195l-126 161q-24 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-45 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320 q0 -14 -10 -22t-27 -10.5t-32 -2.5t-34.5 1.5t-24.5 1.5v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416q-5 0 -24.5 -1.5t-34.5 -1.5t-32 2.5t-27 10.5t-10 22v320q0 13 9.5 22.5t22.5 9.5h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5 q108 0 168 -77l128 -165l128 165q60 77 168 77q93 0 158.5 -65.5t65.5 -158.5t-65.5 -158.5t-158.5 -65.5h440q13 0 22.5 -9.5t9.5 -22.5z" />
<glyph unicode="&#xf06c;" horiz-adv-x="1792" d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268 q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5 t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" />
<glyph unicode="&#xf06d;" horiz-adv-x="1408" d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1 q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" />
<glyph unicode="&#xf06e;" horiz-adv-x="1792" d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" />
<glyph unicode="&#xf070;" horiz-adv-x="1792" d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9 q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5 q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z " />
<glyph unicode="&#xf071;" horiz-adv-x="1792" d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185 q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" />
<glyph unicode="&#xf072;" horiz-adv-x="1408" d="M1397 1324q0 -87 -149 -236l-240 -240l143 -746l1 -6q0 -14 -9 -23l-64 -64q-9 -9 -23 -9q-21 0 -29 18l-274 575l-245 -245q68 -238 68 -252t-9 -23l-64 -64q-9 -9 -23 -9q-18 0 -28 16l-155 280l-280 155q-17 9 -17 28q0 14 9 23l64 65q9 9 23 9t252 -68l245 245 l-575 274q-18 8 -18 29q0 14 9 23l64 64q9 9 23 9q4 0 6 -1l746 -143l240 240q149 149 236 149q32 0 52.5 -20.5t20.5 -52.5z" />
<glyph unicode="&#xf073;" horiz-adv-x="1664" d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64 q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47 h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
<glyph unicode="&#xf074;" horiz-adv-x="1792" d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1 t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5 v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111 t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
<glyph unicode="&#xf075;" horiz-adv-x="1792" d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281 q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" />
<glyph unicode="&#xf076;" d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384 q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf077;" horiz-adv-x="1664" d="M1611 320q0 -53 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-486 485l-486 -485q-36 -38 -90 -38t-90 38l-75 75q-38 36 -38 90q0 53 38 91l651 651q37 37 90 37q52 0 91 -37l650 -651q38 -38 38 -91z" />
<glyph unicode="&#xf078;" horiz-adv-x="1664" d="M1611 832q0 -53 -37 -90l-651 -651q-38 -38 -91 -38q-54 0 -90 38l-651 651q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l486 -486l486 486q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
<glyph unicode="&#xf079;" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z " />
<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5 l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5 t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
<glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" />
<glyph unicode="&#xf07d;" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" />
<glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
<glyph unicode="&#xf080;" horiz-adv-x="1920" d="M512 512v-384h-256v384h256zM896 1024v-896h-256v896h256zM1280 768v-640h-256v640h256zM1664 1152v-1024h-256v1024h256zM1792 32v1216q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5z M1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf081;" d="M1280 958q0 13 -9.5 22.5t-22.5 9.5q-5 0 -15 -4q20 34 20 55q0 13 -9.5 22.5t-22.5 9.5q-7 0 -17 -5q-60 -34 -97 -43q-65 63 -154 63q-98 0 -164.5 -72.5t-64.5 -169.5v-12q-107 14 -187.5 64t-156.5 139q-10 12 -28 12q-26 0 -41 -50.5t-15 -86.5q0 -62 29 -117 q-13 -2 -21.5 -11.5t-8.5 -22.5q0 -112 81 -185q-12 -8 -12 -25q0 -6 1 -9q15 -51 50.5 -91.5t84.5 -60.5q-77 -43 -165 -43q-8 0 -24 1.5t-23 1.5q-13 0 -22.5 -9.5t-9.5 -22.5q0 -17 14 -26q63 -47 150 -73.5t170 -26.5q130 0 248 58q166 79 256 232.5t88 339.5v12 q27 22 62.5 63t35.5 61zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf082;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-350q-2 0 -2 1v671h177q31 0 32 23l12 164q2 15 -8 25q-10 12 -24 12h-189v72q0 44 11.5 57t54.5 13q57 0 117 -13q13 -3 26 5q11 8 13 22l23 166q2 12 -5.5 22.5t-19.5 13.5 q-93 26 -197 26q-311 0 -311 -299v-85h-95q-13 0 -23 -10.5t-10 -24.5v-172q0 -8 5.5 -12t10 -4.5t17.5 -0.5h95v-671l10 -1h-330q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
<glyph unicode="&#xf083;" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280 q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" />
<glyph unicode="&#xf084;" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5 t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" />
<glyph unicode="&#xf085;" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5 l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7 l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31 q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20 t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68 q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70 q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" />
<glyph unicode="&#xf086;" horiz-adv-x="1792" d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224 q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7 q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" />
<glyph unicode="&#xf087;" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5 t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769 q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128 q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" />
<glyph unicode="&#xf088;" d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5 t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5 h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -74 49 -163z" />
<glyph unicode="&#xf089;" horiz-adv-x="896" d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" />
<glyph unicode="&#xf08a;" horiz-adv-x="1792" d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559 q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5 q224 0 351 -124t127 -344z" />
<glyph unicode="&#xf08b;" horiz-adv-x="1664" d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704 q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" />
<glyph unicode="&#xf08c;" d="M512 160v640q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-640q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM503 1028q0 51 -36 87.5t-88 36.5q-51 0 -87 -36.5t-36 -87.5t36 -87.5t87 -36.5q52 0 88 36.5t36 87.5zM1280 160v435 q0 127 -73.5 192.5t-202.5 65.5q-90 0 -158 -45q-12 -8 -14 -12q0 36 -35 36h-176q-14 0 -29.5 -7.5t-15.5 -20.5v-644q0 -13 15.5 -22.5t29.5 -9.5h182q12 0 20.5 9.5t8.5 22.5v349q0 140 114 140q49 0 63.5 -22.5t14.5 -73.5v-393q0 -13 12 -22.5t26 -9.5h186 q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf08d;" horiz-adv-x="1152" d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38 t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" />
<glyph unicode="&#xf08e;" horiz-adv-x="1792" d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf090;" d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5 q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf091;" horiz-adv-x="1664" d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91 t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96 q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf092;" d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -26t19 -63zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85 q0 -52 41 -77v-3q-113 -37 -113 -139q0 -60 36 -98t84 -51t107 -13q224 0 224 187q0 48 -25.5 78t-62.5 42.5t-74 21.5t-62.5 23.5t-25.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q30 7 49 13zM771 350h137q-2 20 -2 90v372q0 59 2 76h-137q3 -26 3 -79v-377 q0 -55 -3 -82zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q4 0 11.5 -0.5t11.5 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072 q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf093;" horiz-adv-x="1664" d="M1664 480v-576q0 -13 -9.5 -22.5t-22.5 -9.5h-1600q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352h1152v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1344 832q0 -26 -19 -45t-45 -19h-256v-448 q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
<glyph unicode="&#xf094;" d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5 q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44 q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5 q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -10 1 -18.5t3 -17t4 -13.5t6.5 -16t6.5 -17q16 -40 25 -118.5t9 -136.5z" />
<glyph unicode="&#xf095;" horiz-adv-x="1408" d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5 q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174 q2 -1 19 -11.5t24 -14t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" />
<glyph unicode="&#xf096;" horiz-adv-x="1664" d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf097;" horiz-adv-x="1280" d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289 q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
<glyph unicode="&#xf098;" d="M1280 343q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5 t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5t320.5 -216.5q6 -2 30 -11t33 -12.5 t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf099;" horiz-adv-x="1920" d="M1875 1202q0 -10 -5 -18q-64 -104 -179 -190v-33q4 -227 -100 -457q-134 -297 -397.5 -464.5t-591.5 -167.5q-265 0 -500 122q-64 33 -87 50q-15 12 -15 27q0 13 9.5 22.5t22.5 9.5q14 0 44 -2.5t45 -2.5q204 0 375 106q-103 24 -181 96t-111 173q-2 8 -2 11q0 12 9 21.5 t22 9.5q5 0 14 -2t12 -2q-89 55 -142 147t-53 196q0 15 11.5 25.5t27.5 10.5q10 0 35 -11.5t30 -13.5q-92 110 -92 256q0 51 14.5 108t40.5 95q10 16 25 16q16 0 27 -12q76 -84 110 -115q123 -111 276 -177.5t317 -80.5q-4 21 -4 49q0 167 118.5 285.5t285.5 118.5 q163 0 282 -114q95 20 209 82q8 5 16 5q13 0 22.5 -9.5t9.5 -22.5q0 -24 -28 -73t-51 -76q7 2 30 10.5t43 16t24 7.5q13 0 22.5 -9.5t9.5 -22.5z" />
<glyph unicode="&#xf09a;" horiz-adv-x="768" d="M560 1125q-49 0 -62 -15.5t-13 -66.5v-88h217q16 0 27 -12q11 -13 10 -29l-14 -200q-2 -15 -12.5 -25.5t-25.5 -10.5h-202v-768q0 -16 -11 -27t-26 -11h-250q-16 0 -27 11t-11 27v768h-122q-16 0 -27 11.5t-11 27.5v200q0 16 11 27t27 11h122v103q0 177 88 263.5 t267 86.5q120 0 225 -30q14 -4 22 -16t6 -26l-27 -195q-2 -16 -16 -26q-14 -9 -30 -6q-76 16 -135 16z" />
<glyph unicode="&#xf09b;" d="M1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5q0 -209 124.5 -378.5t323.5 -231.5v169q-54 -7 -69 -7q-110 0 -153 100q-15 38 -36 63q-5 6 -21 19t-28.5 24t-12.5 16q0 12 28 12q29 0 51.5 -14.5t38 -35 t31.5 -41.5t40.5 -35.5t56.5 -14.5q42 0 81 14q16 57 63 89q-166 16 -246 83.5t-80 224.5q0 118 73 198q-14 42 -14 84q0 58 27 109q57 0 101 -19.5t101 -60.5q76 18 169 18q80 0 153 -16q57 40 100.5 59t99.5 19q27 -51 27 -109q0 -43 -14 -83q73 -82 73 -199 q0 -157 -80 -225.5t-245 -83.5q69 -47 69 -131v-226q199 62 323.5 231.5t124.5 378.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf09c;" horiz-adv-x="1664" d="M704 160q0 6 -15 57t-35 115.5t-20 65.5q32 16 51 47t19 67q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5q0 -36 19 -66.5t51 -47.5q0 -2 -20 -66t-35 -115t-15 -57q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1664 960v-256q0 -26 -19 -45t-45 -19 h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5z" />
<glyph unicode="&#xf09d;" horiz-adv-x="1920" d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608 q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" />
<glyph unicode="&#xf09e;" horiz-adv-x="1408" d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5 t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294 q187 -186 294 -425.5t120 -501.5z" />
<glyph unicode="&#xf0a0;" d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5 h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75 l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" />
<glyph unicode="&#xf0a1;" horiz-adv-x="1792" d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5 t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" />
<glyph unicode="&#xf0a2;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM183 128h1298q-164 181 -246.5 411.5t-82.5 484.5q0 256 -320 256t-320 -256q0 -254 -82.5 -484.5t-246.5 -411.5zM1664 128q0 -52 -38 -90t-90 -38 h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" />
<glyph unicode="&#xf0a3;" d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70 l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70 l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" />
<glyph unicode="&#xf0a4;" horiz-adv-x="1792" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106 q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43 q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5 t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" />
<glyph unicode="&#xf0a5;" horiz-adv-x="1792" d="M1376 128h32v640h-32q-35 0 -67 11.5t-64 38.5t-48 44t-50 55q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576 q-50 0 -89 -38.5t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45 t45 -19t45 19t19 45zM1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128 q0 122 81.5 189t206.5 67q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" />
<glyph unicode="&#xf0a6;" d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576 q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5 t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76 q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" />
<glyph unicode="&#xf0a7;" d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -46 -25 -91t-52 -72t-72 -66q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33t55 33 t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580q0 -142 -77.5 -230 t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100q3 2 17 14t21.5 19 t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" />
<glyph unicode="&#xf0a8;" d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf0a9;" d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf0aa;" d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf0ab;" d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf0ac;" d="M1193 993q11 7 25 22v-1q0 -2 -9.5 -10t-11.5 -12q-1 1 -4 1zM1187 992q-1 1 -2.5 3t-1.5 3q3 -2 10 -5q-6 -4 -6 -1zM728 1175q-16 2 -26 5q1 0 6.5 -1t10.5 -2t9 -2zM773 1212q7 4 13.5 2.5t7.5 -7.5q-5 3 -21 5zM765 1206l-3 2q-2 3 -5.5 5t-4.5 2q2 -1 21 -3 q-6 -4 -8 -6zM663 1290v2q1 -2 3 -5.5t3 -5.5zM558 1250q0 -2 -1 -2l-1 2h2zM933 206v-1v1zM768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1240 162 l5 5q-7 10 -29 12q1 12 -14 26.5t-27 15.5q0 4 -10.5 11t-17.5 8q-9 2 -27 -9q-7 -3 -4 -5q-3 3 -12 11t-16 11q-2 1 -7.5 1t-8.5 2q-1 1 -6 4.5t-7 4.5t-6.5 3t-7.5 1.5t-7.5 -2.5t-8.5 -6t-4.5 -15.5t-2.5 -14.5q-8 6 -0.5 20t1.5 20q-7 7 -21 0.5t-21 -15.5 q-1 -1 -9.5 -5.5t-11.5 -7.5q-4 -6 -9 -17.5t-6 -13.5q0 2 -2.5 6.5t-2.5 6.5q-12 -2 -16 3q5 -16 8 -17l-4 2q-1 -6 3 -15t4 -11q1 -5 -1.5 -13t-2.5 -11q0 -2 5 -11q4 -19 -2 -32q0 -1 -3.5 -7t-6.5 -11l-2 -5l-2 1q-1 1 -2 0q-1 -6 -9 -13t-10 -11q-15 -23 -9 -38 q3 -8 10 -10q3 -1 3 2q1 -9 -11 -27q1 -1 4 -3q-17 0 -10 -14q202 36 352 181h-3zM680 347q16 3 30.5 -16t22.5 -23q41 -20 59 -11q0 -9 14 -28q3 -4 6.5 -11.5t5.5 -10.5q5 -7 19 -16t19 -16q6 3 9 9q13 -35 24 -34q5 0 8 8q0 -1 -0.5 -3t-1.5 -3q7 15 5 26l6 4q5 4 5 5 q-6 6 -9 -3q-30 -14 -48 22q-2 3 -4.5 8t-5 12t-1.5 11.5t6 4.5q11 0 12.5 1.5t-2.5 6t-4 7.5q-1 4 -1.5 12.5t-1.5 12.5l-5 6q-5 6 -11.5 13.5t-7.5 9.5q-4 -10 -16.5 -8.5t-18.5 9.5q1 -2 -0.5 -6.5t-1.5 -6.5q-14 0 -17 1q1 6 3 21t4 22q1 5 5.5 13.5t8 15.5t4.5 14 t-4.5 10.5t-18.5 2.5q-20 -1 -29 -22q-1 -3 -3 -11.5t-5 -12.5t-9 -7q-8 -3 -27 -2t-26 5q-14 8 -24 30.5t-11 41.5q0 10 3 27.5t3 27t-6 26.5q3 2 10 10.5t11 11.5q2 2 5 2h5t4 2t3 6q-1 1 -4 3q-3 3 -4 3q4 -3 19 -1t19 2q0 1 22 0q17 -13 24 2q0 1 -2.5 10.5t-0.5 14.5 q5 -29 32 -10q3 -4 16.5 -6t18.5 -5q3 -2 7 -5.5t6 -5t6 -0.5t9 7q11 -17 13 -25q11 -43 20 -48q8 -2 12.5 -2t5 10.5t0 15.5t-1.5 13l-2 37q-16 3 -20 12.5t1.5 20t16.5 19.5q1 1 16.5 8t21.5 12q24 19 17 39q9 -2 11 9l-5 3q-4 3 -8 5.5t-5 1.5q11 7 2 18q5 3 8 11.5 t9 11.5q9 -14 22 -3q8 9 2 18q5 8 22 11.5t20 9.5q5 -1 7 0t2 4.5v7.5t1 8.5t3 7.5q4 6 16 10.5t14 5.5l19 12q4 4 0 4q18 -2 32 11q13 12 -5 23q2 7 -4 10.5t-16 5.5q3 1 12 0.5t12 1.5q15 11 -7 17q-20 5 -47 -13q-3 -2 -13 -12t-17 -11q15 18 5 22q8 -1 22.5 9t15.5 11 q4 2 10.5 2.5t8.5 1.5q71 25 92 -1q8 11 11 15t9.5 9t15.5 8q21 7 23 9l1 23q-12 -1 -18 8t-7 22l-6 -8q0 6 -3.5 7.5t-7.5 0.5t-9.5 -2t-7.5 0q-9 2 -19.5 15.5t-14.5 16.5q9 0 9 5q-2 5 -10 8q1 6 -2 8t-9 0q-2 12 -1 13q-6 1 -11 11t-8 10q-2 0 -4.5 -2t-5 -5.5l-5 -7 t-3.5 -5.5l-2 -2q-12 6 -24 -10q-9 1 -17 -2q15 6 2 13q-11 5 -21 2q12 5 10 14t-12 16q1 0 4 -1t4 -1q-1 5 -9.5 9.5t-19.5 9t-14 6.5q-7 5 -36 10.5t-36 1.5q-5 -3 -6 -6t1.5 -8.5t3.5 -8.5q6 -23 5 -27q-1 -3 -8.5 -8t-5.5 -12q1 -4 11.5 -10t12.5 -12q5 -13 -4 -25 q-4 -5 -15 -11t-14 -10q-5 -5 -3.5 -11.5t0.5 -9.5q1 1 1 2.5t1 2.5q0 -13 11 -22q8 -6 -16 -18q-20 -11 -20 -4q1 8 -7.5 16t-10.5 12t-3.5 19t-9.5 21q-6 4 -19 4t-18 -5q0 10 -49 30q-17 8 -58 4q7 1 0 17q-8 16 -21 12q-8 25 -4 35q2 5 9 14t9 15q1 3 15.5 6t16.5 8 q1 4 -2.5 6.5t-9.5 4.5q53 -6 63 18q5 9 3 14q0 -1 2 -1t2 -1q12 3 7 17q19 8 26 8q5 -1 11 -6t10 -5q17 -3 21.5 10t-9.5 23q7 -4 7 6q-1 13 -7 19q-3 2 -6.5 2.5t-6.5 0t-7 0.5q-1 0 -8 2q-1 -1 -2 -1h-8q-4 -2 -4 -5v-1q-1 -3 4 -6l5 -1l3 -2q-1 0 -2.5 -2.5t-2.5 -2.5 q0 -3 3 -5q-2 -1 -14 -7.5t-17 -10.5q-1 -1 -4 -2.5t-4 -2.5q-2 -1 -4 2t-4 9t-4 11.5t-4.5 10t-5.5 4.5q-12 0 -18 -17q3 10 -13 17.5t-25 7.5q20 15 -9 30l-1 1q-30 -4 -45 -7q-2 -6 3 -12q-1 -7 6 -9q0 -1 0.5 -1t0.5 -1q0 1 -0.5 1t-0.5 1q3 -1 10.5 -1.5t9.5 -1.5 q3 -1 4.5 -2l7.5 -5t5.5 -6t-2.5 -5q-2 -1 -9 -4t-12.5 -5.5t-6.5 -3.5q-3 -5 0 -16t-2 -15q-5 5 -10 18.5t-8 17.5q8 -9 -30 -6l-8 1q-4 0 -15 -2t-16 -1q-7 0 -29 6q7 17 5 25q5 0 7 2l-6 3q-3 -1 -25 -9q2 -3 8 -9.5t9 -11.5q-22 6 -27 -2q0 -1 -9 0q-25 1 -24 -7 q1 -4 9 -12q0 -9 -1 -9q-27 22 -30 23q-172 -83 -276 -248q1 -2 2.5 -11t3.5 -8.5t11 4.5q9 -9 3 -21q2 2 36 -21q56 -40 22 -53v5.5t1 6.5q-9 -1 -19 5q-3 -6 0.5 -20t11.5 -14q-8 0 -10.5 -17t-2.5 -38.5t-1 -25.5l2 -1q-3 -13 6 -37.5t24 -20.5q-4 -18 5 -21q-1 -4 0 -8 t4.5 -8.5t6 -7l7.5 -7.5l6 -6q28 -11 41 -29q4 -6 10.5 -24.5t15.5 -25.5q-2 -6 10 -21.5t11 -25.5q-1 0 -2.5 -0.5t-2.5 -0.5q3 -8 16.5 -16t16.5 -14q2 -3 2.5 -10.5t3 -12t8.5 -2.5q3 24 -26 68q-16 27 -18 31q-3 5 -5.5 16.5t-4.5 15.5q27 -9 26 -13q-5 -10 26 -52 q2 -3 10 -10t11 -12q3 -4 9.5 -14.5t10.5 -15.5q-1 0 -3 -2l-3 -3q4 -2 9 -5t8 -4.5t7.5 -5t7.5 -7.5q16 -18 20 -33q1 -4 0.5 -15.5t1.5 -16.5q2 -6 6 -11t11.5 -10t11.5 -7t14.5 -6.5t11.5 -5.5q2 -1 18 -11t25 -14q10 -4 16.5 -4.5t16 2.5t15.5 4z" />
<glyph unicode="&#xf0ad;" horiz-adv-x="1664" d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5 t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" />
<glyph unicode="&#xf0ae;" horiz-adv-x="1792" d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19 t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0b0;" horiz-adv-x="1408" d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" />
<glyph unicode="&#xf0b1;" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM1792 512v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 512v-128h-256v128h256zM1792 992v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68 t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf0b2;" d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144 l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z " />
<glyph unicode="&#xf0c0;" horiz-adv-x="1920" d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75 t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5 t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" />
<glyph unicode="&#xf0c1;" horiz-adv-x="1664" d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26 l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15 t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207 q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" />
<glyph unicode="&#xf0c2;" horiz-adv-x="1920" d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z " />
<glyph unicode="&#xf0c3;" horiz-adv-x="1664" d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" />
<glyph unicode="&#xf0c4;" horiz-adv-x="1792" d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84 q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148 q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108 q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6 q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" />
<glyph unicode="&#xf0c5;" horiz-adv-x="1792" d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299 h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" />
<glyph unicode="&#xf0c6;" horiz-adv-x="1408" d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181 l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235 z" />
<glyph unicode="&#xf0c7;" d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5 h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" />
<glyph unicode="&#xf0c8;" d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf0c9;" d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45 t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0ca;" horiz-adv-x="1792" d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
<glyph unicode="&#xf0cb;" horiz-adv-x="1792" d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362 q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5 t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 122t0.5 121v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5 t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
<glyph unicode="&#xf0cc;" horiz-adv-x="1792" d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 97 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6 l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -55 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23 l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" />
<glyph unicode="&#xf0cd;" d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47 q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41 q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472 q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" />
<glyph unicode="&#xf0ce;" horiz-adv-x="1664" d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23 v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192 q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192 q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113 z" />
<glyph unicode="&#xf0d0;" horiz-adv-x="1664" d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276 l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" />
<glyph unicode="&#xf0d1;" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38 t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0d2;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33 q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf0d3;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5 t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
<glyph unicode="&#xf0d4;" d="M678 -57q0 -38 -10 -71h-380q-95 0 -171.5 56.5t-103.5 147.5q24 45 69 77.5t100 49.5t107 24t107 7q32 0 49 -2q6 -4 30.5 -21t33 -23t31 -23t32 -25.5t27.5 -25.5t26.5 -29.5t21 -30.5t17.5 -34.5t9.5 -36t4.5 -40.5zM385 294q-234 -7 -385 -85v433q103 -118 273 -118 q32 0 70 5q-21 -61 -21 -86q0 -67 63 -149zM558 805q0 -100 -43.5 -160.5t-140.5 -60.5q-51 0 -97 26t-78 67.5t-56 93.5t-35.5 104t-11.5 99q0 96 51.5 165t144.5 69q66 0 119 -41t84 -104t47 -130t16 -128zM1536 896v-736q0 -119 -84.5 -203.5t-203.5 -84.5h-468 q39 73 39 157q0 66 -22 122.5t-55.5 93t-72 71t-72 59.5t-55.5 54.5t-22 59.5q0 36 23 68t56 61.5t65.5 64.5t55.5 93t23 131t-26.5 145.5t-75.5 118.5q-6 6 -14 11t-12.5 7.5t-10 9.5t-10.5 17h135l135 64h-437q-138 0 -244.5 -38.5t-182.5 -133.5q0 126 81 213t207 87h960 q119 0 203.5 -84.5t84.5 -203.5v-96h-256v256h-128v-256h-256v-128h256v-256h128v256h256z" />
<glyph unicode="&#xf0d5;" horiz-adv-x="1664" d="M876 71q0 21 -4.5 40.5t-9.5 36t-17.5 34.5t-21 30.5t-26.5 29.5t-27.5 25.5t-32 25.5t-31 23t-33 23t-30.5 21q-17 2 -50 2q-54 0 -106 -7t-108 -25t-98 -46t-69 -75t-27 -107q0 -68 35.5 -121.5t93 -84t120.5 -45.5t127 -15q59 0 112.5 12.5t100.5 39t74.5 73.5 t27.5 110zM756 933q0 60 -16.5 127.5t-47 130.5t-84 104t-119.5 41q-93 0 -144 -69t-51 -165q0 -47 11.5 -99t35.5 -104t56 -93.5t78 -67.5t97 -26q97 0 140.5 60.5t43.5 160.5zM625 1408h437l-135 -79h-135q71 -45 110 -126t39 -169q0 -74 -23 -131.5t-56 -92.5t-66 -64.5 t-56 -61t-23 -67.5q0 -26 16.5 -51t43 -48t58.5 -48t64 -55.5t58.5 -66t43 -85t16.5 -106.5q0 -160 -140 -282q-152 -131 -420 -131q-59 0 -119.5 10t-122 33.5t-108.5 58t-77 89t-30 121.5q0 61 37 135q32 64 96 110.5t145 71t155 36t150 13.5q-64 83 -64 149q0 12 2 23.5 t5 19.5t8 21.5t7 21.5q-40 -5 -70 -5q-149 0 -255.5 98t-106.5 246q0 140 95 250.5t234 141.5q94 20 187 20zM1664 1152v-128h-256v-256h-128v256h-256v128h256v256h128v-256h256z" />
<glyph unicode="&#xf0d6;" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0d7;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0d8;" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
<glyph unicode="&#xf0d9;" horiz-adv-x="640" d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" />
<glyph unicode="&#xf0da;" horiz-adv-x="640" d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" />
<glyph unicode="&#xf0db;" horiz-adv-x="1664" d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf0dc;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
<glyph unicode="&#xf0dd;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0de;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
<glyph unicode="&#xf0e0;" horiz-adv-x="1792" d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123 q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" />
<glyph unicode="&#xf0e1;" horiz-adv-x="1379" d="M1014 961q171 0 268 -85.5t97 -254.5v-586q0 -14 -10.5 -24.5t-24.5 -10.5h-252q-14 0 -24.5 10.5t-10.5 24.5v529q0 71 -26.5 104t-95.5 33q-88 0 -123.5 -51.5t-35.5 -143.5v-471q0 -14 -10.5 -24.5t-25.5 -10.5h-246q-14 0 -24.5 10.5t-10.5 24.5v868q0 14 10.5 24.5 t24.5 10.5h239q13 0 21 -5t10.5 -18.5t3 -18t0.5 -22.5q93 87 246 87zM290 938q14 0 24.5 -10.5t10.5 -24.5v-868q0 -14 -10.5 -24.5t-24.5 -10.5h-246q-14 0 -24.5 10.5t-10.5 24.5v868q0 14 10.5 24.5t24.5 10.5h246zM167 1371q69 0 118 -49t49 -118t-49 -118t-118 -49 t-118 49t-49 118t49 118t118 49z" />
<glyph unicode="&#xf0e2;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-179 0 -336.5 76t-266 213t-147.5 312q-3 14 7 27q9 12 25 12h199q23 0 30 -23q50 -162 185 -261.5t304 -99.5q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5t-163.5 109.5 t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" />
<glyph unicode="&#xf0e3;" horiz-adv-x="1792" d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5 t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14 q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28 q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" />
<glyph unicode="&#xf0e4;" horiz-adv-x="1792" d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5 t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5 t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29 q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
<glyph unicode="&#xf0e5;" horiz-adv-x="1792" d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640 q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5 t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
<glyph unicode="&#xf0e6;" horiz-adv-x="1792" d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257 t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5 t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129 q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" />
<glyph unicode="&#xf0e7;" horiz-adv-x="896" d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" />
<glyph unicode="&#xf0e8;" horiz-adv-x="1792" d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68 z" />
<glyph unicode="&#xf0e9;" horiz-adv-x="1664" d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97 q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69 q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" />
<glyph unicode="&#xf0ea;" horiz-adv-x="1792" d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28 h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" />
<glyph unicode="&#xf0eb;" horiz-adv-x="1024" d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134 q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47 q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5 t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" />
<glyph unicode="&#xf0ec;" horiz-adv-x="1792" d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9 q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
<glyph unicode="&#xf0ed;" horiz-adv-x="1920" d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
<glyph unicode="&#xf0ee;" horiz-adv-x="1920" d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
<glyph unicode="&#xf0f0;" horiz-adv-x="1408" d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56 t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68 t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" />
<glyph unicode="&#xf0f1;" horiz-adv-x="1408" d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48 t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252 t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" />
<glyph unicode="&#xf0f2;" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66 t66 -158z" />
<glyph unicode="&#xf0f3;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1664 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5 q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" />
<glyph unicode="&#xf0f4;" horiz-adv-x="1920" d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45 t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" />
<glyph unicode="&#xf0f5;" horiz-adv-x="1408" d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45 t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0f6;" horiz-adv-x="1280" d="M1024 352v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1024 608v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280z M768 896h299l-299 299v-299zM1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h544q40 0 88 -20t76 -48l408 -408q28 -28 48 -76t20 -88z" />
<glyph unicode="&#xf0f7;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0f8;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5 t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320 v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0f9;" horiz-adv-x="1920" d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152 q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0fa;" horiz-adv-x="1792" d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32 q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" />
<glyph unicode="&#xf0fb;" horiz-adv-x="1920" d="M1632 800q261 -58 287 -93l1 -3q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416 h-64v32h64h160h96q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64z" />
<glyph unicode="&#xf0fc;" horiz-adv-x="1664" d="M640 640v384h-256v-160q0 -45 2 -76t7.5 -56.5t14.5 -40t23 -26.5t33.5 -15.5t45 -7.5t58 -2.5t72.5 0.5zM1664 192v-192h-1152v192l128 192h-97q-211 0 -313 102.5t-102 314.5v287l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" />
<glyph unicode="&#xf0fd;" d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf0fe;" d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf100;" horiz-adv-x="1024" d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" />
<glyph unicode="&#xf101;" horiz-adv-x="1024" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23 l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
<glyph unicode="&#xf102;" horiz-adv-x="1152" d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393 q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
<glyph unicode="&#xf103;" horiz-adv-x="1152" d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
<glyph unicode="&#xf104;" horiz-adv-x="640" d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
<glyph unicode="&#xf105;" horiz-adv-x="640" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
<glyph unicode="&#xf106;" horiz-adv-x="1152" d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
<glyph unicode="&#xf107;" horiz-adv-x="1152" d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
<glyph unicode="&#xf108;" horiz-adv-x="1920" d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19 t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf109;" horiz-adv-x="1920" d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" />
<glyph unicode="&#xf10a;" horiz-adv-x="1152" d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832 q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf10b;" horiz-adv-x="768" d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136 q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
<glyph unicode="&#xf10c;" d="M1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf10d;" horiz-adv-x="1664" d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" />
<glyph unicode="&#xf10e;" horiz-adv-x="1664" d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216 v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" />
<glyph unicode="&#xf110;" horiz-adv-x="1568" d="M496 192q0 -60 -42.5 -102t-101.5 -42q-60 0 -102 42t-42 102t42 102t102 42q59 0 101.5 -42t42.5 -102zM928 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -66 -47 -113t-113 -47t-113 47t-47 113 t47 113t113 47t113 -47t47 -113zM1360 192q0 -46 -33 -79t-79 -33t-79 33t-33 79t33 79t79 33t79 -33t33 -79zM528 1088q0 -73 -51.5 -124.5t-124.5 -51.5t-124.5 51.5t-51.5 124.5t51.5 124.5t124.5 51.5t124.5 -51.5t51.5 -124.5zM992 1280q0 -80 -56 -136t-136 -56 t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1536 640q0 -40 -28 -68t-68 -28t-68 28t-28 68t28 68t68 28t68 -28t28 -68zM1328 1088q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5z" />
<glyph unicode="&#xf111;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf112;" horiz-adv-x="1792" d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19 l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" />
<glyph unicode="&#xf113;" horiz-adv-x="1664" d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320 q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86 t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218 q0 -87 -27 -168q136 -160 136 -398z" />
<glyph unicode="&#xf114;" horiz-adv-x="1664" d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320 q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
<glyph unicode="&#xf115;" horiz-adv-x="1920" d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68 v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z " />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

148
lib/ui/static/js/app.js Normal file
View File

@ -0,0 +1,148 @@
/************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Our main application mdoule. Declare application routes and perform initialization chores.
*
*/
angular.module('ansible', [
'RestServices',
'AuthService',
'Utilities',
'OrganizationFormDefinition',
'UserFormDefinition',
'FormGenerator',
'OrganizationListDefinition',
'UserListDefinition',
'ListGenerator',
'AWToolTip',
'PromptDialog',
'APIDefaults',
'RelatedSearchHelper',
'RelatedPaginateHelper',
'SearchHelper',
'PaginateHelper',
'RefreshHelper',
'AdminListDefinition',
'AWDirectives',
'InventoriesListDefinition',
'InventoryFormDefinition',
'InventoryHelper',
'AWFilters',
'HostFormDefinition',
'HostListDefinition',
'HostHelper',
'GroupFormDefinition',
'GroupListDefinition',
'TeamsListDefinition',
'TeamFormDefinition',
'TeamHelper'
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/inventories', { templateUrl: 'partials/inventories.html',
controller: InventoriesList }).
when('/inventories/add', { templateUrl: 'partials/inventories.html',
controller: InventoriesAdd }).
when('/inventories/:id', { templateUrl: 'partials/inventories.html',
controller: InventoriesEdit }).
when('/inventories/:id/hosts', { templateUrl: 'partials/inventories.html',
controller: HostsList }).
when('/inventories/:id/hosts/add', { templateUrl: 'partials/inventories.html',
controller: HostsAdd }).
when('/inventories/:inventory_id/hosts/:id', { templateUrl: 'partials/inventories.html',
controller: HostsEdit }).
when('/inventories/:id/groups', { templateUrl: 'partials/inventories.html',
controller: GroupsList }).
when('/inventories/:id/groups/add', { templateUrl: 'partials/inventories.html',
controller: GroupsAdd }).
when('/inventories/:inventory_id/groups/:id', { templateUrl: 'partials/inventories.html',
controller: GroupsEdit }).
when('/organizations', { templateUrl: 'partials/organizations.html',
controller: OrganizationsList }).
when('/organizations/add', { templateUrl: 'partials/organizations.html',
controller: OrganizationsAdd }).
when('/organizations/:id', { templateUrl: 'partials/organizations.html',
controller: OrganizationsEdit }).
when('/organizations/:id/admins', { templateUrl: 'partials/organizations.html',
controller: AdminsList }).
when('/organizations/:id/users', { templateUrl: 'partials/users.html',
controller: UsersList }).
when('/organizations/:id/users/add', { templateUrl: 'partials/users.html',
controller: UsersAdd }).
when('/organizations/:organization_id/users/:id', { templateUrl: 'partials/users.html',
controller: UsersEdit }).
when('/teams', { templateUrl: 'partials/teams.html',
controller: TeamsList }).
when('/teams/add', { templateUrl: 'partials/teams.html',
controller: TeamsAdd }).
when('/teams/:id', { templateUrl: 'partials/teams.html',
controller: TeamsEdit }).
when('/users', { templateUrl: 'partials/users.html',
controller: UsersList }).
when('/users/add', { templateUrl: 'partials/users.html',
controller: UsersAdd }).
when('/users/:id', { templateUrl: 'partials/users.html',
controller: UsersEdit }).
when('/login', { templateUrl: 'partials/login-dialog.html', controller: Authenticate }).
when('/logout', { templateUrl: 'partials/login-dialog.html', controller: Authenticate }).
otherwise({redirectTo: '/'});
}])
.run(function($rootScope, $location, Authorization) {
$rootScope.breadcrumbs = new Array();
$rootScope.crumbCache = new Array();
$rootScope.$on("$routeChangeStart", function(event, next, current) {
// Evaluate the token on each navigation request. Redirect to login page when not valid
if (Authorization.isTokenValid() == false) {
if ( next.templateUrl != 'partials/login.html' ) {
$location.path('/login');
}
}
else {
if ($rootScope.current_user == undefined || $rootScope.current_user == null) {
Authorization.restoreUserInfo(); //user must have hit browser refresh
}
}
});
if (! Authorization.isTokenValid() ) {
// When the app first loads, redirect to login page
$location.path('/login');
}
// If browser refresh, activate the correct tab
var base = ($location.path().replace(/^\//,'').split('/')[0]);
if (base == '') {
console.log(base);
base = 'organizations';
$location.path('/organizations');
}
else {
$('.nav-tabs a[href="#' + base + '"]').tab('show');
}
});

View File

@ -0,0 +1,19 @@
/************************************
*
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* config.js
*
* Gobal configuration variables for controlling application behavior.
*
*/
var $AnsibleConfig =
{
session_timeout: 3600, // cookie expiration in seconds. session will expire after this many
// seconds of inactivity.
tooltip_delay: 2000, // Default number of milliseconds to delay displaying/hiding tooltips
debug_mode: true // Enable console logging messages
}

View File

@ -0,0 +1,104 @@
/************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
*
* Admins.js
*
* Controller functions for ading Admins to an Organization.
*
*/
'use strict';
function AdminsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
Alert, AdminList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit,
ReturnToCaller)
{
var list = AdminList;
var defaultUrl = '/api/v1' + '/organizations/' + $routeParams.id + '/users/' ;
var view = GenerateList;
//var paths = $location.path().replace(/^\//,'').split('/');
var mode = 'select';
var scope = view.inject(AdminList, { mode: mode }); // Inject our view
scope.selected = [];
SearchInit({ scope: scope, set: 'admins', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
LoadBreadCrumbs();
scope.finishSelection = function() {
Rest.setUrl('/api/v1' + $location.path() + '/'); // We're assuming the path matches the api path.
// Will this always be true??
scope.queue = [];
scope.$on('callFinished', function() {
// We call the API for each selected user. We need to hang out until all the api
// calls are finished.
if (scope.queue.length == scope.selected.length) {
// All the api calls finished
$('input[type="checkbox"]').prop("checked",false);
scope.selected = [];
var errors = 0;
for (var i=0; i < scope.queue.length; i++) {
if (scope.queue[i].result == 'error') {
errors++;
// there is no way to know which user raised the error. no data comes
// back from the api call.
// $('td.username-column').each(function(index) {
// if ($(this).text() == scope.queue[i].username) {
// $(this).addClass("error");
// }
// });
}
}
if (errors > 0) {
Alert('Error', 'There was an error while adding one or more of the selected users.');
}
else {
ReturnToCaller(1);
}
}
});
if (scope.selected.length > 0 ) {
var user;
for (var i=0; i < scope.selected.length; i++) {
user = null;
for (var j=0; j < scope.admins.length; j++) {
if (scope.admins[j].id == scope.selected[i]) {
user = scope.admins[j];
}
}
if (user !== null) {
Rest.post(user)
.success( function(data, status, headers, config) {
scope.queue.push({ result: 'success', data: data, status: status });
scope.$emit('callFinished');
})
.error( function(data, status, headers, config) {
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
scope.$emit('callFinished');
});
}
}
}
else {
returnToCaller();
}
}
scope.toggle_admin = function(idx) {
if (scope.selected.indexOf(idx) > -1) {
scope.selected.splice(scope.selected.indexOf(idx),1);
}
else {
scope.selected.push(idx);
}
}
}
AdminsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'AdminList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller' ];

View File

@ -0,0 +1,74 @@
/************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
*
* Authentication.js
*
* Controller functions for user authentication.
*
*/
'use strict';
function Authenticate($scope, $rootScope, $location, Authorization, ToggleClass, Alert)
{
// Authorization is injected from AuthService found in services.js
if ($location.path() == '/logout') {
//if logout request, clear AuthToken and user session data
Authorization.logout();
}
$rootScope.userLoggedIn = false; //hide the logout link. if you got here, your logged out.
//gets set back to true by Authorization.setToken().
$scope.sessionExpired = Authorization.didSessionExpire(); //Display session timeout message
$scope.sessionTimeout = ($AnsibleConfig.session_timeout / 60).toFixed(2)
// Display the login dialog
$('#login-modal').modal({ show: true, keyboard: false, backdrop: false });
$scope.reset = function() {
$('#login-form input').each( function(index) { $(this).val(''); });
};
// Call the API to get an auth token
$scope.systemLogin = function(username, password) {
$('.api-error').empty();
Authorization.retrieveToken(username, password)
.success( function(data, status, headers, config) {
Authorization.setToken(data.token);
$scope.reset();
// Get all the profile/access info regarding the logged in user
Authorization.getUser()
.success(function(data, status, headers, config) {
$('#login-modal').modal('hide');
Authorization.setUserInfo(data);
$location.path('/organizations');
})
.error( function(data, status, headers, config) {
Alert('Error', 'Failed to get user data from /api/v1/me. GET status: ' + status);
});
})
.error( function(data, status, headers, config) {
if ( data.non_field_errors && data.non_field_errors.length == 0 ) {
// show field specific errors returned by the API
for (var key in data) {
$scope[key + 'Error'] = data[key][0];
}
}
else {
if ( data.non_field_errors && data.non_field_errors.length > 0 ) {
$rootScope.alertHeader = 'Error!';
$rootScope.alertBody = data.non_field_errors[0];
}
else {
$rootScope.alertHeader = 'Error!';
$rootScope.alertBody = 'The login attempt failed with a status of: ' + status;
}
$scope.reset();
$('#alert-modal').modal({ show: true, keyboard: true, backdrop: 'static' });
}
});
}
}

View File

@ -0,0 +1,227 @@
/************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
*
* Groups.js
*
* Controller functions for Group model.
*
*/
'use strict';
function GroupsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
Alert, GroupList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit,
PaginateInit, ReturnToCaller, ClearScope, ProcessErrors)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var list = GroupList;
var defaultUrl = '/api/v1/inventories/' + $routeParams.id + '/groups/';
var view = GenerateList;
var paths = $location.path().replace(/^\//,'').split('/');
var scope = view.inject(GroupList, { mode: 'edit' }); // Inject our view
scope.selected = [];
SearchInit({ scope: scope, set: 'groups', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
LoadBreadCrumbs();
scope.addGroup = function() {
$location.path($location.path() + '/add');
}
scope.editGroup = function(id) {
$location.path($location.path() + '/' + id);
}
scope.deleteGroup = function(id, name) {
var action = function() {
var url = defaultUrl;
Rest.setUrl(url);
Rest.post({ id: id, disassociate: 1 })
.success( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
scope.search(list.iterator);
})
.error( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
};
Prompt({ hdr: 'Delete',
body: 'Are you sure you want to delete group' + name + '?',
action: action
});
}
}
GroupsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'LookUpInventoryInit'];
function GroupsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, GroupForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller,
ClearScope, LookUpInventoryInit)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
// Inject dynamic view
var defaultUrl = '/api/v1/inventories/';
var form = GroupForm;
var generator = GenerateForm;
var scope = generator.inject(form, {mode: 'add', related: false});
generator.reset();
var master={};
LoadBreadCrumbs();
LookUpInventoryInit({ scope: scope });
// Load inventory lookup value
var url = defaultUrl + $routeParams.id + '/';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
scope['inventory'] = data.id;
master['inventory'] = data.id;
scope['inventory_name'] = data.name;
master['inventory_name'] = data.name;
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to retrieve: ' + url + '. GET status: ' + status });
});
// Save
scope.formSave = function() {
Rest.setUrl(defaultUrl + $routeParams.id + '/groups/');
var data = {}
for (var fld in form.fields) {
data[fld] = scope[fld];
}
Rest.post(data)
.success( function(data, status, headers, config) {
ReturnToCaller(1);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to add new group. Post returned status: ' + status });
});
};
// Cancel
scope.formReset = function() {
// Defaults
generator.reset();
};
}
GroupsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'GroupForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'LookUpInventoryInit' ];
function GroupsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, GroupForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInventoryInit)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var defaultUrl='/api/v1/groups/';
var generator = GenerateForm;
var form = GroupForm;
var scope = generator.inject(form, {mode: 'edit', related: true});
generator.reset();
var master = {};
var id = $routeParams.id;
var relatedSets = {};
LookUpInventoryInit({ scope: scope });
// After the Organization is loaded, retrieve each related set
scope.$on('groupLoaded', function() {
Rest.setUrl(scope['inventory_url']);
Rest.get()
.success( function(data, status, headers, config) {
scope['inventory_name'] = data.name;
master['inventory_name'] = data.name;
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to retrieve: ' + scope.orgnization_url + '. GET status: ' + status });
});
for (var set in relatedSets) {
scope.search(relatedSets[set].iterator);
}
});
// Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl + ':id/');
Rest.get({ params: {id: id} })
.success( function(data, status, headers, config) {
LoadBreadCrumbs();
for (var fld in form.fields) {
if (data[fld]) {
scope[fld] = data[fld];
master[fld] = scope[fld];
}
}
var related = data.related;
for (var set in form.related) {
if (related[set]) {
relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
}
}
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
scope['inventory_url'] = data.related.inventory;
scope.$emit('groupLoaded');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve group: ' + $routeParams.id + '. GET status: ' + status });
});
// Save changes to the parent
scope.formSave = function() {
Rest.setUrl(defaultUrl + id + '/');
var data = {}
for (var fld in form.fields) {
data[fld] = scope[fld];
}
Rest.put(data)
.success( function(data, status, headers, config) {
var base = $location.path().replace(/^\//,'').split('/')[0];
(base == 'inventories') ? ReturnToCaller() : ReturnToCaller(1);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update host: ' + $routeParams.id + '. PUT status: ' + status });
});
};
// Cancel
scope.formReset = function() {
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
}
};
}
HostsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'HostForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'LookUpInventoryInit' ];

View File

@ -0,0 +1,228 @@
/************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
*
* Hosts.js
*
* Controller functions for Host model.
*
*/
'use strict';
function HostsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
Alert, HostList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit,
ReturnToCaller, ClearScope, ProcessErrors)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var list = HostList;
var defaultUrl = '/api/v1/inventories/' + $routeParams.id + '/hosts/';
var view = GenerateList;
var paths = $location.path().replace(/^\//,'').split('/');
var scope = view.inject(HostList, { mode: 'edit' }); // Inject our view
scope.selected = [];
SearchInit({ scope: scope, set: 'hosts', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
LoadBreadCrumbs();
scope.addHost = function() {
$location.path($location.path() + '/add');
}
scope.editHost = function(id) {
$location.path($location.path() + '/' + id);
}
scope.deleteHost = function(id, name) {
var action = function() {
var url = defaultUrl;
Rest.setUrl(url);
Rest.post({ id: id, disassociate: 1 })
.success( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
scope.search(list.iterator);
})
.error( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
};
Prompt({ hdr: 'Delete',
body: 'Are you sure you want to delete host ' + name + '?',
action: action
});
}
}
HostsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors' ];
function HostsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, HostForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller,
ClearScope, LookUpInventoryInit)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
// Inject dynamic view
var defaultUrl = '/api/v1/inventories/';
var form = HostForm;
var generator = GenerateForm;
var scope = generator.inject(form, {mode: 'add', related: false});
generator.reset();
var master = {};
LoadBreadCrumbs();
LookUpInventoryInit({ scope: scope });
// Load inventory lookup value
var url = defaultUrl + $routeParams.id + '/';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
scope['inventory'] = data.id;
master['inventory'] = data.id;
scope['inventory_name'] = data.name;
master['inventory_name'] = data.name;
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to retrieve: ' + url + '. GET status: ' + status });
});
// Save
scope.formSave = function() {
Rest.setUrl(defaultUrl + $routeParams.id + '/hosts/');
var data = {}
for (var fld in form.fields) {
data[fld] = scope[fld];
}
Rest.post(data)
.success( function(data, status, headers, config) {
ReturnToCaller(1);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to add new host. Post returned status: ' + status });
});
};
// Cancel
scope.formReset = function() {
// Defaults
generator.reset();
};
}
HostsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'HostForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'LookUpInventoryInit' ];
function HostsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInventoryInit)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var defaultUrl='/api/v1/hosts/';
var generator = GenerateForm;
var form = UserForm;
var scope = generator.inject(form, {mode: 'edit', related: true});
generator.reset();
var master = {};
var id = $routeParams.id;
var relatedSets = {};
LookUpInventoryInit({ scope: scope });
// After form data loads, load related sets and lookups
scope.$on('hostLoaded', function() {
Rest.setUrl(scope['inventory_url']);
Rest.get()
.success( function(data, status, headers, config) {
scope['inventory_name'] = data.name;
master['inventory_name'] = data.name;
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to retrieve: ' + scope.inventory_url + '. GET status: ' + status });
});
for (var set in relatedSets) {
scope.search(relatedSets[set].iterator);
}
});
// Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl + ':id/');
Rest.get({ params: {id: id} })
.success( function(data, status, headers, config) {
LoadBreadCrumbs();
for (var fld in form.fields) {
if (data[fld]) {
scope[fld] = data[fld];
master[fld] = scope[fld];
}
}
var related = data.related;
for (var set in form.related) {
if (related[set]) {
relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
}
}
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
scope['inventory_url'] = data.related.inventory;
scope.$emit('hostLoaded');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve host: ' + $routeParams.id + '. GET status: ' + status });
});
// Save changes to the parent
scope.formSave = function() {
Rest.setUrl(defaultUrl + id + '/');
var data = {}
for (var fld in form.fields) {
data[fld] = scope[fld];
}
Rest.put(data)
.success( function(data, status, headers, config) {
var base = $location.path().replace(/^\//,'').split('/')[0];
(base == 'inventories') ? ReturnToCaller() : ReturnToCaller(1);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update host: ' + $routeParams.id + '. PUT status: ' + status });
});
};
// Cancel
scope.formReset = function() {
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
}
};
}
HostsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'HostForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'LookUpInventoryInit' ];

View File

@ -0,0 +1,332 @@
/************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
*
* Inventories.js
*
* Controller functions for the Inventory model.
*
*/
'use strict';
function InventoriesList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, InventoryList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
ClearScope, ProcessErrors, SetListeners)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var list = InventoryList;
var defaultUrl = '/api/v1/inventories/';
var view = GenerateList;
var paths = $location.path().replace(/^\//,'').split('/');
var mode = (paths[0] == 'inventories') ? 'edit' : 'select'; // if base path 'users', we're here to add/edit users
var scope = view.inject(InventoryList, { mode: mode }); // Inject our view
scope.selected = [];
SetListeners({ scope: scope, set: 'inventories', iterator: list.iterator });
SearchInit({ scope: scope, set: 'inventories', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
LoadBreadCrumbs();
scope.addInventory = function() {
$location.path($location.path() + '/add');
}
scope.editInventory = function(id) {
$location.path($location.path() + '/' + id);
}
scope.deleteInventory = function(id, name) {
var action = function() {
var url = defaultUrl + id + '/';
Rest.setUrl(url);
Rest.delete()
.success( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
scope.search(list.iterator);
})
.error( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
};
Prompt({ hdr: 'Delete',
body: 'Are you sure you want to delete ' + name + '?',
action: action
});
}
scope.lookupOrganization = function(organization_id) {
Rest.setUrl('/api/v1/organization/' + organization_id + '/');
Rest.get()
.success( function(data, status, headers, config) {
return data.name;
});
}
scope.finishSelection = function() {
Rest.setUrl('/api/v1' + $location.path() + '/'); // We're assuming the path matches the api path.
// Will this always be true??
scope.queue = [];
scope.$on('callFinished', function() {
// We call the API for each selected user. We need to hang out until all the api
// calls are finished.
if (scope.queue.length == scope.selected.length) {
// All the api calls finished
$('input[type="checkbox"]').prop("checked",false);
scope.selected = [];
var errors = 0;
for (var i=0; i < scope.queue.length; i++) {
if (scope.queue[i].result == 'error') {
errors++;
// there is no way to know which user raised the error. no data comes
// back from the api call.
// $('td.username-column').each(function(index) {
// if ($(this).text() == scope.queue[i].username) {
// $(this).addClass("error");
// }
// });
}
}
if (errors > 0) {
Alert('Error', 'There was an error while adding one or more of the selected inventories.');
}
else {
ReturnToCaller(1);
}
}
});
if (scope.selected.length > 0 ) {
var inventory = null;
for (var i=0; i < scope.selected.length; i++) {
for (var j=0; j < scope.inventories.length; j++) {
if (scope.inventories[j].id == scope.selected[i]) {
inventory = scope.inventories[j];
}
}
if (inventory !== null) {
Rest.post(inventory)
.success( function(data, status, headers, config) {
scope.queue.push({ result: 'success', data: data, status: status });
scope.$emit('callFinished');
})
.error( function(data, status, headers, config) {
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
scope.$emit('callFinished');
});
}
}
}
else {
ReturnToCaller();
}
}
scope.toggle_inventory = function(idx) {
if (scope.selected.indexOf(idx) > -1) {
scope.selected.splice(scope.selected.indexOf(idx),1);
}
else {
scope.selected.push(idx);
}
}
}
InventoriesList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'InventoryList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
'SetListeners' ];
function InventoriesAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
GenerateList, OrganizationList, SearchInit, PaginateInit, LookUpOrganizationInit)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
// Inject dynamic view
var defaultUrl = '/api/v1/inventories/';
var form = InventoryForm;
var generator = GenerateForm;
var scope = generator.inject(form, {mode: 'add', related: false});
generator.reset();
LoadBreadCrumbs();
LookUpOrganizationInit({ scope: scope });
// Save
scope.formSave = function() {
Rest.setUrl(defaultUrl);
var data = {}
for (var fld in form.fields) {
data[fld] = scope[fld];
}
Rest.post(data)
.success( function(data, status, headers, config) {
ReturnToCaller();
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to add new inventory. Post returned status: ' + status });
});
};
// Reset
scope.formReset = function() {
// Defaults
generator.reset();
};
}
InventoriesAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList',
'OrganizationList', 'SearchInit', 'PaginateInit', 'LookUpOrganizationInit' ];
function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpOrganizationInit, Prompt,
TreeInit)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var defaultUrl='/api/v1/inventories/';
var generator = GenerateForm;
var form = InventoryForm;
var scope = generator.inject(form, {mode: 'edit', related: true});
generator.reset();
var base = $location.path().replace(/^\//,'').split('/')[0];
var master = {};
var id = $routeParams.id;
var relatedSets = {};
LookUpOrganizationInit({ scope: scope });
// After inventory is loaded, retrieve each related set and any lookups
scope.$on('inventoryLoaded', function() {
Rest.setUrl(scope['organization_url']);
Rest.get()
.success( function(data, status, headers, config) {
scope['organization_name'] = data.name;
master['organization_name'] = data.name;
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to retrieve: ' + scope.orgnization_url + '. GET status: ' + status });
});
for (var set in relatedSets) {
scope.search(relatedSets[set].iterator);
}
});
// Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl + ':id/');
Rest.get({ params: {id: id} })
.success( function(data, status, headers, config) {
LoadBreadCrumbs({ path: '/inventories/' + id, title: data.name });
for (var fld in form.fields) {
if (data[fld]) {
scope[fld] = data[fld];
master[fld] = scope[fld];
}
}
var related = data.related;
for (var set in form.related) {
if (related[set]) {
relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
}
}
// Load the tree view
TreeInit(related.groups);
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
scope['organization_url'] = data.related.organization;
scope.$emit('inventoryLoaded');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve inventory: ' + $routeParams.id + '. GET status: ' + status });
});
// Save changes to the parent
scope.formSave = function() {
Rest.setUrl(defaultUrl + $routeParams.id);
var data = {}
for (var fld in form.fields) {
data[fld] = scope[fld];
}
Rest.put(data)
.success( function(data, status, headers, config) {
var base = $location.path().replace(/^\//,'').split('/')[0];
(base == 'inventories') ? ReturnToCaller() : ReturnToCaller(1);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update inventory: ' + $routeParams.id + '. PUT status: ' + status });
});
};
// Cancel
scope.formReset = function() {
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
}
};
// Related set: Add button
scope.add = function(set) {
$rootScope.flashMessage = null;
$location.path('/' + base + '/' + $routeParams.id + '/' + set + '/add');
};
// Related set: Edit button
scope.edit = function(set, id, name) {
$rootScope.flashMessage = null;
$location.path('/' + base + '/' + $routeParams.id + '/' + set + '/' + id);
};
// Related set: Delete button
scope.delete = function(set, itm_id, name, title) {
$rootScope.flashMessage = null;
var action = function() {
var url = defaultUrl + id + '/' + set + '/';
Rest.setUrl(url);
Rest.post({ id: itm_id, disassociate: 1 })
.success( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
scope.search(form.related[set].iterator);
})
.error( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
});
};
Prompt({ hdr: 'Delete',
body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?',
action: action
});
}
}
InventoriesEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'LookUpOrganizationInit', 'Prompt',
'TreeInit' ];

View File

@ -0,0 +1,234 @@
/************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
*
* Organizations.js
*
* Controller functions for Organization model.
*
*/
'use strict';
function OrganizationsList ($scope, $rootScope, $location, $log, Rest, Alert, LoadBreadCrumbs, Prompt, GetAPIDefaults,
GenerateList, OrganizationList, SearchInit, PaginateInit, ClearScope, ProcessErrors)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var list = OrganizationList;
var generate = GenerateList;
var paths = $location.path().replace(/^\//,'').split('/');
var mode = (paths[0] == 'organizations') ? 'edit' : 'select'; // if base path 'users', we're here to add/edit users
var scope = generate.inject(OrganizationList, { mode: mode }); // Inject our view
var defaultUrl = '/api/v1/organizations/';
var iterator = list.iterator;
$rootScope.flashMessage = null;
LoadBreadCrumbs();
// Initialize search and paginate pieces and load data
SearchInit({ scope: scope, set: list.name, list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
//getData();
scope.addOrganization = function() {
$location.path($location.path() + '/add');
}
scope.editOrganization = function(id) {
$location.path($location.path() + '/' + id);
}
scope.deleteOrganization = function(id, name) {
var action = function() {
var url = defaultUrl + id + '/';
Rest.setUrl(url);
Rest.delete()
.success( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
scope.search(list.iterator);
})
.error( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
};
Prompt({ hdr: 'Delete',
body: 'Are you sure you want to delete ' + name + '?',
action: action
});
}
}
OrganizationsList.$inject=[ '$scope', '$rootScope', '$location', '$log', 'Rest', 'Alert', 'LoadBreadCrumbs', 'Prompt', 'GetAPIDefaults',
'GenerateList', 'OrganizationList', 'SearchInit', 'PaginateInit', 'ClearScope', 'ProcessErrors'];
function OrganizationsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
// Inject dynamic view
var form = GenerateForm;
var scope = form.inject(OrganizationForm, {mode: 'add', related: false});
form.reset();
LoadBreadCrumbs();
// Save
scope.formSave = function() {
Rest.setUrl('/api/v1/organizations/');
Rest.post({ name: $scope.name,
description: $scope.description })
.success( function(data, status, headers, config) {
$rootScope.flashMessage = "Your changes were successfully saved!";
$location.path('/organizations/' + data.id + '/');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, OrganizationForm,
{ hdr: 'Error!', msg: 'Failed to add new location. Post returned status: ' + status });
});
};
// Cancel
scope.formReset = function() {
$rootScope.flashMessage = null;
form.reset();
};
}
OrganizationsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'OrganizationForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope' ];
function OrganizationsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, GetAPIDefaults,
RelatedSearchInit, RelatedPaginateInit, Prompt, ClearScope)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
// Inject dynamic view
var form = OrganizationForm;
var generator = GenerateForm;
var scope = GenerateForm.inject(form, {mode: 'edit', related: true});
generator.reset();
var defaultUrl = '/api/v1/organizations/';
var base = $location.path().replace(/^\//,'').split('/')[0];
var master = {};
var id = $routeParams.id;
var relatedSets = {};
// After the Organization is loaded, retrieve each related set
scope.$on('organizationLoaded', function() {
for (var set in relatedSets) {
scope.search(relatedSets[set].iterator);
}
});
// Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl + ':id/');
Rest.get({ params: {id: id} })
.success( function(data, status, headers, config) {
LoadBreadCrumbs({ path: '/organizations/' + id, title: data.name });
for (var fld in form.fields) {
if (data[fld]) {
scope[fld] = data[fld];
master[fld] = data[fld];
}
}
var related = data.related;
for (var set in form.related) {
if (related[set]) {
relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
}
}
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
scope.$emit('organizationLoaded');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve organization: ' + $routeParams.id + '. GET status: ' + status });
});
// Save changes to the parent
scope.formSave = function() {
var params = {};
for (var fld in form.fields) {
params[fld] = scope[fld];
}
Rest.setUrl('/api/v1/organizations/' + $routeParams.id + '/');
Rest.put(params)
.success( function(data, status, headers, config) {
master = params;
$rootScope.flashMessage = "Your changes were successfully saved!";
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, OrganizationForm,
{ hdr: 'Error!', msg: 'Failed to update organization: ' + id + '. PUT status: ' + status });
});
};
// Reset the form
scope.formReset = function() {
$rootScope.flashMessage = null;
form.reset();
for (var fld in master) {
scope[fld] = master[fld];
}
};
// Related set: Add button
scope.add = function(set) {
$rootScope.flashMessage = null;
$location.path('/' + base + '/' + $routeParams.id + '/' + set);
};
// Related set: Edit button
scope.edit = function(set, id, name) {
$rootScope.flashMessage = null;
$location.path('/' + base + '/' + $routeParams.id + '/' + set + '/' + id);
};
// Related set: Delete button
scope.delete = function(set, itm_id, name, title) {
$rootScope.flashMessage = null;
var action = function() {
var url = defaultUrl + id + '/' + set + '/';
Rest.setUrl(url);
Rest.post({ id: itm_id, disassociate: 1 })
.success( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
scope.search(form.related[set].iterator);
})
.error( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
});
};
Prompt({ hdr: 'Delete',
body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?',
action: action
});
}
}
OrganizationsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'OrganizationForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'GetAPIDefaults',
'RelatedSearchInit', 'RelatedPaginateInit', 'Prompt', 'ClearScope'];

View File

@ -0,0 +1,328 @@
/************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
*
* Teams.js
*
* Controller functions for the Team model.
*
*/
'use strict';
function TeamsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, TeamList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
ClearScope, ProcessErrors, SetTeamListeners)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var list = TeamList;
var defaultUrl = '/api/v1/teams/';
var view = GenerateList;
var paths = $location.path().replace(/^\//,'').split('/');
var mode = (paths[0] == 'teams') ? 'edit' : 'select'; // if base path 'teams', we're here to add/edit teams
var scope = view.inject(list, { mode: mode }); // Inject our view
scope.selected = [];
SetTeamListeners({ scope: scope, set: 'teams', iterator: list.iterator });
SearchInit({ scope: scope, set: 'teams', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
LoadBreadCrumbs();
scope.addTeam = function() {
$location.path($location.path() + '/add');
}
scope.editTeam = function(id) {
$location.path($location.path() + '/' + id);
}
scope.deleteTeam = function(id, name) {
var action = function() {
var url = defaultUrl + id + '/';
Rest.setUrl(url);
Rest.delete()
.success( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
scope.search(list.iterator);
})
.error( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
};
Prompt({ hdr: 'Delete',
body: 'Are you sure you want to delete ' + name + '?',
action: action
});
}
scope.lookupOrganization = function(organization_id) {
Rest.setUrl('/api/v1/organization/' + organization_id + '/');
Rest.get()
.success( function(data, status, headers, config) {
return data.name;
});
}
scope.finishSelection = function() {
Rest.setUrl('/api/v1' + $location.path() + '/'); // We're assuming the path matches the api path.
// Will this always be true??
scope.queue = [];
scope.$on('callFinished', function() {
// We call the API for each selected user. We need to hang out until all the api
// calls are finished.
if (scope.queue.length == scope.selected.length) {
// All the api calls finished
$('input[type="checkbox"]').prop("checked",false);
scope.selected = [];
var errors = 0;
for (var i=0; i < scope.queue.length; i++) {
if (scope.queue[i].result == 'error') {
errors++;
// there is no way to know which user raised the error. no data comes
// back from the api call.
// $('td.username-column').each(function(index) {
// if ($(this).text() == scope.queue[i].username) {
// $(this).addClass("error");
// }
// });
}
}
if (errors > 0) {
Alert('Error', 'There was an error while adding one or more of the selected teams.');
}
else {
ReturnToCaller(1);
}
}
});
if (scope.selected.length > 0 ) {
var team = null;
for (var i=0; i < scope.selected.length; i++) {
for (var j=0; j < scope.teams.length; j++) {
if (scope.teams[j].id == scope.selected[i]) {
team = scope.teams[j];
}
}
if (team !== null) {
Rest.post(team)
.success( function(data, status, headers, config) {
scope.queue.push({ result: 'success', data: data, status: status });
scope.$emit('callFinished');
})
.error( function(data, status, headers, config) {
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
scope.$emit('callFinished');
});
}
}
}
else {
ReturnToCaller();
}
}
scope.toggle_team = function(idx) {
if (scope.selected.indexOf(idx) > -1) {
scope.selected.splice(scope.selected.indexOf(idx),1);
}
else {
scope.selected.push(idx);
}
}
}
TeamsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'TeamList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
'SetTeamListeners' ];
function TeamsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
GenerateList, OrganizationList, SearchInit, PaginateInit, TeamLookUpOrganizationInit)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
// Inject dynamic view
var defaultUrl = '/api/v1/teams/';
var form = TeamForm;
var generator = GenerateForm;
var scope = generator.inject(form, {mode: 'add', related: false});
generator.reset();
LoadBreadCrumbs();
TeamLookUpOrganizationInit({ scope: scope });
// Save
scope.formSave = function() {
Rest.setUrl(defaultUrl);
var data = {}
for (var fld in form.fields) {
data[fld] = scope[fld];
}
Rest.post(data)
.success( function(data, status, headers, config) {
ReturnToCaller();
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to add new inventory. Post returned status: ' + status });
});
};
// Reset
scope.formReset = function() {
// Defaults
generator.reset();
};
}
TeamsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'TeamForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList',
'OrganizationList', 'SearchInit', 'PaginateInit', 'TeamLookUpOrganizationInit' ];
function TeamsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
RelatedPaginateInit, ReturnToCaller, ClearScope, TeamLookUpOrganizationInit, Prompt)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var defaultUrl='/api/v1/teams/';
var generator = GenerateForm;
var form = InventoryForm;
var scope = generator.inject(form, {mode: 'edit', related: true});
generator.reset();
var base = $location.path().replace(/^\//,'').split('/')[0];
var master = {};
var id = $routeParams.id;
var relatedSets = {};
TeamLookUpOrganizationInit({ scope: scope });
// After inventory is loaded, retrieve each related set and any lookups
scope.$on('teamLoaded', function() {
Rest.setUrl(scope['organization_url']);
Rest.get()
.success( function(data, status, headers, config) {
scope['organization_name'] = data.name;
master['organization_name'] = data.name;
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to retrieve: ' + scope.orgnization_url + '. GET status: ' + status });
});
for (var set in relatedSets) {
scope.search(relatedSets[set].iterator);
}
});
// Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl + ':id/');
Rest.get({ params: {id: id} })
.success( function(data, status, headers, config) {
LoadBreadCrumbs({ path: '/teams/' + id, title: data.name });
for (var fld in form.fields) {
if (data[fld]) {
scope[fld] = data[fld];
master[fld] = scope[fld];
}
}
var related = data.related;
for (var set in form.related) {
if (related[set]) {
relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
}
}
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
scope['organization_url'] = data.related.organization;
scope.$emit('teamLoaded');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve team: ' + $routeParams.id + '. GET status: ' + status });
});
// Save changes to the parent
scope.formSave = function() {
Rest.setUrl(defaultUrl + $routeParams.id);
var data = {}
for (var fld in form.fields) {
data[fld] = scope[fld];
}
Rest.put(data)
.success( function(data, status, headers, config) {
var base = $location.path().replace(/^\//,'').split('/')[0];
(base == 'inventories') ? ReturnToCaller() : ReturnToCaller(1);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update team: ' + $routeParams.id + '. PUT status: ' + status });
});
};
// Cancel
scope.formReset = function() {
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
}
};
// Related set: Add button
scope.add = function(set) {
$rootScope.flashMessage = null;
$location.path('/' + base + '/' + $routeParams.id + '/' + set + '/add');
};
// Related set: Edit button
scope.edit = function(set, id, name) {
$rootScope.flashMessage = null;
$location.path('/' + base + '/' + $routeParams.id + '/' + set + '/' + id);
};
// Related set: Delete button
scope.delete = function(set, itm_id, name, title) {
$rootScope.flashMessage = null;
var action = function() {
var url = defaultUrl + id + '/' + set + '/';
Rest.setUrl(url);
Rest.post({ id: itm_id, disassociate: 1 })
.success( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
scope.search(form.related[set].iterator);
})
.error( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
});
};
Prompt({ hdr: 'Delete',
body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?',
action: action
});
}
}
TeamsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'TeamForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'TeamLookUpOrganizationInit', 'Prompt'
];

View File

@ -0,0 +1,284 @@
/************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
*
* Users.js
*
* Controller functions for User model.
*
*/
'use strict';
function UsersList ($scope, $rootScope, $location, $log, $routeParams, Rest,
Alert, UserList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit,
ReturnToCaller, ClearScope, ProcessErrors)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var list = UserList;
var defaultUrl = '/api/v1/users/';
var view = GenerateList;
var paths = $location.path().replace(/^\//,'').split('/');
var mode = (paths[0] == 'users') ? 'edit' : 'select'; // if base path 'users', we're here to add/edit users
var scope = view.inject(UserList, { mode: mode }); // Inject our view
scope.selected = [];
SearchInit({ scope: scope, set: 'users', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
LoadBreadCrumbs();
scope.addUser = function() {
$location.path($location.path() + '/add');
}
scope.editUser = function(id) {
$location.path($location.path() + '/' + id);
}
scope.deleteUser = function(id, name) {
var action = function() {
var url = defaultUrl + id + '/';
Rest.setUrl(url);
Rest.delete()
.success( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
scope.search(list.iterator);
})
.error( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
};
Prompt({ hdr: 'Delete',
body: 'Are you sure you want to delete ' + name + '?',
action: action
});
}
scope.finishSelection = function() {
Rest.setUrl('/api/v1' + $location.path() + '/'); // We're assuming the path matches the api path.
// Will this always be true??
scope.queue = [];
scope.$on('callFinished', function() {
// We call the API for each selected user. We need to hang out until all the api
// calls are finished.
if (scope.queue.length == scope.selected.length) {
// All the api calls finished
$('input[type="checkbox"]').prop("checked",false);
scope.selected = [];
var errors = 0;
for (var i=0; i < scope.queue.length; i++) {
if (scope.queue[i].result == 'error') {
errors++;
// there is no way to know which user raised the error. no data comes
// back from the api call.
// $('td.username-column').each(function(index) {
// if ($(this).text() == scope.queue[i].username) {
// $(this).addClass("error");
// }
// });
}
}
if (errors > 0) {
Alert('Error', 'There was an error while adding one or more of the selected users.');
}
else {
ReturnToCaller(1);
}
}
});
if (scope.selected.length > 0 ) {
var user;
for (var i=0; i < scope.selected.length; i++) {
user = null;
for (var j=0; j < scope.users.length; j++) {
if (scope.users[j].id == scope.selected[i]) {
user = scope.users[j];
}
}
if (user !== null) {
Rest.post(user)
.success( function(data, status, headers, config) {
scope.queue.push({ result: 'success', data: data, status: status });
scope.$emit('callFinished');
})
.error( function(data, status, headers, config) {
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
scope.$emit('callFinished');
});
}
}
}
else {
ReturnToCaller();
}
}
scope.toggle_user = function(idx) {
if (scope.selected.indexOf(idx) > -1) {
scope.selected.splice(scope.selected.indexOf(idx),1);
}
else {
scope.selected.push(idx);
}
}
}
UsersList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'UserList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors' ];
function UsersAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
// Inject dynamic view
var defaultUrl = '/api/v1/organizations/';
var form = UserForm;
var generator = GenerateForm;
var scope = generator.inject(form, {mode: 'add', related: false});
generator.reset();
LoadBreadCrumbs();
// Save
scope.formSave = function() {
Rest.setUrl(defaultUrl + $routeParams.id + '/users/');
var data = {}
for (var fld in form.fields) {
data[fld] = scope[fld];
}
Rest.post(data)
.success( function(data, status, headers, config) {
ReturnToCaller(1);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to add new user. Post returned status: ' + status });
});
};
// Cancel
scope.formReset = function() {
// Defaults
generator.reset();
};
// Password change
scope.clearPWConfirm = function() {
// If password value changes, make sure password_confirm must be re-entered
scope.password_confirm = '';
scope[form.name]['password_confirm'].$setValidity('awpassmatch', false);
}
}
UsersAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'UserForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope'];
function UsersEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
RelatedPaginateInit, ReturnToCaller, ClearScope)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var defaultUrl='/api/v1/users/';
var generator = GenerateForm;
var form = UserForm;
var scope = generator.inject(form, {mode: 'edit', related: true});
generator.reset();
var master = {};
var id = $routeParams.id;
var relatedSets = {};
// After the Organization is loaded, retrieve each related set
scope.$on('userLoaded', function() {
for (var set in relatedSets) {
scope.search(relatedSets[set].iterator);
}
});
// Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl + ':id/');
Rest.get({ params: {id: id} })
.success( function(data, status, headers, config) {
LoadBreadCrumbs({ path: '/users/' + id, title: data.username });
for (var fld in form.fields) {
if (data[fld]) {
if (fld == 'is_superuser') {
scope[fld] = (data[fld] == 'true' || data[fld] == true) ? 'true' : 'false';
}
else {
scope[fld] = data[fld];
}
master[fld] = scope[fld];
}
}
var related = data.related;
for (var set in form.related) {
if (related[set]) {
relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
}
}
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
scope.$emit('userLoaded');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve user: ' + $routeParams.id + '. GET status: ' + status });
});
// Save changes to the parent
scope.formSave = function() {
Rest.setUrl(defaultUrl + $routeParams.id);
var data = {}
for (var fld in form.fields) {
data[fld] = scope[fld];
}
Rest.put(data)
.success( function(data, status, headers, config) {
var base = $location.path().replace(/^\//,'').split('/')[0];
(base == 'users') ? ReturnToCaller() : ReturnToCaller(1);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update users: ' + $routeParams.id + '. PUT status: ' + status });
});
};
// Cancel
scope.formReset = function() {
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
}
};
// Password change
scope.clearPWConfirm = function() {
// If password value changes, make sure password_confirm must be re-entered
scope.password_confirm = '';
scope[form.name]['password_confirm'].$setValidity('awpassmatch', false);
}
}
UsersEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'UserForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope'];

View File

@ -0,0 +1,64 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Groups.js
* Form definition for Group model
*
*
*/
angular.module('GroupFormDefinition', [])
.value(
'GroupForm', {
addTitle: 'Create Group', //Legend in add mode
editTitle: '{{ name }}', //Legend in edit mode
name: 'group', //Form name attribute
well: true, //Wrap the form with TB well
fields: {
name: {
label: 'Name',
type: 'text',
addRequired: true,
editRequired: true
},
description: {
label: 'Description',
type: 'text',
addRequired: true,
editRequired: true
},
inventory: {
label: 'Inventory',
type: 'lookup',
sourceModel: 'inventory',
sourceField: 'name',
addRequired: true,
editRequired: true,
ngClick: 'lookUpInventory()'
}
},
buttons: { //for now always generates <button> tags
save: {
label: 'Save',
icon: 'icon-ok',
class: 'btn btn-success',
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
},
reset: {
ngClick: 'formReset()',
label: 'Reset',
icon: 'icon-remove',
class: 'btn',
ngDisabled: true //Disabled when $pristine
}
},
related: { //related colletions (and maybe items?)
}
}); //UserForm

View File

@ -0,0 +1,64 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Hosts.js
* Form definition for Host model
*
*
*/
angular.module('HostFormDefinition', [])
.value(
'HostForm', {
addTitle: 'Create Host', //Legend in add mode
editTitle: '{{ name }}', //Legend in edit mode
name: 'host', //Form name attribute
well: true, //Wrap the form with TB well
fields: {
name: {
label: 'Name',
type: 'text',
addRequired: true,
editRequired: true
},
description: {
label: 'Description',
type: 'text',
addRequired: true,
editRequired: true
},
inventory: {
label: 'Inventory',
type: 'lookup',
sourceModel: 'inventory',
sourceField: 'name',
addRequired: true,
editRequired: true,
ngClick: 'lookUpInventory()'
}
},
buttons: { //for now always generates <button> tags
save: {
label: 'Save',
icon: 'icon-ok',
class: 'btn btn-success',
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
},
reset: {
ngClick: 'formReset()',
label: 'Reset',
icon: 'icon-remove',
class: 'btn',
ngDisabled: true //Disabled when $pristine
}
},
related: { //related colletions (and maybe items?)
}
}); //UserForm

View File

@ -0,0 +1,108 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Inventories.js
* Form definition for User model
*
*
*/
angular.module('InventoryFormDefinition', [])
.value(
'InventoryForm', {
addTitle: 'Create Inventory', //Legend in add mode
editTitle: '{{ name }}', //Legend in edit mode
name: 'inventory',
well: true,
fields: {
name: {
label: 'Name',
type: 'text',
addRequired: true,
editRequired: true,
capitalize: true
},
description: {
label: 'Description',
type: 'text',
addRequired: true,
editRequired: true
},
organization: {
label: 'Organization',
type: 'lookup',
sourceModel: 'organization',
sourceField: 'name',
addRequired: true,
editRequired: true,
ngClick: 'lookUpOrganization()'
}
},
buttons: { //for now always generates <button> tags
save: {
label: 'Save',
icon: 'icon-ok',
class: 'btn btn-success',
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
},
reset: {
ngClick: 'formReset()',
label: 'Reset',
icon: 'icon-remove',
class: 'btn',
ngDisabled: true //Disabled when $pristine
}
},
related: { //related colletions (and maybe items?)
hosts: {
type: 'collection',
title: 'Hosts',
iterator: 'host',
open: false,
actions: {
add: {
ngClick: "add('hosts')",
icon: 'icon-plus',
awToolTip: 'Create a new host'
},
},
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
}
},
fieldActions: {
edit: {
ngClick: "edit('hosts', \{\{ host.id \}\}, '\{\{ host.name \}\}')",
icon: 'icon-edit',
awToolTip: 'Edit host'
},
delete: {
ngClick: "delete('hosts', \{\{ host.id \}\}, '\{\{ host.name \}\}', 'hosts')",
icon: 'icon-remove',
class: 'btn-danger',
awToolTip: 'Create a new host'
}
}
},
groups: {
type: 'tree',
title: 'Groups',
open: true
}
}
}); //InventoryForm

View File

@ -0,0 +1,128 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Organization.js
* Form definition for Organization model
*
*
*/
angular.module('OrganizationFormDefinition', [])
.value(
'OrganizationForm', {
addTitle: 'Create Organization', //Title in add mode
editTitle: '{{ name }}', //Title in edit mode
name: 'organization', //entity or model name in singular form
well: true, //Wrap the form with TB well/
fields: {
name: {
label: 'Name',
type: 'text',
addRequired: true,
editRequired: true,
capitalize: true
},
description: {
label: 'Description',
type: 'text',
addRequired: true,
editRequired: true
}
},
buttons: { //for now always generates <button> tags
save: {
label: 'Save',
icon: 'icon-ok',
class: 'btn btn-success',
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
},
reset: {
ngClick: 'formReset()',
label: 'Reset',
icon: 'icon-remove',
class: 'btn',
ngDisabled: true //Disabled when $pristine
}
},
related: { //related colletions (and maybe items?)
users: {
type: 'collection',
title: 'Users',
iterator: 'user',
open: false,
actions: {
add: {
ngClick: "add('users')",
icon: 'icon-plus'
},
},
fields: {
username: {
key: true,
label: 'Username'
},
first_name: {
label: 'First Name'
},
last_name: {
label: 'Last Name'
}
},
fieldActions: {
edit: {
ngClick: "edit('users', \{\{ user.id \}\}, '\{\{ user.username \}\}')",
icon: 'icon-edit'
},
delete: {
ngClick: "delete('users', \{\{ user.id \}\}, '\{\{ user.username \}\}', 'users')",
icon: 'icon-remove',
class: 'btn-danger'
}
}
},
admins: { // Assumes a plural name (e.g. things)
type: 'collection',
title: 'Administrators',
iterator: 'admin', // Singular form of name (e.g. thing)
open: false, // Open accordion on load?
actions: { // Actions displayed top right of list
add: {
ngClick: "add('admins')",
icon: 'icon-plus'
}
},
fields: {
username: {
key: true,
label: 'Username'
},
first_name: {
label: 'First Name'
},
last_name: {
label: 'Last Name'
}
},
fieldActions: { // Actions available on each row
delete: {
ngClick: "delete('admins', \{\{ admin.id \}\}, '\{\{ admin.username \}\}', 'administrators')",
icon: 'icon-remove',
class: 'btn-danger'
}
}
}
}
}); //OrganizationForm

View File

@ -0,0 +1,65 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Teams.js
* Form definition for Team model
*
*
*/
angular.module('TeamFormDefinition', [])
.value(
'TeamForm', {
addTitle: 'Create Team', //Legend in add mode
editTitle: '{{ name }}', //Legend in edit mode
name: 'team',
well: true,
fields: {
name: {
label: 'Name',
type: 'text',
addRequired: true,
editRequired: true,
capitalize: true
},
description: {
label: 'Description',
type: 'text',
addRequired: true,
editRequired: true
},
organization: {
label: 'Organization',
type: 'lookup',
sourceModel: 'organization',
sourceField: 'name',
addRequired: true,
editRequired: true,
ngClick: 'lookUpOrganization()'
}
},
buttons: { //for now always generates <button> tags
save: {
label: 'Save',
icon: 'icon-ok',
class: 'btn btn-success',
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
},
reset: {
ngClick: 'formReset()',
label: 'Reset',
icon: 'icon-remove',
class: 'btn',
ngDisabled: true //Disabled when $pristine
}
},
related: { //related colletions (and maybe items?)
}
}); //InventoryForm

View File

@ -0,0 +1,175 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Users.js
* Form definition for User model
*
*
*/
angular.module('UserFormDefinition', [])
.value(
'UserForm', {
addTitle: 'Create User', //Legend in add mode
editTitle: '{{ username }}', //Legend in edit mode
name: 'user', //Form name attribute
well: true, //Wrap the form with TB well
fields: {
username: {
label: 'Username',
type: 'text',
addRequired: true,
editRequired: true
},
first_name: {
label: 'First Name',
type: 'text',
addRequired: true,
editRequired: true,
capitalize: true
},
last_name: {
label: 'Last Name',
type: 'text',
addRequired: true,
editRequired: true,
capitalize: true
},
email: {
label: 'Email',
type: 'email',
addRequired: true,
editRequired: true
},
password: {
label: 'Password',
type: 'password',
addRequired: true,
editRequired: false,
ngChange: 'clearPWConfirm()'
},
password_confirm: {
label: 'Confirm Password',
type: 'password',
addRequired: false,
editRequired: false,
awPassMatch: true
},
is_superuser: {
label: 'Superuser?',
type: 'checkbox',
trueValue: 'true',
falseValue: 'false',
default: 'false',
ngShow: "current_user['is_superuser'] == true"
}
},
buttons: { //for now always generates <button> tags
save: {
label: 'Save',
icon: 'icon-ok',
class: 'btn btn-success',
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
},
reset: {
ngClick: 'formReset()',
label: 'Reset',
icon: 'icon-remove',
class: 'btn',
ngDisabled: true //Disabled when $pristine
}
},
related: { //related colletions (and maybe items?)
admin_of_organizations: { // Assumes a plural name (e.g. things)
type: 'collection',
title: 'Admin of Organizations',
iterator: 'adminof', // Singular form of name (e.g. thing)
open: false, // Open accordion on load?
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
},
}
},
organizations: {
type: 'collection',
title: 'Organizations',
iterator: 'organization',
open: false,
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
}
}
},
teams: {
type: 'collection',
title: 'Teams',
iterator: 'team',
open: false,
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
}
}
},
projects: {
type: 'collection',
title: 'Projects',
iterator: 'project',
open: false,
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
}
}
},
credentials: {
type: 'collection',
title: 'Credentials',
iterator: 'credential',
open: false,
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
}
}
},
}
}); //UserForm

View File

@ -0,0 +1,89 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* APIDefaults
*
*
*/
angular.module('APIDefaults', ['RestServices', 'Utilities'])
.factory('GetAPIDefaults', ['Alert', 'Rest', '$rootScope', function(Alert, Rest, $rootScope) {
return function(key) {
//Reload a related collection on pagination or search change
var answer;
var result = {};
var cnt=0;
function lookup(key) {
var result = {};
for (id in $rootScope.apiDefaults) {
if (id == key || id.iterator == key) {
result[id] = defaults[id];
break;
}
}
return result;
}
function wait() {
var answer;
if ( result == {} && cnt < 5) {
cnt++;
setTimeout(1000, wait());
}
else {
if (result.status == 'success') {
return lookup(key);
}
}
}
if ($rootScope.apiDefaults == null || $rootScope.apiDefaults == undefined) {
var result = {};
var url = '/api/v1';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
defaults = data;
for (var id in defaults) {
switch (id) {
case 'organizations':
dafaults[id].iterator = 'organization';
break;
case 'jobs':
defaults[id].iterator = 'job';
break;
case 'users':
defaults[id].iterator = 'user';
break;
case 'teams':
defaults[id].iterator = 'team';
break;
case 'hosts':
defaults[id].iterator = 'host';
break;
case 'groups':
defaults[id].iterator = 'group';
break;
case 'projects':
defaults[id].iterator = 'project';
break;
}
}
$rootScope.apiDefaults = defaults;
result = {status: 'success'};
})
.error( function(data, status, headers, config) {
result = {status: 'error', msg: 'Call to ' + url + ' failed. GET returned status: ' + status};
});
return wait();
}
else {
return lookup(key);
}
}
}]);

View File

@ -0,0 +1,58 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Helper
* Routines shared amongst the hosts controllers
*/
angular.module('HostHelper', [ 'RestServices', 'Utilities', 'OrganizationListDefinition',
'SearchHelper', 'PaginateHelper', 'ListGenerator' ])
.factory('LookUpInventoryInit', ['Alert', 'Rest', 'InventoryList', 'GenerateList', 'SearchInit', 'PaginateInit',
function(Alert, Rest, InventoryList, GenerateList, SearchInit, PaginateInit) {
return function(params) {
var scope = params.scope;
// Show pop-up to select organization
scope.lookUpInventory = function() {
var list = InventoryList;
var listGenerator = GenerateList;
var listScope = listGenerator.inject(list, { mode: 'lookup', hdr: 'Select Inventory' });
var defaultUrl = '/api/v1/inventories';
listScope.selectAction = function() {
var found = false;
for (var i=0; i < listScope[list.name].length; i++) {
if (listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] == "success") {
found = true;
scope['inventory'] = listScope[list.name][i].id;
scope['inventory_name'] = listScope[list.name][i].name;
scope['host_form'].$setDirty();
listGenerator.hide();
}
}
if (found == false) {
Alert('No Selection', 'Click on a row to select an Inventory before clicking the Select button.');
}
}
listScope.toggle_inventory = function(id) {
// when user clicks a row, remove 'success' class from all rows except clicked-on row
if (listScope[list.name]) {
for (var i=0; i < listScope[list.name].length; i++) {
listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] = "";
}
}
if (id != null && id != undefined) {
listScope[list.iterator + "_" + id + "_class"] = "success";
}
}
SearchInit({ scope: listScope, set: list.name, list: list, url: defaultUrl });
PaginateInit({ scope: listScope, list: list, url: defaultUrl, mode: 'lookup' });
scope.search(list.iterator);
listScope.toggle_inventory(scope.inventory);
}
}
}]);

View File

@ -0,0 +1,129 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* InventoryHelper
* Routines shared amongst the inventory controllers
*/
angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationListDefinition',
'SearchHelper', 'PaginateHelper', 'ListGenerator' ])
.factory('SetListeners', ['Alert', 'Rest', function(Alert, Rest) {
return function(params) {
var scope = params.scope;
var set = params.set;
var iterator = params.iterator;
// Listeners to perform lookups after main inventory list loads
scope.$on('resultFound', function(e, results, lookup_results) {
if ( lookup_results.length == results.length ) {
key = 'organization';
property = 'organization_name';
for (var i=0; i < results.length; i++) {
for (var j=0; j < lookup_results.length; j++) {
if (results[i][key] == lookup_results[j].id) {
results[i][property] = lookup_results[j].value;
}
}
}
scope[iterator + 'SearchSpin'] = false;
scope[set] = results;
}
});
scope.$on('refreshFinished', function(e, results) {
// Loop through the result set (sent to us by the search helper) and
// lookup the id and name of each organization. After each lookup
// completes, call resultFound.
var lookup_results = [];
for (var i = 0; i < results.length; i++) {
Rest.setUrl('/api/v1/organizations/' + results[i].organization + '/');
Rest.get()
.success( function( data, status, headers, config) {
lookup_results.push({ id: data.id, value: data.name });
scope.$emit('resultFound', results, lookup_results);
})
.error( function( data, status, headers, config) {
lookup_results.push({ id: 'error' });
scope.$emit('resultFound', results, lookup_results);
});
}
});
}
}])
.factory('LookUpOrganizationInit', ['Alert', 'Rest', 'OrganizationList', 'GenerateList', 'SearchInit', 'PaginateInit',
function(Alert, Rest, OrganizationList, GenerateList, SearchInit, PaginateInit) {
return function(params) {
var scope = params.scope;
// Show pop-up to select organization
scope.lookUpOrganization = function() {
var list = OrganizationList;
var listGenerator = GenerateList;
var listScope = listGenerator.inject(list, { mode: 'lookup', hdr: 'Select Organization' });
var defaultUrl = '/api/v1/organizations';
listScope.selectAction = function() {
var found = false;
for (var i=0; i < listScope[list.name].length; i++) {
if (listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] == "success") {
found = true;
scope['organization'] = listScope[list.name][i].id;
scope['organization_name'] = listScope[list.name][i].name;
scope['inventory_form'].$setDirty();
listGenerator.hide();
}
}
if (found == false) {
Alert('No Selection', 'Click on a row to select an Organization before clicking the Select button.');
}
}
listScope.toggle_organization = function(id) {
// when user clicks a row, remove 'success' class from all rows except clicked-on row
if (listScope[list.name]) {
for (var i=0; i < listScope[list.name].length; i++) {
listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] = "";
}
}
if (id != null && id != undefined) {
listScope[list.iterator + "_" + id + "_class"] = "success";
}
}
SearchInit({ scope: listScope, set: list.name, list: list, url: defaultUrl });
PaginateInit({ scope: listScope, list: list, url: defaultUrl, mode: 'lookup' });
scope.search(list.iterator);
listScope.toggle_organization(scope.organization);
}
}
}])
.factory('TreeInit', ['Alert', 'Rest', function(Alert, Rest) {
return function(groups) {
Rest.setUrl(groups);
Rest.get()
.success( function(data, status, headers, config) {
var treeData = [];
for (var i=0; i < data.results.length; i++) {
treeData.push({
data: data.results[i].name,
state: 'closed',
attr: { id: data.results[i] }
});
}
$('#tree-view').jstree({ "json_data": { data: treeData },
plugins: ['themes', 'json_data', 'ui'] });
})
.error( function(data, status, headers, config) {
Alert('Error', 'Failed to laod tree data. Url: ' + groups + ' GET status: ' + status);
});
}
}]);

View File

@ -0,0 +1,51 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* PaginateHelper
*
* All the parts for controlling the search widget on
* related collections.
*
* PaginateInit({
* scope: <scope>,
* list: <form object used by FormGenerator>
* url: <
* });
*
*/
angular.module('PaginateHelper', ['RefreshHelper'])
.factory('PaginateInit', [ 'Refresh', function(Refresh) {
return function(params) {
var scope = params.scope;
var list = params.list;
var defaultUrl = params.url;
var mode = (params.mode) ? params.mode : null;
scope[list.iterator + 'Page'] = 0;
if (mode == 'lookup') {
scope[list.iterator + 'PageSize'] = 5;
}
else {
scope[list.iterator + 'PageSize'] = 20;
}
scope.nextSet = function(set, iterator) {
scope[iterator + 'Page']++;
Refresh({ scope: scope, set: set, iterator: iterator, url: scope[iterator + 'NextUrl'] });
};
scope.prevSet = function(set, iterator) {
scope[iterator + 'Page']--;
Refresh({ scope: scope, set: set, iterator: iterator, url: scope[iterator + 'PrevUrl'] });
};
scope.changePageSize = function(set, iterator) {
// Called when a new page size is selected
scope[iterator + 'Page'] = 0;
Refresh({ scope: scope, set: set, iterator: iterator, url: defaultUrl });
}
}
}]);

View File

@ -0,0 +1,43 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* RefreshRelatedHelper
*
* Used to refresh a related set whenever pagination or filter options change.
*
* RefreshRelated({
* scope: <current scope>,
* set: <model>,
* iterator: <model name in singular form (i.e. organization),
* url: <the api url to call>
* });
*
*/
angular.module('RefreshRelatedHelper', ['RestServices', 'Utilities'])
.factory('RefreshRelated', ['Alert', 'Rest', function(Alert, Rest) {
return function(params) {
var scope = params.scope;
var set = params.set;
var iterator = params.iterator;
var url = params.url;
url.replace(/page_size\=\d+/,''); //stop repeatedly appending page_size
Rest.setUrl(url);
Rest.get({ params: { page_size: scope[iterator + 'PageSize'] }})
.success( function(data, status, headers, config) {
scope[set] = data['results'];
scope[iterator + 'NextUrl'] = data.next;
scope[iterator + 'PrevUrl'] = data.previous;
scope[iterator + 'Count'] = data.count;
scope[iterator + 'PageCount'] = Math.ceil((data.count / scope[iterator + 'PageSize']));
scope[iterator + 'SearchSpin'] = false;
})
.error ( function(data, status, headers, config) {
scope[iterator + 'SearchSpin'] = true;
Alert('Error!', 'Failed to retrieve related set: ' + set + '. GET returned status: ' + status);
});
}
}]);

View File

@ -0,0 +1,53 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* RefreshHelper
*
* Used to refresh a related set whenever pagination or filter options change.
*
* RefreshRelated({
* scope: <current scope>,
* set: <model>,
* iterator: <model name in singular form (i.e. organization),
* url: <the api url to call>
* });
*
*/
angular.module('RefreshHelper', ['RestServices', 'Utilities'])
.factory('Refresh', ['Alert', 'Rest', function(Alert, Rest) {
return function(params) {
var scope = params.scope;
var set = params.set;
var iterator = params.iterator;
var url = params.url;
url.replace(/page_size\=\d+/,''); //stop repeatedly appending page_size
url += scope[iterator + 'SearchParams'];
Rest.setUrl(url);
Rest.get({ params: { page_size: scope[iterator + 'PageSize'] }})
.success( function(data, status, headers, config) {
scope[iterator + 'NextUrl'] = data.next;
scope[iterator + 'PrevUrl'] = data.previous;
scope[iterator + 'Count'] = data.count;
scope[iterator + 'PageCount'] = Math.ceil((data.count / scope[iterator + 'PageSize']));
if (set == 'inventories') {
lookup_results = [];
scope.$emit('refreshFinished', data['results']);
}
else if (set == 'teams') {
lookup_results = [];
scope.$emit('TeamRefreshFinished', data['results']);
}
else {
scope[iterator + 'SearchSpin'] = false;
scope[set] = data['results'];
}
})
.error ( function(data, status, headers, config) {
scope[iterator + 'SearchSpin'] = true;
Alert('Error!', 'Failed to retrieve ' + set + '. GET returned status: ' + status);
});
}
}]);

View File

@ -0,0 +1,52 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* RelatedPaginateHelper
*
* All the parts for controlling the search widget on
* related collections.
*
* RelatedPaginateInit({
* scope: <scope>,
* relatedSets: <array of related collections {model_name, url, iterator}>,
* form: <form object used by FormGenerator>
* });
*
*/
angular.module('RelatedPaginateHelper', ['RefreshRelatedHelper'])
.factory('RelatedPaginateInit', [ 'RefreshRelated', function(RefreshRelated) {
return function(params) {
var scope = params.scope;
var relatedSets = params.relatedSets;
for (var key in relatedSets){
scope[relatedSets[key].iterator + 'Page'] = 0;
scope[relatedSets[key].iterator + 'PageSize'] = 20;
}
scope.nextSet = function(set, iterator) {
scope[iterator + 'Page']++;
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: scope[iterator + 'NextUrl'] });
};
scope.prevSet = function(set, iterator) {
scope[iterator + 'Page']--;
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: scope[iterator + 'PrevUrl'] });
};
scope.changePageSize = function(set, iterator) {
// Called when a new page size is selected
var defaultUrl;
scope[iterator + 'Page'] = 0;
for (var key in relatedSets) {
if (key == set) {
defaultUrl = relatedSets[key].url;
break;
}
}
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: defaultUrl });
}
}
}]);

View File

@ -0,0 +1,80 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* RelatedSearchHelper
*
* All the parts for controlling the search widget on
* related collections.
*
* SearchInit({
* scope: <scope>,
* relatedSets: <array of related collections {model_name, url, iterator}>,
* form: <form object used by FormGenerator>
* });
*
*
*/
angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelatedHelper'])
.factory('RelatedSearchInit', ['Alert', 'Rest', 'RefreshRelated', function(Alert, Rest, RefreshRelated) {
return function(params) {
var scope = params.scope;
var relatedSets = params.relatedSets;
var form = params.form;
// Set default values
for (var set in form.related) {
for (var fld in form.related[set].fields) {
if (form.related[set].fields[fld].key) {
scope[form.related[set].iterator + 'SearchField'] = fld
scope[form.related[set].iterator + 'SearchFieldLabel'] = form.related[set].fields[fld].label;
break;
}
}
scope[form.related[set].iterator + 'SearchType'] = 'contains';
scope[form.related[set].iterator + 'SearchTypeLabel'] = 'Contains';
}
// Functions to handle search widget changes
scope.setSearchField = function(model, fld, label) {
scope[model + 'SearchFieldLabel'] = label;
scope[model + 'SearchField'] = fld;
scope.search(model);
}
scope.setSearchType = function(model, type, label) {
scope[model + 'SearchTypeLabel'] = label;
scope[model + 'SearchType'] = type;
scope.search(model);
}
scope.search = function(model) {
scope[model + 'SearchSpin'] = true;
var set, url, iterator, default_order;
for (var key in relatedSets) {
if (relatedSets[key].iterator == model) {
set = key;
iterator = relatedSets[key].iterator;
url = relatedSets[key].url;
for (var fld in form.related[key].fields) {
if (form.related[key].fields[fld].key) {
default_order = fld;
}
}
break;
}
}
if (scope[model + 'SearchValue'] != '' && scope[model + 'SearchValue'] != undefined) {
url += '?' + scope[model + 'SearchField'] +
'__' + scope[model + 'SearchType'] + '=' + escape(scope[model + 'SearchValue']);
url += (default_order) ? '&order_by=' + escape(default_order) : '';
}
else {
url += (default_order) ? '?order_by=' + escape(default_order) : '';
}
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: url });
}
}
}]);

View File

@ -0,0 +1,84 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* SearchHelper
*
* All the parts for controlling the search widget on
* related collections.
*
* SearchInit({
* scope: <scope>,
* set: <model name (i.e. organizations),
* name was given in ng-repeat>
* url: <default api url used to load data>
* list: <list object used by ListGenerator>
* });
*
*/
angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
.factory('SearchInit', ['Alert', 'Rest', 'Refresh', function(Alert, Rest, Refresh) {
return function(params) {
var scope = params.scope;
var set = params.set;
var defaultUrl = params.url;
var list = params.list;
var iterator = list.iterator;
var default_order;
// Set default values
for (fld in list.fields) {
if (list.fields[fld].key) {
default_order = fld;
scope[iterator + 'SearchField'] = fld
scope[iterator + 'SearchFieldLabel'] = list.fields[fld].label;
break;
}
}
scope[iterator + 'SearchType'] = 'icontains';
scope[iterator + 'SearchTypeLabel'] = 'Contains';
scope[iterator + 'SearchParams'] = '';
scope[iterator + 'SearchValue'] = '';
// Functions to handle search widget changes
scope.setSearchField = function(iterator, fld, label) {
scope[iterator + 'SearchFieldLabel'] = label;
scope[iterator + 'SearchField'] = fld;
scope.search(iterator);
}
scope.setSearchType = function(iterator, type, label) {
scope[iterator + 'SearchTypeLabel'] = label;
scope[iterator + 'SearchType'] = type;
scope.search(iterator);
}
scope.search = function(iterator) {
//
// need to be able to search by related set. Ex: /api/v1/inventories/?organization__name__icontains=
//
scope[iterator + 'SearchSpin'] = true;
var url = defaultUrl;
if (scope[iterator + 'SearchValue'] != '' && scope[iterator + 'SearchValue'] != undefined) {
if (list.fields[scope[iterator + 'SearchField']].sourceModel) {
// handle fields whose source is a related model e.g. inventories.organization
scope[iterator + 'SearchParams'] = '?' + list.fields[scope[iterator + 'SearchField']].sourceModel + '__' +
list.fields[scope[iterator + 'SearchField']].sourceField + '__' +
scope[iterator + 'SearchType'] + '=' + escape(scope[iterator + 'SearchValue']);
scope[iterator + 'SearchParams'] += (default_order) ? '&order_by=' + escape(default_order) : '';
}
else {
scope[iterator + 'SearchParams'] = '?' + scope[iterator + 'SearchField'] + '__' +
scope[iterator + 'SearchType'] + '=' + escape(scope[iterator + 'SearchValue']);
scope[iterator + 'SearchParams'] += (default_order) ? '&order_by=' + escape(default_order) : '';
}
}
else {
scope[iterator + 'SearchParams'] = '';
scope[iterator + 'SearchParams'] += (default_order) ? '?order_by=' + escape(default_order) : '';
}
Refresh({ scope: scope, set: set, iterator: iterator, url: url });
}
}
}]);

View File

@ -0,0 +1,109 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* TeamHelper
* Routines shared amongst the team controllers
*/
angular.module('TeamHelper', [ 'RestServices', 'Utilities', 'OrganizationListDefinition',
'SearchHelper', 'PaginateHelper', 'ListGenerator' ])
.factory('SetTeamListeners', ['Alert', 'Rest', function(Alert, Rest) {
return function(params) {
var scope = params.scope;
var set = params.set;
var iterator = params.iterator;
// Listeners to perform lookups after main inventory list loads
scope.$on('TeamResultFound', function(e, results, lookup_results) {
if ( lookup_results.length == results.length ) {
key = 'organization';
property = 'organization_name';
for (var i=0; i < results.length; i++) {
for (var j=0; j < lookup_results.length; j++) {
if (results[i][key] == lookup_results[j].id) {
results[i][property] = lookup_results[j].value;
}
}
}
scope[iterator + 'SearchSpin'] = false;
scope[set] = results;
}
});
scope.$on('TeamRefreshFinished', function(e, results) {
// Loop through the result set (sent to us by the search helper) and
// lookup the id and name of each organization. After each lookup
// completes, call resultFound.
var lookup_results = [];
for (var i = 0; i < results.length; i++) {
Rest.setUrl('/api/v1/organizations/' + results[i].organization + '/');
Rest.get()
.success( function( data, status, headers, config) {
console.log('here!');
console.log(data);
lookup_results.push({ id: data.id, value: data.name });
scope.$emit('TeamResultFound', results, lookup_results);
})
.error( function( data, status, headers, config) {
lookup_results.push({ id: 'error' });
scope.$emit('TeamResultFound', results, lookup_results);
});
}
});
}
}])
.factory('TeamLookUpOrganizationInit', ['Alert', 'Rest', 'OrganizationList', 'GenerateList', 'SearchInit', 'PaginateInit',
function(Alert, Rest, OrganizationList, GenerateList, SearchInit, PaginateInit) {
return function(params) {
var scope = params.scope;
// Show pop-up to select organization
scope.lookUpOrganization = function() {
var list = OrganizationList;
var listGenerator = GenerateList;
var listScope = listGenerator.inject(list, { mode: 'lookup', hdr: 'Select Organization' });
var defaultUrl = '/api/v1/organizations';
listScope.selectAction = function() {
var found = false;
for (var i=0; i < listScope[list.name].length; i++) {
if (listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] == "success") {
found = true;
scope['organization'] = listScope[list.name][i].id;
scope['organization_name'] = listScope[list.name][i].name;
scope['team_form'].$setDirty();
listGenerator.hide();
}
}
if (found == false) {
Alert('No Selection', 'Click on a row to select an Organization before clicking the Select button.');
}
}
listScope.toggle_organization = function(id) {
// when user clicks a row, remove 'success' class from all rows except clicked-on row
if (listScope[list.name]) {
for (var i=0; i < listScope[list.name].length; i++) {
listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] = "";
}
}
if (id != null && id != undefined) {
listScope[list.iterator + "_" + id + "_class"] = "success";
}
}
SearchInit({ scope: listScope, set: list.name, list: list, url: defaultUrl });
PaginateInit({ scope: listScope, list: list, url: defaultUrl, mode: 'lookup' });
scope.search(list.iterator);
listScope.toggle_organization(scope.organization);
}
}
}]);

View File

@ -0,0 +1,37 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Admins.js
* List view object for Admins data model.
*
*
*/
angular.module('AdminListDefinition', [])
.value(
'AdminList', {
name: 'admins',
iterator: 'admin',
selectTitle: 'Add Administrators',
editTitle: 'Admins',
selectInstructions: 'Click the Select checkbox next to each user to be added. Click the Finished button when done.',
fields: {
username: {
key: true,
label: 'Username'
},
first_name: {
label: 'First Name'
},
last_name: {
label: 'Last Name'
}
},
actions: {
},
fieldActions: {
}
});

View File

@ -0,0 +1,52 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Groups.js
* List view object for Group data model.
*
*
*/
angular.module('GroupListDefinition', [])
.value(
'GroupList', {
name: 'groups',
iterator: 'group',
selectTitle: 'Add Group',
editTitle: 'Groups',
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
}
},
actions: {
add: {
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addGroup()',
class: 'btn btn-mini btn-success',
awToolTip: 'Create a new group'
}
},
fieldActions: {
edit: {
ngClick: "editGroup(\{\{ group.id \}\})",
icon: 'icon-edit',
awToolTip: 'Edit group'
},
delete: {
ngClick: "deleteGroup(\{\{ group.id \}\},'\{\{ group.name \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
awToolTip: 'Delete group'
}
}
});

View File

@ -0,0 +1,52 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Hosts.js
* List view object for Users data model.
*
*
*/
angular.module('HostListDefinition', [])
.value(
'HostList', {
name: 'hosts',
iterator: 'host',
selectTitle: 'Add Host',
editTitle: 'Hosts',
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
}
},
actions: {
add: {
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addHost()',
class: 'btn btn-mini btn-success',
awToolTip: 'Create a new host'
}
},
fieldActions: {
edit: {
ngClick: "editHost(\{\{ host.id \}\})",
icon: 'icon-edit',
awToolTip: 'Edit host'
},
delete: {
ngClick: "deleteHost(\{\{ host.id \}\},'\{\{ host.name \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
awToolTip: 'Delete host'
}
}
});

View File

@ -0,0 +1,59 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Inventories.js
* List view object for Inventories data model.
*
*
*/
angular.module('InventoriesListDefinition', [])
.value(
'InventoryList', {
name: 'inventories',
iterator: 'inventory',
selectTitle: 'Add Inventories',
editTitle: 'Inventories',
selectInstructions: 'Check the Select checkbox next to each inventory to be added, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new inventory.',
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Descriptions'
},
organization: {
label: 'Organization',
ngBind: 'inventory.organization_name',
sourceModel: 'organization',
sourceField: 'name'
}
},
actions: {
add: {
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addInventory()',
class: 'btn btn-mini btn-success',
awToolTip: 'Create a new row'
}
},
fieldActions: {
edit: {
ngClick: "editInventory(\{\{ inventory.id \}\})",
icon: 'icon-edit',
awToolTip: 'Edit'
},
delete: {
ngClick: "deleteInventory(\{\{ inventory.id \}\},'\{\{ inventory.name \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
awToolTip: 'Delete'
}
}
});

View File

@ -0,0 +1,52 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Organizations.js
* List view object for Organizations data model.
*
*
*/
angular.module('OrganizationListDefinition', [])
.value(
'OrganizationList', {
name: 'organizations',
iterator: 'organization',
selectTitle: 'Add Organizations',
editTitle: 'Organizations',
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
}
},
actions: {
add: {
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addOrganization()',
class: 'btn btn-mini btn-success',
awToolTip: 'Create a new row'
}
},
fieldActions: {
edit: {
ngClick: "editOrganization(\{\{ organization.id \}\})",
icon: 'icon-edit',
awToolTip: 'Edit'
},
delete: {
ngClick: "deleteOrganization(\{\{ organization.id \}\},'\{\{ organization.name \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
awToolTip: 'Delete'
}
}
});

View File

@ -0,0 +1,59 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Teams.js
* List view object for Team data model.
*
*
*/
angular.module('TeamsListDefinition', [])
.value(
'TeamList', {
name: 'teams',
iterator: 'team',
selectTitle: 'Add Team',
editTitle: 'Teams',
selectInstructions: 'Check the Select checkbox next to each team to be added, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new team.',
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Descriptions'
},
organization: {
label: 'Organization',
ngBind: 'team.organization_name',
sourceModel: 'organization',
sourceField: 'name'
}
},
actions: {
add: {
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addTeam()',
class: 'btn btn-mini btn-success',
awToolTip: 'Create a new team'
}
},
fieldActions: {
edit: {
ngClick: "editTeam(\{\{ team.id \}\})",
icon: 'icon-edit',
awToolTip: 'Edit team'
},
delete: {
ngClick: "deleteTeam(\{\{ team.id \}\},'\{\{ team.name \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
awToolTip: 'Delete team'
}
}
});

View File

@ -0,0 +1,57 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Users.js
* List view object for Users data model.
*
*
*/
angular.module('UserListDefinition', [])
.value(
'UserList', {
name: 'users',
iterator: 'user',
selectTitle: 'Add Users',
editTitle: 'Users',
selectInstructions: 'Check the Select checkbox next to each user to be added, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new user.',
editInstructions: 'Create new users from the Organizations tab. Each Organizaton has an associated list of Users.',
fields: {
username: {
key: true,
label: 'Username'
},
first_name: {
label: 'First Name'
},
last_name: {
label: 'Last Name'
}
},
actions: {
add: {
icon: 'icon-plus',
mode: 'select', // One of: edit, select, all
ngClick: 'addUser()',
class: 'btn btn-mini btn-success',
awToolTip: 'Create a new row'
}
},
fieldActions: {
edit: {
ngClick: "editUser(\{\{ user.id \}\})",
icon: 'icon-edit',
awToolTip: 'Edit'
},
delete: {
ngClick: "deleteUser(\{\{ user.id \}\},'\{\{ user.username \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
awToolTip: 'Delete'
}
}
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
/*
AngularJS v1.1.4
(c) 2010-2012 Google, Inc. http://angularjs.org
License: MIT
*/
(function(v,t,H){'use strict';function F(d){return d.replace(/\&/g,"&amp;").replace(/\</g,"&lt;").replace(/\>/g,"&gt;").replace(/"/g,"&quot;")}function A(d,f){var a=t.element("<pre>"+f+"</pre>");d.html("");d.append(a.contents());return d}var s={},w={value:{}},K={"angular.js":"http://code.angularjs.org/"+t.version.full+"/angular.min.js","angular-resource.js":"http://code.angularjs.org/"+t.version.full+"/angular-resource.min.js","angular-sanitize.js":"http://code.angularjs.org/"+t.version.full+"/angular-sanitize.min.js",
"angular-cookies.js":"http://code.angularjs.org/"+t.version.full+"/angular-cookies.min.js"};s.jsFiddle=function(d,f,a){return{terminal:!0,link:function(o,c,l){function b(a,c){return'<input type="hidden" name="'+a+'" value="'+f(c)+'">'}var r={html:"",css:"",js:""};t.forEach(l.jsFiddle.split(" "),function(a,c){var b=a.split(".")[1];r[b]+=b=="html"?c==0?"<div ng-app"+(l.module?'="'+l.module+'"':"")+">\n"+d(a,2):"\n\n\n <\!-- CACHE FILE: "+a+' --\>\n <script type="text/ng-template" id="'+a+'">\n'+d(a,
4)+" <\/script>\n":d(a)+"\n"});r.html+="</div>\n";A(c,'<form class="jsfiddle" method="post" action="http://jsfiddle.net/api/post/library/pure/" target="_blank">'+b("title","AngularJS Example: ")+b("css",'</style> <\!-- Ugly Hack due to jsFiddle issue: http://goo.gl/BUfGZ --\> \n<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">\n'+a.angular+(l.resource?a.resource:"")+"<style>\n"+r.css)+b("html",r.html)+b("js",r.js)+'<button class="btn btn-primary"><i class="icon-white icon-pencil"></i> Edit Me</button></form>')}}};
s.code=function(){return{restrict:"E",terminal:!0}};s.prettyprint=["reindentCode",function(d){return{restrict:"C",terminal:!0,compile:function(f){f.html(v.prettyPrintOne(d(f.html()),H,!0))}}}];s.ngSetText=["getEmbeddedTemplate",function(d){return{restrict:"CA",priority:10,compile:function(f,a){A(f,F(d(a.ngSetText)))}}}];s.ngHtmlWrap=["reindentCode","templateMerge",function(d,f){return{compile:function(a,d){var c={head:"",module:"",body:a.text()};t.forEach((d.ngHtmlWrap||"").split(" "),function(a){if(a){var a=
K[a]||a,b=a.split(/\./).pop();b=="css"?c.head+='<link rel="stylesheet" href="'+a+'" type="text/css">\n':b=="js"?c.head+='<script src="'+a+'"><\/script>\n':c.module='="'+a+'"'}});A(a,F(f("<!doctype html>\n<html ng-app{{module}}>\n <head>\n{{head:4}} </head>\n <body>\n{{body:4}} </body>\n</html>",c)))}}}];s.ngSetHtml=["getEmbeddedTemplate",function(d){return{restrict:"CA",priority:10,compile:function(f,a){A(f,d(a.ngSetHtml))}}}];s.ngEvalJavascript=["getEmbeddedTemplate",function(d){return{compile:function(f,
a){var o=d(a.ngEvalJavascript);try{v.execScript?v.execScript(o||'""'):v.eval(o)}catch(c){v.console?v.console.log(o,"\n",c):v.alert(c)}}}}];s.ngEmbedApp=["$templateCache","$browser","$rootScope","$location","$sniffer",function(d,f,a,o,c){return{terminal:!0,link:function(l,b,r){l=[];l.push(["$provide",function(b){b.value("$templateCache",d);b.value("$anchorScroll",t.noop);b.value("$browser",f);b.value("$sniffer",c);b.provider("$location",function(){this.$get=["$rootScope",function(b){a.$on("$locationChangeSuccess",
function(a,c,d){b.$broadcast("$locationChangeSuccess",c,d)});return o}];this.html5Mode=t.noop});b.decorator("$timeout",["$rootScope","$delegate",function(a,b){return t.extend(function(c,d){return d&&d>50?setTimeout(function(){a.$apply(c)},d):b.apply(this,arguments)},b)}]);b.decorator("$rootScope",["$delegate",function(b){a.$watch(function(){b.$digest()});return b}])}]);r.ngEmbedApp&&l.push(r.ngEmbedApp);b.bind("click",function(a){a.target.attributes.getNamedItem("ng-click")&&a.preventDefault()});
t.bootstrap(b,l)}}}];w.reindentCode=function(){return function(d,f){if(!d)return d;for(var a=d.split(/\r?\n/),o=" ".substr(0,f||0),c;a.length&&a[0].match(/^\s*$/);)a.shift();for(;a.length&&a[a.length-1].match(/^\s*$/);)a.pop();var l=999;for(c=0;c<a.length;c++){var b=a[0],r=b.match(/^\s*/)[0];if(r!==b&&r.length<l)l=r.length}for(c=0;c<a.length;c++)a[c]=o+a[c].substring(l);a.push("");return a.join("\n")}};w.templateMerge=["reindentCode",function(d){return function(f,a){return f.replace(/\{\{(\w+)(?:\:(\d+))?\}\}/g,
function(f,c,l){f=a[c];l&&(f=d(f,l));return f==H?"":f})}}];w.getEmbeddedTemplate=["reindentCode",function(d){return function(f){f=document.getElementById(f);return!f?null:d(t.element(f).html(),0)}}];t.module("bootstrapPrettify",[]).directive(s).factory(w);v.PR_SHOULD_USE_CONTINUATION=!0;(function(){function d(a){function b(i){var a=i.charCodeAt(0);if(a!==92)return a;var k=i.charAt(1);return(a=O[k])?a:"0"<=k&&k<="7"?parseInt(i.substring(1),8):k==="u"||k==="x"?parseInt(i.substring(2),16):i.charCodeAt(1)}
function E(i){if(i<32)return(i<16?"\\x0":"\\x")+i.toString(16);i=String.fromCharCode(i);return i==="\\"||i==="-"||i==="]"||i==="^"?"\\"+i:i}function c(i){var a=i.substring(1,i.length-1).match(/\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\s\S]|-|[^-\\]/g),i=[],k=a[0]==="^",e=["["];k&&e.push("^");for(var k=k?1:0,g=a.length;k<g;++k){var j=a[k];if(/\\[bdsw]/i.test(j))e.push(j);else{var j=b(j),h;k+2<g&&"-"===a[k+1]?(h=b(a[k+2]),k+=2):h=j;i.push([j,h]);h<65||j>122||(h<65||j>90||
i.push([Math.max(65,j)|32,Math.min(h,90)|32]),h<97||j>122||i.push([Math.max(97,j)&-33,Math.min(h,122)&-33]))}}i.sort(function(i,a){return i[0]-a[0]||a[1]-i[1]});a=[];g=[];for(k=0;k<i.length;++k)j=i[k],j[0]<=g[1]+1?g[1]=Math.max(g[1],j[1]):a.push(g=j);for(k=0;k<a.length;++k)j=a[k],e.push(E(j[0])),j[1]>j[0]&&(j[1]+1>j[0]&&e.push("-"),e.push(E(j[1])));e.push("]");return e.join("")}function d(i){for(var a=i.source.match(RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)",
"g")),e=a.length,b=[],g=0,j=0;g<e;++g){var h=a[g];h==="("?++j:"\\"===h.charAt(0)&&(h=+h.substring(1))&&(h<=j?b[h]=-1:a[g]=E(h))}for(g=1;g<b.length;++g)-1===b[g]&&(b[g]=++f);for(j=g=0;g<e;++g)h=a[g],h==="("?(++j,b[j]||(a[g]="(?:")):"\\"===h.charAt(0)&&(h=+h.substring(1))&&h<=j&&(a[g]="\\"+b[h]);for(g=0;g<e;++g)"^"===a[g]&&"^"!==a[g+1]&&(a[g]="");if(i.ignoreCase&&y)for(g=0;g<e;++g)h=a[g],i=h.charAt(0),h.length>=2&&i==="["?a[g]=c(h):i!=="\\"&&(a[g]=h.replace(/[a-zA-Z]/g,function(a){a=a.charCodeAt(0);
return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var f=0,y=!1,n=!1,q=0,e=a.length;q<e;++q){var m=a[q];if(m.ignoreCase)n=!0;else if(/[a-z]/i.test(m.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){y=!0;n=!1;break}}for(var O={b:8,t:9,n:10,v:11,f:12,r:13},p=[],q=0,e=a.length;q<e;++q){m=a[q];if(m.global||m.multiline)throw Error(""+m);p.push("(?:"+d(m)+")")}return RegExp(p.join("|"),n?"gi":"g")}function f(a,b){function c(a){switch(a.nodeType){case 1:if(d.test(a.className))break;
for(var e=a.firstChild;e;e=e.nextSibling)c(e);e=a.nodeName.toLowerCase();if("br"===e||"li"===e)f[n]="\n",y[n<<1]=l++,y[n++<<1|1]=a;break;case 3:case 4:e=a.nodeValue,e.length&&(e=b?e.replace(/\r\n?/g,"\n"):e.replace(/[ \t\r\n]+/g," "),f[n]=e,y[n<<1]=l,l+=e.length,y[n++<<1|1]=a)}}var d=/(?:^|\s)nocode(?:\s|$)/,f=[],l=0,y=[],n=0;c(a);return{sourceCode:f.join("").replace(/\n$/,""),spans:y}}function a(a,b,c,d){b&&(a={sourceCode:b,basePos:a},c(a),d.push.apply(d,a.decorations))}function o(b,c){var E={},
f;(function(){for(var a=b.concat(c),n=[],q={},e=0,m=a.length;e<m;++e){var l=a[e],p=l[3];if(p)for(var i=p.length;--i>=0;)E[p.charAt(i)]=l;l=l[1];p=""+l;q.hasOwnProperty(p)||(n.push(l),q[p]=null)}n.push(/[\0-\uffff]/);f=d(n)})();var l=c.length,t=function(b){for(var d=b.basePos,G=[d,"pln"],e=0,m=b.sourceCode.match(f)||[],s={},p=0,i=m.length;p<i;++p){var x=m[p],k=s[x],u=void 0,g;if(typeof k==="string")g=!1;else{var j=E[x.charAt(0)];if(j)u=x.match(j[1]),k=j[0];else{for(g=0;g<l;++g)if(j=c[g],u=x.match(j[1])){k=
j[0];break}u||(k="pln")}if((g=k.length>=5&&"lang-"===k.substring(0,5))&&!(u&&typeof u[1]==="string"))g=!1,k="src";g||(s[x]=k)}j=e;e+=x.length;if(g){g=u[1];var h=x.indexOf(g),D=h+g.length;u[2]&&(D=x.length-u[2].length,h=D-g.length);k=k.substring(5);a(d+j,x.substring(0,h),t,G);a(d+j+h,g,r(k,g),G);a(d+j+D,x.substring(D),t,G)}else G.push(d+j,k)}b.decorations=G};return t}function c(a){var b=[],c=[];a.tripleQuotedStrings?b.push(["str",/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
null,"'\""]):a.multiLineStrings?b.push(["str",/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):b.push(["str",/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);a.verbatimStrings&&c.push(["str",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);var d=a.hashComments;d&&(a.cStyleComments?(d>1?b.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"]):b.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,
null,"#"]),c.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,null])):b.push(["com",/^#[^\r\n]*/,null,"#"]));a.cStyleComments&&(c.push(["com",/^\/\/[^\r\n]*/,null]),c.push(["com",/^\/\*[\s\S]*?(?:\*\/|$)/,null]));a.regexLiterals&&c.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*(/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/)")]);
(d=a.types)&&c.push(["typ",d]);a=(""+a.keywords).replace(/^ | $/g,"");a.length&&c.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),null]);b.push(["pln",/^\s+/,null," \r\n\t\u00a0"]);c.push(["lit",/^@[a-z_$][a-z_$@0-9]*/i,null],["typ",/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],["pln",/^[a-z_$][a-z_$@0-9]*/i,null],["lit",/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],["pln",/^\\[\s\S]?/,null],["pun",/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);
return o(b,c)}function l(a,b,c){function d(a){switch(a.nodeType){case 1:if(l.test(a.className))break;if("br"===a.nodeName)f(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)d(a);break;case 3:case 4:if(c){var b=a.nodeValue,e=b.match(t);if(e){var m=b.substring(0,e.index);a.nodeValue=m;(b=b.substring(e.index+e[0].length))&&a.parentNode.insertBefore(n.createTextNode(b),a.nextSibling);f(a);m||a.parentNode.removeChild(a)}}}}function f(a){function b(a,c){var e=c?a.cloneNode(!1):
a,h=a.parentNode;if(h){var h=b(h,1),d=a.nextSibling;h.appendChild(e);for(var i=d;i;i=d)d=i.nextSibling,h.appendChild(i)}return e}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),c;(c=a.parentNode)&&c.nodeType===1;)a=c;e.push(a)}for(var l=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,n=a.ownerDocument,q=n.createElement("li");a.firstChild;)q.appendChild(a.firstChild);for(var e=[q],m=0;m<e.length;++m)d(e[m]);b===(b|0)&&e[0].setAttribute("value",b);var s=n.createElement("ol");s.className=
"linenums";for(var b=Math.max(0,b-1|0)||0,m=0,p=e.length;m<p;++m)q=e[m],q.className="L"+(m+b)%10,q.firstChild||q.appendChild(n.createTextNode("\u00a0")),s.appendChild(q);a.appendChild(s)}function b(a,b){for(var c=b.length;--c>=0;){var d=b[c];I.hasOwnProperty(d)?s.console&&console.warn("cannot override language handler %s",d):I[d]=a}}function r(a,b){if(!a||!I.hasOwnProperty(a))a=/^\s*</.test(b)?"default-markup":"default-code";return I[a]}function t(a){var b=a.langExtension;try{var c=f(a.sourceNode,
a.pre),d=c.sourceCode;a.sourceCode=d;a.spans=c.spans;a.basePos=0;r(b,d)(a);var l=/\bMSIE\s(\d+)/.exec(navigator.userAgent),l=l&&+l[1]<=8,b=/\n/g,o=a.sourceCode,y=o.length,c=0,n=a.spans,q=n.length,d=0,e=a.decorations,m=e.length,v=0;e[m]=y;var p,i;for(i=p=0;i<m;)e[i]!==e[i+2]?(e[p++]=e[i++],e[p++]=e[i++]):i+=2;m=p;for(i=p=0;i<m;){for(var x=e[i],k=e[i+1],u=i+2;u+2<=m&&e[u+1]===k;)u+=2;e[p++]=x;e[p++]=k;i=u}e.length=p;var g=a.sourceNode,j;if(g)j=g.style.display,g.style.display="none";try{for(;d<q;){var h=
n[d+2]||y,D=e[v+2]||y,u=Math.min(h,D),C=n[d+1],J;if(C.nodeType!==1&&(J=o.substring(c,u))){l&&(J=J.replace(b,"\r"));C.nodeValue=J;var A=C.ownerDocument,w=A.createElement("span");w.className=e[v+1];var B=C.parentNode;B.replaceChild(w,C);w.appendChild(C);c<h&&(n[d+1]=C=A.createTextNode(o.substring(u,h)),B.insertBefore(C,w.nextSibling))}c=u;c>=h&&(d+=2);c>=D&&(v+=2)}}finally{if(g)g.style.display=j}}catch(z){s.console&&console.log(z&&z.stack?z.stack:z)}}var s=v,B=["break,continue,do,else,for,if,return,while"],
z=[[B,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],A=[z,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],
w=[z,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],F=[w,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],z=[z,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],
L=[B,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],M=[B,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],B=[B,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],N=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,
K=/\S/,P=c({keywords:[A,F,z,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+L,M,B],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),I={};b(P,["default-code"]);b(o([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",
/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);b(o([["pln",/^[\s]+/,null," \t\r\n"],["atv",/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],
["pun",/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);b(o([],[["atv",/^[\s\S]+/]]),["uq.val"]);b(c({keywords:A,hashComments:!0,cStyleComments:!0,types:N}),["c","cc","cpp","cxx","cyc","m"]);b(c({keywords:"null,true,false"}),["json"]);b(c({keywords:F,hashComments:!0,cStyleComments:!0,
verbatimStrings:!0,types:N}),["cs"]);b(c({keywords:w,cStyleComments:!0}),["java"]);b(c({keywords:B,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);b(c({keywords:L,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py"]);b(c({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl",
"pl","pm"]);b(c({keywords:M,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);b(c({keywords:z,cStyleComments:!0,regexLiterals:!0}),["js"]);b(c({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);b(o([],[["str",/^[\s\S]+/]]),["regex"]);var Q=s.PR={createSimpleLexer:o,
registerLangHandler:b,sourceDecorator:c,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:s.prettyPrintOne=function(a,b,c){var d=document.createElement("div");d.innerHTML="<pre>"+a+"</pre>";d=d.firstChild;c&&l(d,c,!0);t({langExtension:b,numberLines:c,sourceNode:d,pre:1});return d.innerHTML},prettyPrint:s.prettyPrint=
function(a){function b(){var u;for(var c=s.PR_SHOULD_USE_CONTINUATION?n.now()+250:Infinity;q<d.length&&n.now()<c;q++){var g=d[q],j=g.className;if(v.test(j)&&!p.test(j)){for(var h=!1,f=g.parentNode;f;f=f.parentNode)if(k.test(f.tagName)&&f.className&&v.test(f.className)){h=!0;break}if(!h){g.className+=" prettyprinted";var j=j.match(m),o;if(h=!j){for(var h=g,f=H,r=h.firstChild;r;r=r.nextSibling)var w=r.nodeType,f=w===1?f?h:r:w===3?K.test(r.nodeValue)?h:f:f;h=(o=f===h?H:f)&&x.test(o.tagName)}h&&(j=o.className.match(m));
j&&(j=j[1]);u=i.test(g.tagName)?1:(h=(h=g.currentStyle)?h.whiteSpace:document.defaultView&&document.defaultView.getComputedStyle?document.defaultView.getComputedStyle(g,null).getPropertyValue("white-space"):0)&&"pre"===h.substring(0,3),h=u;(f=(f=g.className.match(/\blinenums\b(?::(\d+))?/))?f[1]&&f[1].length?+f[1]:!0:!1)&&l(g,f,h);e={langExtension:j,sourceNode:g,numberLines:f,pre:h};t(e)}}}q<d.length?setTimeout(b,250):a&&a()}for(var c=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),
document.getElementsByTagName("xmp")],d=[],f=0;f<c.length;++f)for(var o=0,r=c[f].length;o<r;++o)d.push(c[f][o]);var c=null,n=Date;n.now||(n={now:function(){return+new Date}});var q=0,e,m=/\blang(?:uage)?-([\w.]+)(?!\S)/,v=/\bprettyprint\b/,p=/\bprettyprinted\b/,i=/pre|xmp/i,x=/^code$/i,k=/^(?:pre|code|xmp)$/i;b()}};typeof define==="function"&&define.amd&&define("google-code-prettify",[],function(){return Q})})()})(window,window.angular);angular.element(document).find("head").append('<style type="text/css">.com{color:#93a1a1;}.lit{color:#195f91;}.pun,.opn,.clo{color:#93a1a1;}.fun{color:#dc322f;}.str,.atv{color:#D14;}.kwd,.linenums .tag{color:#1e347b;}.typ,.atn,.dec,.var{color:teal;}.pln{color:#48484c;}.prettyprint{padding:8px;background-color:#f7f7f9;border:1px solid #e1e1e8;}.prettyprint.linenums{-webkit-box-shadow:inset 40px 0 0 #fbfbfc,inset 41px 0 0 #ececf0;-moz-box-shadow:inset 40px 0 0 #fbfbfc,inset 41px 0 0 #ececf0;box-shadow:inset 40px 0 0 #fbfbfc,inset 41px 0 0 #ececf0;}ol.linenums{margin:0 0 0 33px;}ol.linenums li{padding-left:12px;color:#bebec5;line-height:18px;text-shadow:0 1px 0 #fff;}</style>');

167
lib/ui/static/lib/angular/angular-bootstrap.js vendored Executable file
View File

@ -0,0 +1,167 @@
/**
* @license AngularJS v1.1.4
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {
'use strict';
var directive = {};
directive.dropdownToggle =
['$document', '$location', '$window',
function ($document, $location, $window) {
var openElement = null, close;
return {
restrict: 'C',
link: function(scope, element, attrs) {
scope.$watch(function dropdownTogglePathWatch(){return $location.path();}, function dropdownTogglePathWatchAction() {
close && close();
});
element.parent().bind('click', function(event) {
close && close();
});
element.bind('click', function(event) {
event.preventDefault();
event.stopPropagation();
var iWasOpen = false;
if (openElement) {
iWasOpen = openElement === element;
close();
}
if (!iWasOpen){
element.parent().addClass('open');
openElement = element;
close = function (event) {
event && event.preventDefault();
event && event.stopPropagation();
$document.unbind('click', close);
element.parent().removeClass('open');
close = null;
openElement = null;
}
$document.bind('click', close);
}
});
}
};
}];
directive.tabbable = function() {
return {
restrict: 'C',
compile: function(element) {
var navTabs = angular.element('<ul class="nav nav-tabs"></ul>'),
tabContent = angular.element('<div class="tab-content"></div>');
tabContent.append(element.contents());
element.append(navTabs).append(tabContent);
},
controller: ['$scope', '$element', function($scope, $element) {
var navTabs = $element.contents().eq(0),
ngModel = $element.controller('ngModel') || {},
tabs = [],
selectedTab;
ngModel.$render = function() {
var $viewValue = this.$viewValue;
if (selectedTab ? (selectedTab.value != $viewValue) : $viewValue) {
if(selectedTab) {
selectedTab.paneElement.removeClass('active');
selectedTab.tabElement.removeClass('active');
selectedTab = null;
}
if($viewValue) {
for(var i = 0, ii = tabs.length; i < ii; i++) {
if ($viewValue == tabs[i].value) {
selectedTab = tabs[i];
break;
}
}
if (selectedTab) {
selectedTab.paneElement.addClass('active');
selectedTab.tabElement.addClass('active');
}
}
}
};
this.addPane = function(element, attr) {
var li = angular.element('<li><a href></a></li>'),
a = li.find('a'),
tab = {
paneElement: element,
paneAttrs: attr,
tabElement: li
};
tabs.push(tab);
attr.$observe('value', update)();
attr.$observe('title', function(){ update(); a.text(tab.title); })();
function update() {
tab.title = attr.title;
tab.value = attr.value || attr.title;
if (!ngModel.$setViewValue && (!ngModel.$viewValue || tab == selectedTab)) {
// we are not part of angular
ngModel.$viewValue = tab.value;
}
ngModel.$render();
}
navTabs.append(li);
li.bind('click', function(event) {
event.preventDefault();
event.stopPropagation();
if (ngModel.$setViewValue) {
$scope.$apply(function() {
ngModel.$setViewValue(tab.value);
ngModel.$render();
});
} else {
// we are not part of angular
ngModel.$viewValue = tab.value;
ngModel.$render();
}
});
return function() {
tab.tabElement.remove();
for(var i = 0, ii = tabs.length; i < ii; i++ ) {
if (tab == tabs[i]) {
tabs.splice(i, 1);
}
}
};
}
}]
};
};
directive.tabPane = function() {
return {
require: '^tabbable',
restrict: 'C',
link: function(scope, element, attrs, tabsCtrl) {
element.bind('$remove', tabsCtrl.addPane(element, attrs));
}
};
};
angular.module('bootstrap', []).directive(directive);
})(window, window.angular);

View File

@ -0,0 +1,9 @@
/*
AngularJS v1.1.4
(c) 2010-2012 Google, Inc. http://angularjs.org
License: MIT
*/
(function(n,j){'use strict';j.module("bootstrap",[]).directive({dropdownToggle:["$document","$location","$window",function(h,e){var d=null,a;return{restrict:"C",link:function(g,b){g.$watch(function(){return e.path()},function(){a&&a()});b.parent().bind("click",function(){a&&a()});b.bind("click",function(i){i.preventDefault();i.stopPropagation();i=!1;d&&(i=d===b,a());i||(b.parent().addClass("open"),d=b,a=function(c){c&&c.preventDefault();c&&c.stopPropagation();h.unbind("click",a);b.parent().removeClass("open");
d=a=null},h.bind("click",a))})}}}],tabbable:function(){return{restrict:"C",compile:function(h){var e=j.element('<ul class="nav nav-tabs"></ul>'),d=j.element('<div class="tab-content"></div>');d.append(h.contents());h.append(e).append(d)},controller:["$scope","$element",function(h,e){var d=e.contents().eq(0),a=e.controller("ngModel")||{},g=[],b;a.$render=function(){var a=this.$viewValue;if(b?b.value!=a:a)if(b&&(b.paneElement.removeClass("active"),b.tabElement.removeClass("active"),b=null),a){for(var c=
0,d=g.length;c<d;c++)if(a==g[c].value){b=g[c];break}b&&(b.paneElement.addClass("active"),b.tabElement.addClass("active"))}};this.addPane=function(e,c){function l(){f.title=c.title;f.value=c.value||c.title;if(!a.$setViewValue&&(!a.$viewValue||f==b))a.$viewValue=f.value;a.$render()}var k=j.element("<li><a href></a></li>"),m=k.find("a"),f={paneElement:e,paneAttrs:c,tabElement:k};g.push(f);c.$observe("value",l)();c.$observe("title",function(){l();m.text(f.title)})();d.append(k);k.bind("click",function(b){b.preventDefault();
b.stopPropagation();a.$setViewValue?h.$apply(function(){a.$setViewValue(f.value);a.$render()}):(a.$viewValue=f.value,a.$render())});return function(){f.tabElement.remove();for(var a=0,b=g.length;a<b;a++)f==g[a]&&g.splice(a,1)}}}]}},tabPane:function(){return{require:"^tabbable",restrict:"C",link:function(h,e,d,a){e.bind("$remove",a.addPane(e,d))}}}})})(window,window.angular);

184
lib/ui/static/lib/angular/angular-cookies.js vendored Executable file
View File

@ -0,0 +1,184 @@
/**
* @license AngularJS v1.1.4
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {
'use strict';
/**
* @ngdoc overview
* @name ngCookies
*/
angular.module('ngCookies', ['ng']).
/**
* @ngdoc object
* @name ngCookies.$cookies
* @requires $browser
*
* @description
* Provides read/write access to browser's cookies.
*
* Only a simple Object is exposed and by adding or removing properties to/from
* this object, new cookies are created/deleted at the end of current $eval.
*
* @example
<doc:example>
<doc:source>
<script>
function ExampleController($cookies) {
// Retrieving a cookie
var favoriteCookie = $cookies.myFavorite;
// Setting a cookie
$cookies.myFavorite = 'oatmeal';
}
</script>
</doc:source>
</doc:example>
*/
factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {
var cookies = {},
lastCookies = {},
lastBrowserCookies,
runEval = false,
copy = angular.copy,
isUndefined = angular.isUndefined;
//creates a poller fn that copies all cookies from the $browser to service & inits the service
$browser.addPollFn(function() {
var currentCookies = $browser.cookies();
if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl
lastBrowserCookies = currentCookies;
copy(currentCookies, lastCookies);
copy(currentCookies, cookies);
if (runEval) $rootScope.$apply();
}
})();
runEval = true;
//at the end of each eval, push cookies
//TODO: this should happen before the "delayed" watches fire, because if some cookies are not
// strings or browser refuses to store some cookies, we update the model in the push fn.
$rootScope.$watch(push);
return cookies;
/**
* Pushes all the cookies from the service to the browser and verifies if all cookies were stored.
*/
function push() {
var name,
value,
browserCookies,
updated;
//delete any cookies deleted in $cookies
for (name in lastCookies) {
if (isUndefined(cookies[name])) {
$browser.cookies(name, undefined);
}
}
//update all cookies updated in $cookies
for(name in cookies) {
value = cookies[name];
if (!angular.isString(value)) {
if (angular.isDefined(lastCookies[name])) {
cookies[name] = lastCookies[name];
} else {
delete cookies[name];
}
} else if (value !== lastCookies[name]) {
$browser.cookies(name, value);
updated = true;
}
}
//verify what was actually stored
if (updated){
updated = false;
browserCookies = $browser.cookies();
for (name in cookies) {
if (cookies[name] !== browserCookies[name]) {
//delete or reset all cookies that the browser dropped from $cookies
if (isUndefined(browserCookies[name])) {
delete cookies[name];
} else {
cookies[name] = browserCookies[name];
}
updated = true;
}
}
}
}
}]).
/**
* @ngdoc object
* @name ngCookies.$cookieStore
* @requires $cookies
*
* @description
* Provides a key-value (string-object) storage, that is backed by session cookies.
* Objects put or retrieved from this storage are automatically serialized or
* deserialized by angular's toJson/fromJson.
* @example
*/
factory('$cookieStore', ['$cookies', function($cookies) {
return {
/**
* @ngdoc method
* @name ngCookies.$cookieStore#get
* @methodOf ngCookies.$cookieStore
*
* @description
* Returns the value of given cookie key
*
* @param {string} key Id to use for lookup.
* @returns {Object} Deserialized cookie value.
*/
get: function(key) {
return angular.fromJson($cookies[key]);
},
/**
* @ngdoc method
* @name ngCookies.$cookieStore#put
* @methodOf ngCookies.$cookieStore
*
* @description
* Sets a value for given cookie key
*
* @param {string} key Id for the `value`.
* @param {Object} value Value to be stored.
*/
put: function(key, value) {
$cookies[key] = angular.toJson(value);
},
/**
* @ngdoc method
* @name ngCookies.$cookieStore#remove
* @methodOf ngCookies.$cookieStore
*
* @description
* Remove given cookie
*
* @param {string} key Id of the key-value pair to delete.
*/
remove: function(key) {
delete $cookies[key];
}
};
}]);
})(window, window.angular);

View File

@ -0,0 +1,7 @@
/*
AngularJS v1.1.4
(c) 2010-2012 Google, Inc. http://angularjs.org
License: MIT
*/
(function(m,f,l){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(d,c){var b={},g={},h,i=!1,j=f.copy,k=f.isUndefined;c.addPollFn(function(){var a=c.cookies();h!=a&&(h=a,j(a,g),j(a,b),i&&d.$apply())})();i=!0;d.$watch(function(){var a,e,d;for(a in g)k(b[a])&&c.cookies(a,l);for(a in b)e=b[a],f.isString(e)?e!==g[a]&&(c.cookies(a,e),d=!0):f.isDefined(g[a])?b[a]=g[a]:delete b[a];if(d)for(a in e=c.cookies(),b)b[a]!==e[a]&&(k(e[a])?delete b[a]:b[a]=e[a])});return b}]).factory("$cookieStore",
["$cookies",function(d){return{get:function(c){return f.fromJson(d[c])},put:function(c,b){d[c]=f.toJson(b)},remove:function(c){delete d[c]}}}])})(window,window.angular);

304
lib/ui/static/lib/angular/angular-loader.js vendored Executable file
View File

@ -0,0 +1,304 @@
/**
* @license AngularJS v1.1.4
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(
/**
* @ngdoc interface
* @name angular.Module
* @description
*
* Interface for configuring angular {@link angular.module modules}.
*/
function setupModuleLoader(window) {
function ensure(obj, name, factory) {
return obj[name] || (obj[name] = factory());
}
return ensure(ensure(window, 'angular', Object), 'module', function() {
/** @type {Object.<string, angular.Module>} */
var modules = {};
/**
* @ngdoc function
* @name angular.module
* @description
*
* The `angular.module` is a global place for creating and registering Angular modules. All
* modules (angular core or 3rd party) that should be available to an application must be
* registered using this mechanism.
*
*
* # Module
*
* A module is a collocation of services, directives, filters, and configuration information. Module
* is used to configure the {@link AUTO.$injector $injector}.
*
* <pre>
* // Create a new module
* var myModule = angular.module('myModule', []);
*
* // register a new service
* myModule.value('appName', 'MyCoolApp');
*
* // configure existing services inside initialization blocks.
* myModule.config(function($locationProvider) {
'use strict';
* // Configure existing providers
* $locationProvider.hashPrefix('!');
* });
* </pre>
*
* Then you can create an injector and load your modules like this:
*
* <pre>
* var injector = angular.injector(['ng', 'MyModule'])
* </pre>
*
* However it's more likely that you'll just use
* {@link ng.directive:ngApp ngApp} or
* {@link angular.bootstrap} to simplify this process for you.
*
* @param {!string} name The name of the module to create or retrieve.
* @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the
* the module is being retrieved for further configuration.
* @param {Function} configFn Optional configuration function for the module. Same as
* {@link angular.Module#config Module#config()}.
* @returns {module} new module with the {@link angular.Module} api.
*/
return function module(name, requires, configFn) {
if (requires && modules.hasOwnProperty(name)) {
modules[name] = null;
}
return ensure(modules, name, function() {
if (!requires) {
throw Error('No module: ' + name);
}
/** @type {!Array.<Array.<*>>} */
var invokeQueue = [];
/** @type {!Array.<Function>} */
var runBlocks = [];
var config = invokeLater('$injector', 'invoke');
/** @type {angular.Module} */
var moduleInstance = {
// Private state
_invokeQueue: invokeQueue,
_runBlocks: runBlocks,
/**
* @ngdoc property
* @name angular.Module#requires
* @propertyOf angular.Module
* @returns {Array.<string>} List of module names which must be loaded before this module.
* @description
* Holds the list of modules which the injector will load before the current module is loaded.
*/
requires: requires,
/**
* @ngdoc property
* @name angular.Module#name
* @propertyOf angular.Module
* @returns {string} Name of the module.
* @description
*/
name: name,
/**
* @ngdoc method
* @name angular.Module#provider
* @methodOf angular.Module
* @param {string} name service name
* @param {Function} providerType Construction function for creating new instance of the service.
* @description
* See {@link AUTO.$provide#provider $provide.provider()}.
*/
provider: invokeLater('$provide', 'provider'),
/**
* @ngdoc method
* @name angular.Module#factory
* @methodOf angular.Module
* @param {string} name service name
* @param {Function} providerFunction Function for creating new instance of the service.
* @description
* See {@link AUTO.$provide#factory $provide.factory()}.
*/
factory: invokeLater('$provide', 'factory'),
/**
* @ngdoc method
* @name angular.Module#service
* @methodOf angular.Module
* @param {string} name service name
* @param {Function} constructor A constructor function that will be instantiated.
* @description
* See {@link AUTO.$provide#service $provide.service()}.
*/
service: invokeLater('$provide', 'service'),
/**
* @ngdoc method
* @name angular.Module#value
* @methodOf angular.Module
* @param {string} name service name
* @param {*} object Service instance object.
* @description
* See {@link AUTO.$provide#value $provide.value()}.
*/
value: invokeLater('$provide', 'value'),
/**
* @ngdoc method
* @name angular.Module#constant
* @methodOf angular.Module
* @param {string} name constant name
* @param {*} object Constant value.
* @description
* Because the constant are fixed, they get applied before other provide methods.
* See {@link AUTO.$provide#constant $provide.constant()}.
*/
constant: invokeLater('$provide', 'constant', 'unshift'),
/**
* @ngdoc method
* @name angular.Module#animation
* @methodOf angular.Module
* @param {string} name animation name
* @param {Function} animationFactory Factory function for creating new instance of an animation.
* @description
*
* Defines an animation hook that can be later used with {@link ng.directive:ngAnimate ngAnimate}
* alongside {@link ng.directive:ngAnimate#Description common ng directives} as well as custom directives.
* <pre>
* module.animation('animation-name', function($inject1, $inject2) {
* return {
* //this gets called in preparation to setup an animation
* setup : function(element) { ... },
*
* //this gets called once the animation is run
* start : function(element, done, memo) { ... }
* }
* })
* </pre>
*
* See {@link ng.$animationProvider#register $animationProvider.register()} and
* {@link ng.directive:ngAnimate ngAnimate} for more information.
*/
animation: invokeLater('$animationProvider', 'register'),
/**
* @ngdoc method
* @name angular.Module#filter
* @methodOf angular.Module
* @param {string} name Filter name.
* @param {Function} filterFactory Factory function for creating new instance of filter.
* @description
* See {@link ng.$filterProvider#register $filterProvider.register()}.
*/
filter: invokeLater('$filterProvider', 'register'),
/**
* @ngdoc method
* @name angular.Module#controller
* @methodOf angular.Module
* @param {string} name Controller name.
* @param {Function} constructor Controller constructor function.
* @description
* See {@link ng.$controllerProvider#register $controllerProvider.register()}.
*/
controller: invokeLater('$controllerProvider', 'register'),
/**
* @ngdoc method
* @name angular.Module#directive
* @methodOf angular.Module
* @param {string} name directive name
* @param {Function} directiveFactory Factory function for creating new instance of
* directives.
* @description
* See {@link ng.$compileProvider#directive $compileProvider.directive()}.
*/
directive: invokeLater('$compileProvider', 'directive'),
/**
* @ngdoc method
* @name angular.Module#config
* @methodOf angular.Module
* @param {Function} configFn Execute this function on module load. Useful for service
* configuration.
* @description
* Use this method to register work which needs to be performed on module loading.
*/
config: config,
/**
* @ngdoc method
* @name angular.Module#run
* @methodOf angular.Module
* @param {Function} initializationFn Execute this function after injector creation.
* Useful for application initialization.
* @description
* Use this method to register work which should be performed when the injector is done
* loading all modules.
*/
run: function(block) {
runBlocks.push(block);
return this;
}
};
if (configFn) {
config(configFn);
}
return moduleInstance;
/**
* @param {string} provider
* @param {string} method
* @param {String=} insertMethod
* @returns {angular.Module}
*/
function invokeLater(provider, method, insertMethod) {
return function() {
invokeQueue[insertMethod || 'push']([provider, method, arguments]);
return moduleInstance;
}
}
});
};
});
}
)(window);
/**
* Closure compiler type information
*
* @typedef { {
* requires: !Array.<string>,
* invokeQueue: !Array.<Array.<*>>,
*
* service: function(string, Function):angular.Module,
* factory: function(string, Function):angular.Module,
* value: function(string, *):angular.Module,
*
* filter: function(string, Function):angular.Module,
*
* init: function(Function):angular.Module
* } }
*/
angular.Module;

View File

@ -0,0 +1,7 @@
/*
AngularJS v1.1.4
(c) 2010-2012 Google, Inc. http://angularjs.org
License: MIT
*/
(function(i){'use strict';function d(c,b,e){return c[b]||(c[b]=e())}return d(d(i,"angular",Object),"module",function(){var c={};return function(b,e,f){e&&c.hasOwnProperty(b)&&(c[b]=null);return d(c,b,function(){function a(a,b,d){return function(){c[d||"push"]([a,b,arguments]);return g}}if(!e)throw Error("No module: "+b);var c=[],d=[],h=a("$injector","invoke"),g={_invokeQueue:c,_runBlocks:d,requires:e,name:b,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),
value:a("$provide","value"),constant:a("$provide","constant","unshift"),animation:a("$animationProvider","register"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:h,run:function(a){d.push(a);return this}};f&&h(f);return g})}})})(window);

267
lib/ui/static/lib/angular/angular-mobile.js vendored Executable file
View File

@ -0,0 +1,267 @@
/**
* @license AngularJS v1.1.4
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {
'use strict';
/**
* @ngdoc overview
* @name ngMobile
* @description
*/
/*
* Touch events and other mobile helpers by Braden Shepherdson (braden.shepherdson@gmail.com)
* Based on jQuery Mobile touch event handling (jquerymobile.com)
*/
// define ngSanitize module and register $sanitize service
var ngMobile = angular.module('ngMobile', []);
/**
* @ngdoc directive
* @name ngMobile.directive:ngTap
*
* @description
* Specify custom behavior when element is tapped on a touchscreen device.
* A tap is a brief, down-and-up touch without much motion.
*
* @element ANY
* @param {expression} ngClick {@link guide/expression Expression} to evaluate
* upon tap. (Event object is available as `$event`)
*
* @example
<doc:example>
<doc:source>
<button ng-tap="count = count + 1" ng-init="count=0">
Increment
</button>
count: {{ count }}
</doc:source>
</doc:example>
*/
ngMobile.config(['$provide', function($provide) {
$provide.decorator('ngClickDirective', ['$delegate', function($delegate) {
// drop the default ngClick directive
$delegate.shift();
return $delegate;
}]);
}]);
ngMobile.directive('ngClick', ['$parse', '$timeout', '$rootElement',
function($parse, $timeout, $rootElement) {
var TAP_DURATION = 750; // Shorter than 750ms is a tap, longer is a taphold or drag.
var MOVE_TOLERANCE = 12; // 12px seems to work in most mobile browsers.
var PREVENT_DURATION = 2500; // 2.5 seconds maximum from preventGhostClick call to click
var CLICKBUSTER_THRESHOLD = 25; // 25 pixels in any dimension is the limit for busting clicks.
var lastPreventedTime;
var touchCoordinates;
// TAP EVENTS AND GHOST CLICKS
//
// Why tap events?
// Mobile browsers detect a tap, then wait a moment (usually ~300ms) to see if you're
// double-tapping, and then fire a click event.
//
// This delay sucks and makes mobile apps feel unresponsive.
// So we detect touchstart, touchmove, touchcancel and touchend ourselves and determine when
// the user has tapped on something.
//
// What happens when the browser then generates a click event?
// The browser, of course, also detects the tap and fires a click after a delay. This results in
// tapping/clicking twice. So we do "clickbusting" to prevent it.
//
// How does it work?
// We attach global touchstart and click handlers, that run during the capture (early) phase.
// So the sequence for a tap is:
// - global touchstart: Sets an "allowable region" at the point touched.
// - element's touchstart: Starts a touch
// (- touchmove or touchcancel ends the touch, no click follows)
// - element's touchend: Determines if the tap is valid (didn't move too far away, didn't hold
// too long) and fires the user's tap handler. The touchend also calls preventGhostClick().
// - preventGhostClick() removes the allowable region the global touchstart created.
// - The browser generates a click event.
// - The global click handler catches the click, and checks whether it was in an allowable region.
// - If preventGhostClick was called, the region will have been removed, the click is busted.
// - If the region is still there, the click proceeds normally. Therefore clicks on links and
// other elements without ngTap on them work normally.
//
// This is an ugly, terrible hack!
// Yeah, tell me about it. The alternatives are using the slow click events, or making our users
// deal with the ghost clicks, so I consider this the least of evils. Fortunately Angular
// encapsulates this ugly logic away from the user.
//
// Why not just put click handlers on the element?
// We do that too, just to be sure. The problem is that the tap event might have caused the DOM
// to change, so that the click fires in the same position but something else is there now. So
// the handlers are global and care only about coordinates and not elements.
// Checks if the coordinates are close enough to be within the region.
function hit(x1, y1, x2, y2) {
return Math.abs(x1 - x2) < CLICKBUSTER_THRESHOLD && Math.abs(y1 - y2) < CLICKBUSTER_THRESHOLD;
}
// Checks a list of allowable regions against a click location.
// Returns true if the click should be allowed.
// Splices out the allowable region from the list after it has been used.
function checkAllowableRegions(touchCoordinates, x, y) {
for (var i = 0; i < touchCoordinates.length; i += 2) {
if (hit(touchCoordinates[i], touchCoordinates[i+1], x, y)) {
touchCoordinates.splice(i, i + 2);
return true; // allowable region
}
}
return false; // No allowable region; bust it.
}
// Global click handler that prevents the click if it's in a bustable zone and preventGhostClick
// was called recently.
function onClick(event) {
if (Date.now() - lastPreventedTime > PREVENT_DURATION) {
return; // Too old.
}
var touches = event.touches && event.touches.length ? event.touches : [event];
var x = touches[0].clientX;
var y = touches[0].clientY;
// Work around desktop Webkit quirk where clicking a label will fire two clicks (on the label
// and on the input element). Depending on the exact browser, this second click we don't want
// to bust has either (0,0) or negative coordinates.
if (x < 1 && y < 1) {
return; // offscreen
}
// Look for an allowable region containing this click.
// If we find one, that means it was created by touchstart and not removed by
// preventGhostClick, so we don't bust it.
if (checkAllowableRegions(touchCoordinates, x, y)) {
return;
}
// If we didn't find an allowable region, bust the click.
event.stopPropagation();
event.preventDefault();
}
// Global touchstart handler that creates an allowable region for a click event.
// This allowable region can be removed by preventGhostClick if we want to bust it.
function onTouchStart(event) {
var touches = event.touches && event.touches.length ? event.touches : [event];
var x = touches[0].clientX;
var y = touches[0].clientY;
touchCoordinates.push(x, y);
$timeout(function() {
// Remove the allowable region.
for (var i = 0; i < touchCoordinates.length; i += 2) {
if (touchCoordinates[i] == x && touchCoordinates[i+1] == y) {
touchCoordinates.splice(i, i + 2);
return;
}
}
}, PREVENT_DURATION, false);
}
// On the first call, attaches some event handlers. Then whenever it gets called, it creates a
// zone around the touchstart where clicks will get busted.
function preventGhostClick(x, y) {
if (!touchCoordinates) {
$rootElement[0].addEventListener('click', onClick, true);
$rootElement[0].addEventListener('touchstart', onTouchStart, true);
touchCoordinates = [];
}
lastPreventedTime = Date.now();
checkAllowableRegions(touchCoordinates, x, y);
}
// Actual linking function.
return function(scope, element, attr) {
var expressionFn = $parse(attr.ngClick),
tapping = false,
tapElement, // Used to blur the element after a tap.
startTime, // Used to check if the tap was held too long.
touchStartX,
touchStartY;
function resetState() {
tapping = false;
}
element.bind('touchstart', function(event) {
tapping = true;
tapElement = event.target ? event.target : event.srcElement; // IE uses srcElement.
// Hack for Safari, which can target text nodes instead of containers.
if(tapElement.nodeType == 3) {
tapElement = tapElement.parentNode;
}
startTime = Date.now();
var touches = event.touches && event.touches.length ? event.touches : [event];
var e = touches[0].originalEvent || touches[0];
touchStartX = e.clientX;
touchStartY = e.clientY;
});
element.bind('touchmove', function(event) {
resetState();
});
element.bind('touchcancel', function(event) {
resetState();
});
element.bind('touchend', function(event) {
var diff = Date.now() - startTime;
var touches = (event.changedTouches && event.changedTouches.length) ? event.changedTouches :
((event.touches && event.touches.length) ? event.touches : [event]);
var e = touches[0].originalEvent || touches[0];
var x = e.clientX;
var y = e.clientY;
var dist = Math.sqrt( Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2) );
if (tapping && diff < TAP_DURATION && dist < MOVE_TOLERANCE) {
// Call preventGhostClick so the clickbuster will catch the corresponding click.
preventGhostClick(x, y);
// Blur the focused element (the button, probably) before firing the callback.
// This doesn't work perfectly on Android Chrome, but seems to work elsewhere.
// I couldn't get anything to work reliably on Android Chrome.
if (tapElement) {
tapElement.blur();
}
scope.$apply(function() {
// TODO(braden): This is sending the touchend, not a tap or click. Is that kosher?
expressionFn(scope, {$event: event});
});
}
tapping = false;
});
// Hack for iOS Safari's benefit. It goes searching for onclick handlers and is liable to click
// something else nearby.
element.onclick = function(event) { };
// Fallback click handler.
// Busted clicks don't get this far, and adding this handler allows ng-tap to be used on
// desktop as well, to allow more portable sites.
element.bind('click', function(event) {
scope.$apply(function() {
expressionFn(scope, {$event: event});
});
});
};
}]);
})(window, window.angular);

View File

@ -0,0 +1,9 @@
/*
AngularJS v1.1.4
(c) 2010-2012 Google, Inc. http://angularjs.org
License: MIT
*/
(function(r,h){'use strict';var d=h.module("ngMobile",[]);d.config(["$provide",function(j){j.decorator("ngClickDirective",["$delegate",function(g){g.shift();return g}])}]);d.directive("ngClick",["$parse","$timeout","$rootElement",function(j,g,d){function k(a,b,c){for(var f=0;f<a.length;f+=2)if(Math.abs(a[f]-b)<m&&Math.abs(a[f+1]-c)<m)return a.splice(f,f+2),!0;return!1}function h(a){if(!(Date.now()-n>o)){var b=a.touches&&a.touches.length?a.touches:[a],e=b[0].clientX,b=b[0].clientY;!(e<1&&b<1)&&!k(c,
e,b)&&(a.stopPropagation(),a.preventDefault())}}function p(a){var a=a.touches&&a.touches.length?a.touches:[a],b=a[0].clientX,e=a[0].clientY;c.push(b,e);g(function(){for(var a=0;a<c.length;a+=2)if(c[a]==b&&c[a+1]==e){c.splice(a,a+2);break}},o,!1)}function q(a,b){c||(d[0].addEventListener("click",h,!0),d[0].addEventListener("touchstart",p,!0),c=[]);n=Date.now();k(c,a,b)}var o=2500,m=25,n,c;return function(a,b,c){var f=j(c.ngClick),d=!1,i,g,h,k;b.bind("touchstart",function(a){d=!0;i=a.target?a.target:
a.srcElement;if(i.nodeType==3)i=i.parentNode;g=Date.now();a=a.touches&&a.touches.length?a.touches:[a];a=a[0].originalEvent||a[0];h=a.clientX;k=a.clientY});b.bind("touchmove",function(){d=!1});b.bind("touchcancel",function(){d=!1});b.bind("touchend",function(b){var c=Date.now()-g,e=b.changedTouches&&b.changedTouches.length?b.changedTouches:b.touches&&b.touches.length?b.touches:[b],l=e[0].originalEvent||e[0],e=l.clientX,l=l.clientY,j=Math.sqrt(Math.pow(e-h,2)+Math.pow(l-k,2));d&&c<750&&j<12&&(q(e,l),
i&&i.blur(),a.$apply(function(){f(a,{$event:b})}));d=!1});b.onclick=function(){};b.bind("click",function(b){a.$apply(function(){f(a,{$event:b})})})}}])})(window,window.angular);

1846
lib/ui/static/lib/angular/angular-mocks.js vendored Executable file

File diff suppressed because it is too large Load Diff

521
lib/ui/static/lib/angular/angular-resource.js vendored Executable file
View File

@ -0,0 +1,521 @@
/**
* @license AngularJS v1.1.4
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {
'use strict';
/**
* @ngdoc overview
* @name ngResource
* @description
*/
/**
* @ngdoc object
* @name ngResource.$resource
* @requires $http
*
* @description
* A factory which creates a resource object that lets you interact with
* [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.
*
* The returned resource object has action methods which provide high-level behaviors without
* the need to interact with the low level {@link ng.$http $http} service.
*
* # Installation
* To use $resource make sure you have included the `angular-resource.js` that comes in Angular
* package. You also can find this stuff in {@link http://code.angularjs.org/ code.angularjs.org}.
* Finally load the module in your application:
*
* angular.module('app', ['ngResource']);
*
* and you ready to get started!
*
* @param {string} url A parametrized URL template with parameters prefixed by `:` as in
* `/user/:username`. If you are using a URL with a port number (e.g.
* `http://example.com:8080/api`), you'll need to escape the colon character before the port
* number, like this: `$resource('http://example.com\\:8080/api')`.
*
* @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
* `actions` methods. If any of the parameter value is a function, it will be executed every time
* when a param value needs to be obtained for a request (unless the param was overridden).
*
* Each key value in the parameter object is first bound to url template if present and then any
* excess keys are appended to the url search query after the `?`.
*
* Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in
* URL `/path/greet?salutation=Hello`.
*
* If the parameter value is prefixed with `@` then the value of that parameter is extracted from
* the data object (useful for non-GET operations).
*
* @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the
* default set of resource actions. The declaration should be created in the format of {@link
* ng.$http#Parameters $http.config}:
*
* {action1: {method:?, params:?, isArray:?, headers:?, ...},
* action2: {method:?, params:?, isArray:?, headers:?, ...},
* ...}
*
* Where:
*
* - **`action`** {string} The name of action. This name becomes the name of the method on your
* resource object.
* - **`method`** {string} HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,
* and `JSONP`.
* - **`params`** {Object=} Optional set of pre-bound parameters for this action. If any of the
* parameter value is a function, it will be executed every time when a param value needs to be
* obtained for a request (unless the param was overridden).
* - **`url`** {string} action specific `url` override. The url templating is supported just like
* for the resource-level urls.
* - **`isArray`** {boolean=} If true then the returned object for this action is an array, see
* `returns` section.
* - **`transformRequest`** `{function(data, headersGetter)|Array.<function(data, headersGetter)>}`
* transform function or an array of such functions. The transform function takes the http
* request body and headers and returns its transformed (typically serialized) version.
* - **`transformResponse`** `{function(data, headersGetter)|Array.<function(data, headersGetter)>}`
* transform function or an array of such functions. The transform function takes the http
* response body and headers and returns its transformed (typically deserialized) version.
* - **`cache`** `{boolean|Cache}` If true, a default $http cache will be used to cache the
* GET request, otherwise if a cache instance built with
* {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
* caching.
* - **`timeout`** `{number}` timeout in milliseconds.
* - **`withCredentials`** - `{boolean}` - whether to to set the `withCredentials` flag on the
* XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5
* requests with credentials} for more information.
* - **`responseType`** - `{string}` - see {@link
* https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}.
*
* @returns {Object} A resource "class" object with methods for the default set of resource actions
* optionally extended with custom `actions`. The default set contains these actions:
*
* { 'get': {method:'GET'},
* 'save': {method:'POST'},
* 'query': {method:'GET', isArray:true},
* 'remove': {method:'DELETE'},
* 'delete': {method:'DELETE'} };
*
* Calling these methods invoke an {@link ng.$http} with the specified http method,
* destination and parameters. When the data is returned from the server then the object is an
* instance of the resource class. The actions `save`, `remove` and `delete` are available on it
* as methods with the `$` prefix. This allows you to easily perform CRUD operations (create,
* read, update, delete) on server-side data like this:
* <pre>
var User = $resource('/user/:userId', {userId:'@id'});
var user = User.get({userId:123}, function() {
user.abc = true;
user.$save();
});
</pre>
*
* It is important to realize that invoking a $resource object method immediately returns an
* empty reference (object or array depending on `isArray`). Once the data is returned from the
* server the existing reference is populated with the actual data. This is a useful trick since
* usually the resource is assigned to a model which is then rendered by the view. Having an empty
* object results in no rendering, once the data arrives from the server then the object is
* populated with the data and the view automatically re-renders itself showing the new data. This
* means that in most case one never has to write a callback function for the action methods.
*
* The action methods on the class object or instance object can be invoked with the following
* parameters:
*
* - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])`
* - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])`
* - non-GET instance actions: `instance.$action([parameters], [success], [error])`
*
*
* The Resource instances and collection have these additional properties:
*
* - `$then`: the `then` method of a {@link ng.$q promise} derived from the underlying
* {@link ng.$http $http} call.
*
* The success callback for the `$then` method will be resolved if the underlying `$http` requests
* succeeds.
*
* The success callback is called with a single object which is the {@link ng.$http http response}
* object extended with a new property `resource`. This `resource` property is a reference to the
* result of the resource action resource object or array of resources.
*
* The error callback is called with the {@link ng.$http http response} object when an http
* error occurs.
*
* - `$resolved`: true if the promise has been resolved (either with success or rejection);
* Knowing if the Resource has been resolved is useful in data-binding.
*
* @example
*
* # Credit card resource
*
* <pre>
// Define CreditCard class
var CreditCard = $resource('/user/:userId/card/:cardId',
{userId:123, cardId:'@id'}, {
charge: {method:'POST', params:{charge:true}}
});
// We can retrieve a collection from the server
var cards = CreditCard.query(function() {
// GET: /user/123/card
// server returns: [ {id:456, number:'1234', name:'Smith'} ];
var card = cards[0];
// each item is an instance of CreditCard
expect(card instanceof CreditCard).toEqual(true);
card.name = "J. Smith";
// non GET methods are mapped onto the instances
card.$save();
// POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
// server returns: {id:456, number:'1234', name: 'J. Smith'};
// our custom method is mapped as well.
card.$charge({amount:9.99});
// POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
});
// we can create an instance as well
var newCard = new CreditCard({number:'0123'});
newCard.name = "Mike Smith";
newCard.$save();
// POST: /user/123/card {number:'0123', name:'Mike Smith'}
// server returns: {id:789, number:'01234', name: 'Mike Smith'};
expect(newCard.id).toEqual(789);
* </pre>
*
* The object returned from this function execution is a resource "class" which has "static" method
* for each action in the definition.
*
* Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and `headers`.
* When the data is returned from the server then the object is an instance of the resource type and
* all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
* operations (create, read, update, delete) on server-side data.
<pre>
var User = $resource('/user/:userId', {userId:'@id'});
var user = User.get({userId:123}, function() {
user.abc = true;
user.$save();
});
</pre>
*
* It's worth noting that the success callback for `get`, `query` and other method gets passed
* in the response that came from the server as well as $http header getter function, so one
* could rewrite the above example and get access to http headers as:
*
<pre>
var User = $resource('/user/:userId', {userId:'@id'});
User.get({userId:123}, function(u, getResponseHeaders){
u.abc = true;
u.$save(function(u, putResponseHeaders) {
//u => saved user object
//putResponseHeaders => $http header getter
});
});
</pre>
* # Buzz client
Let's look at what a buzz client created with the `$resource` service looks like:
<doc:example>
<doc:source jsfiddle="false">
<script>
function BuzzController($resource) {
this.userId = 'googlebuzz';
this.Activity = $resource(
'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
{alt:'json', callback:'JSON_CALLBACK'},
{get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}
);
}
BuzzController.prototype = {
fetch: function() {
this.activities = this.Activity.get({userId:this.userId});
},
expandReplies: function(activity) {
activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});
}
};
BuzzController.$inject = ['$resource'];
</script>
<div ng-controller="BuzzController">
<input ng-model="userId"/>
<button ng-click="fetch()">fetch</button>
<hr/>
<div ng-repeat="item in activities.data.items">
<h1 style="font-size: 15px;">
<img src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
<a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
<a href ng-click="expandReplies(item)" style="float: right;">Expand replies: {{item.links.replies[0].count}}</a>
</h1>
{{item.object.content | html}}
<div ng-repeat="reply in item.replies.data.items" style="margin-left: 20px;">
<img src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
<a href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>: {{reply.content | html}}
</div>
</div>
</div>
</doc:source>
<doc:scenario>
</doc:scenario>
</doc:example>
*/
angular.module('ngResource', ['ng']).
factory('$resource', ['$http', '$parse', function($http, $parse) {
var DEFAULT_ACTIONS = {
'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'}
};
var noop = angular.noop,
forEach = angular.forEach,
extend = angular.extend,
copy = angular.copy,
isFunction = angular.isFunction,
getter = function(obj, path) {
return $parse(path)(obj);
};
/**
* We need our custom method because encodeURIComponent is too aggressive and doesn't follow
* http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
* segments:
* segment = *pchar
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
* pct-encoded = "%" HEXDIG HEXDIG
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
* / "*" / "+" / "," / ";" / "="
*/
function encodeUriSegment(val) {
return encodeUriQuery(val, true).
replace(/%26/gi, '&').
replace(/%3D/gi, '=').
replace(/%2B/gi, '+');
}
/**
* This method is intended for encoding *key* or *value* parts of query component. We need a custom
* method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
* encoded per http://tools.ietf.org/html/rfc3986:
* query = *( pchar / "/" / "?" )
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* pct-encoded = "%" HEXDIG HEXDIG
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
* / "*" / "+" / "," / ";" / "="
*/
function encodeUriQuery(val, pctEncodeSpaces) {
return encodeURIComponent(val).
replace(/%40/gi, '@').
replace(/%3A/gi, ':').
replace(/%24/g, '$').
replace(/%2C/gi, ',').
replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
}
function Route(template, defaults) {
this.template = template = template + '#';
this.defaults = defaults || {};
this.urlParams = {};
}
Route.prototype = {
setUrlParams: function(config, params, actionUrl) {
var self = this,
url = actionUrl || self.template,
val,
encodedVal;
var urlParams = self.urlParams = {};
forEach(url.split(/\W/), function(param){
if (param && (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) {
urlParams[param] = true;
}
});
url = url.replace(/\\:/g, ':');
params = params || {};
forEach(self.urlParams, function(_, urlParam){
val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
if (angular.isDefined(val) && val !== null) {
encodedVal = encodeUriSegment(val);
url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), encodedVal + "$1");
} else {
url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match,
leadingSlashes, tail) {
if (tail.charAt(0) == '/') {
return tail;
} else {
return leadingSlashes + tail;
}
});
}
});
// set the url
config.url = url.replace(/\/?#$/, '').replace(/\/*$/, '');
// set params - delegate param encoding to $http
forEach(params, function(value, key){
if (!self.urlParams[key]) {
config.params = config.params || {};
config.params[key] = value;
}
});
}
};
function ResourceFactory(url, paramDefaults, actions) {
var route = new Route(url);
actions = extend({}, DEFAULT_ACTIONS, actions);
function extractParams(data, actionParams){
var ids = {};
actionParams = extend({}, paramDefaults, actionParams);
forEach(actionParams, function(value, key){
if (isFunction(value)) { value = value(); }
ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;
});
return ids;
}
function Resource(value){
copy(value || {}, this);
}
forEach(actions, function(action, name) {
action.method = angular.uppercase(action.method);
var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';
Resource[name] = function(a1, a2, a3, a4) {
var params = {};
var data;
var success = noop;
var error = null;
var promise;
switch(arguments.length) {
case 4:
error = a4;
success = a3;
//fallthrough
case 3:
case 2:
if (isFunction(a2)) {
if (isFunction(a1)) {
success = a1;
error = a2;
break;
}
success = a2;
error = a3;
//fallthrough
} else {
params = a1;
data = a2;
success = a3;
break;
}
case 1:
if (isFunction(a1)) success = a1;
else if (hasBody) data = a1;
else params = a1;
break;
case 0: break;
default:
throw "Expected between 0-4 arguments [params, data, success, error], got " +
arguments.length + " arguments.";
}
var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));
var httpConfig = {},
promise;
forEach(action, function(value, key) {
if (key != 'params' && key != 'isArray' ) {
httpConfig[key] = copy(value);
}
});
httpConfig.data = data;
route.setUrlParams(httpConfig, extend({}, extractParams(data, action.params || {}), params), action.url);
function markResolved() { value.$resolved = true; }
promise = $http(httpConfig);
value.$resolved = false;
promise.then(markResolved, markResolved);
value.$then = promise.then(function(response) {
var data = response.data;
var then = value.$then, resolved = value.$resolved;
if (data) {
if (action.isArray) {
value.length = 0;
forEach(data, function(item) {
value.push(new Resource(item));
});
} else {
copy(data, value);
value.$then = then;
value.$resolved = resolved;
}
}
(success||noop)(value, response.headers);
response.resource = value;
return response;
}, error).then;
return value;
};
Resource.prototype['$' + name] = function(a1, a2, a3) {
var params = extractParams(this),
success = noop,
error;
switch(arguments.length) {
case 3: params = a1; success = a2; error = a3; break;
case 2:
case 1:
if (isFunction(a1)) {
success = a1;
error = a2;
} else {
params = a1;
success = a2 || noop;
}
case 0: break;
default:
throw "Expected between 1-3 arguments [params, success, error], got " +
arguments.length + " arguments.";
}
var data = hasBody ? this : undefined;
Resource[name].call(this, params, data, success, error);
};
});
Resource.bind = function(additionalParamDefaults){
return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
};
return Resource;
}
return ResourceFactory;
}]);
})(window, window.angular);

View File

@ -0,0 +1,11 @@
/*
AngularJS v1.1.4
(c) 2010-2012 Google, Inc. http://angularjs.org
License: MIT
*/
(function(B,f,x){'use strict';f.module("ngResource",["ng"]).factory("$resource",["$http","$parse",function(y,z){function v(g,c){this.template=g+"#";this.defaults=c||{};this.urlParams={}}function w(g,c,d){function j(e,b){var p={},b=q({},c,b);k(b,function(a,b){l(a)&&(a=a());var h;a.charAt&&a.charAt(0)=="@"?(h=a.substr(1),h=z(h)(e)):h=a;p[b]=h});return p}function b(b){u(b||{},this)}var m=new v(g),d=q({},A,d);k(d,function(e,c){e.method=f.uppercase(e.method);var p=e.method=="POST"||e.method=="PUT"||e.method==
"PATCH";b[c]=function(a,c,h,g){function f(){i.$resolved=!0}var n={},d,o=r,s=null;switch(arguments.length){case 4:s=g,o=h;case 3:case 2:if(l(c)){if(l(a)){o=a;s=c;break}o=c;s=h}else{n=a;d=c;o=h;break}case 1:l(a)?o=a:p?d=a:n=a;break;case 0:break;default:throw"Expected between 0-4 arguments [params, data, success, error], got "+arguments.length+" arguments.";}var i=this instanceof b?this:e.isArray?[]:new b(d),t={};k(e,function(a,b){b!="params"&&b!="isArray"&&(t[b]=u(a))});t.data=d;m.setUrlParams(t,q({},
j(d,e.params||{}),n),e.url);n=y(t);i.$resolved=!1;n.then(f,f);i.$then=n.then(function(a){var c=a.data,h=i.$then,d=i.$resolved;if(c)e.isArray?(i.length=0,k(c,function(a){i.push(new b(a))})):(u(c,i),i.$then=h,i.$resolved=d);(o||r)(i,a.headers);a.resource=i;return a},s).then;return i};b.prototype["$"+c]=function(a,e,h){var d=j(this),f=r,g;switch(arguments.length){case 3:d=a;f=e;g=h;break;case 2:case 1:l(a)?(f=a,g=e):(d=a,f=e||r);case 0:break;default:throw"Expected between 1-3 arguments [params, success, error], got "+
arguments.length+" arguments.";}b[c].call(this,d,p?this:x,f,g)}});b.bind=function(b){return w(g,q({},c,b),d)};return b}var A={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}},r=f.noop,k=f.forEach,q=f.extend,u=f.copy,l=f.isFunction;v.prototype={setUrlParams:function(g,c,d){var j=this,b=d||j.template,m,e,l=j.urlParams={};k(b.split(/\W/),function(c){c&&RegExp("(^|[^\\\\]):"+c+"(\\W|$)").test(b)&&(l[c]=!0)});b=b.replace(/\\:/g,
":");c=c||{};k(j.urlParams,function(d,a){m=c.hasOwnProperty(a)?c[a]:j.defaults[a];f.isDefined(m)&&m!==null?(e=encodeURIComponent(m).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"%20").replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+"),b=b.replace(RegExp(":"+a+"(\\W|$)","g"),e+"$1")):b=b.replace(RegExp("(/?):"+a+"(\\W|$)","g"),function(a,b,c){return c.charAt(0)=="/"?c:b+c})});g.url=b.replace(/\/?#$/,"").replace(/\/*$/,"");k(c,function(b,
a){if(!j.urlParams[a])g.params=g.params||{},g.params[a]=b})}};return w}])})(window,window.angular);

558
lib/ui/static/lib/angular/angular-sanitize.js vendored Executable file
View File

@ -0,0 +1,558 @@
/**
* @license AngularJS v1.1.4
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {
'use strict';
/**
* @ngdoc overview
* @name ngSanitize
* @description
*/
/*
* HTML Parser By Misko Hevery (misko@hevery.com)
* based on: HTML Parser By John Resig (ejohn.org)
* Original code by Erik Arvidsson, Mozilla Public License
* http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
*
* // Use like so:
* htmlParser(htmlString, {
* start: function(tag, attrs, unary) {},
* end: function(tag) {},
* chars: function(text) {},
* comment: function(text) {}
* });
*
*/
/**
* @ngdoc service
* @name ngSanitize.$sanitize
* @function
*
* @description
* The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
* then serialized back to properly escaped html string. This means that no unsafe input can make
* it into the returned string, however, since our parser is more strict than a typical browser
* parser, it's possible that some obscure input, which would be recognized as valid HTML by a
* browser, won't make it through the sanitizer.
*
* @param {string} html Html input.
* @returns {string} Sanitized html.
*
* @example
<doc:example module="ngSanitize">
<doc:source>
<script>
function Ctrl($scope) {
$scope.snippet =
'<p style="color:blue">an html\n' +
'<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
'snippet</p>';
}
</script>
<div ng-controller="Ctrl">
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
<table>
<tr>
<td>Filter</td>
<td>Source</td>
<td>Rendered</td>
</tr>
<tr id="html-filter">
<td>html filter</td>
<td>
<pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre>
</td>
<td>
<div ng-bind-html="snippet"></div>
</td>
</tr>
<tr id="escaped-html">
<td>no filter</td>
<td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
<td><div ng-bind="snippet"></div></td>
</tr>
<tr id="html-unsafe-filter">
<td>unsafe html filter</td>
<td><pre>&lt;div ng-bind-html-unsafe="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
<td><div ng-bind-html-unsafe="snippet"></div></td>
</tr>
</table>
</div>
</doc:source>
<doc:scenario>
it('should sanitize the html snippet ', function() {
expect(using('#html-filter').element('div').html()).
toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
});
it('should escape snippet without any filter', function() {
expect(using('#escaped-html').element('div').html()).
toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
"&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
"snippet&lt;/p&gt;");
});
it('should inline raw snippet if filtered as unsafe', function() {
expect(using('#html-unsafe-filter').element("div").html()).
toBe("<p style=\"color:blue\">an html\n" +
"<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
"snippet</p>");
});
it('should update', function() {
input('snippet').enter('new <b>text</b>');
expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');
expect(using('#escaped-html').element('div').html()).toBe("new &lt;b&gt;text&lt;/b&gt;");
expect(using('#html-unsafe-filter').binding("snippet")).toBe('new <b>text</b>');
});
</doc:scenario>
</doc:example>
*/
var $sanitize = function(html) {
var buf = [];
htmlParser(html, htmlSanitizeWriter(buf));
return buf.join('');
};
// Regular Expressions for parsing tags and attributes
var START_TAG_REGEXP = /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,
END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/,
ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,
BEGIN_TAG_REGEXP = /^</,
BEGING_END_TAGE_REGEXP = /^<\s*\//,
COMMENT_REGEXP = /<!--(.*?)-->/g,
CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
URI_REGEXP = /^((ftp|https?):\/\/|mailto:|tel:|#)/,
NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Match everything outside of normal chars and " (quote character)
// Good source of info about elements and attributes
// http://dev.w3.org/html5/spec/Overview.html#semantics
// http://simon.html5.org/html-elements
// Safe Void Elements - HTML5
// http://dev.w3.org/html5/spec/Overview.html#void-elements
var voidElements = makeMap("area,br,col,hr,img,wbr");
// Elements that you can, intentionally, leave open (and which close themselves)
// http://dev.w3.org/html5/spec/Overview.html#optional-tags
var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
optionalEndTagInlineElements = makeMap("rp,rt"),
optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);
// Safe Block Elements - HTML5
var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article,aside," +
"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6," +
"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
// Inline Elements - HTML5
var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b,bdi,bdo," +
"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small," +
"span,strike,strong,sub,sup,time,tt,u,var"));
// Special Elements (can contain anything)
var specialElements = makeMap("script,style");
var validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);
//Attributes that have href and hence need to be sanitized
var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap");
var validAttrs = angular.extend({}, uriAttrs, makeMap(
'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+
'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+
'scope,scrolling,shape,span,start,summary,target,title,type,'+
'valign,value,vspace,width'));
function makeMap(str) {
var obj = {}, items = str.split(','), i;
for (i = 0; i < items.length; i++) obj[items[i]] = true;
return obj;
}
/**
* @example
* htmlParser(htmlString, {
* start: function(tag, attrs, unary) {},
* end: function(tag) {},
* chars: function(text) {},
* comment: function(text) {}
* });
*
* @param {string} html string
* @param {object} handler
*/
function htmlParser( html, handler ) {
var index, chars, match, stack = [], last = html;
stack.last = function() { return stack[ stack.length - 1 ]; };
while ( html ) {
chars = true;
// Make sure we're not in a script or style element
if ( !stack.last() || !specialElements[ stack.last() ] ) {
// Comment
if ( html.indexOf("<!--") === 0 ) {
index = html.indexOf("-->");
if ( index >= 0 ) {
if (handler.comment) handler.comment( html.substring( 4, index ) );
html = html.substring( index + 3 );
chars = false;
}
// end tag
} else if ( BEGING_END_TAGE_REGEXP.test(html) ) {
match = html.match( END_TAG_REGEXP );
if ( match ) {
html = html.substring( match[0].length );
match[0].replace( END_TAG_REGEXP, parseEndTag );
chars = false;
}
// start tag
} else if ( BEGIN_TAG_REGEXP.test(html) ) {
match = html.match( START_TAG_REGEXP );
if ( match ) {
html = html.substring( match[0].length );
match[0].replace( START_TAG_REGEXP, parseStartTag );
chars = false;
}
}
if ( chars ) {
index = html.indexOf("<");
var text = index < 0 ? html : html.substring( 0, index );
html = index < 0 ? "" : html.substring( index );
if (handler.chars) handler.chars( decodeEntities(text) );
}
} else {
html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), function(all, text){
text = text.
replace(COMMENT_REGEXP, "$1").
replace(CDATA_REGEXP, "$1");
if (handler.chars) handler.chars( decodeEntities(text) );
return "";
});
parseEndTag( "", stack.last() );
}
if ( html == last ) {
throw "Parse Error: " + html;
}
last = html;
}
// Clean up any remaining tags
parseEndTag();
function parseStartTag( tag, tagName, rest, unary ) {
tagName = angular.lowercase(tagName);
if ( blockElements[ tagName ] ) {
while ( stack.last() && inlineElements[ stack.last() ] ) {
parseEndTag( "", stack.last() );
}
}
if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {
parseEndTag( "", tagName );
}
unary = voidElements[ tagName ] || !!unary;
if ( !unary )
stack.push( tagName );
var attrs = {};
rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {
var value = doubleQuotedValue
|| singleQoutedValue
|| unqoutedValue
|| '';
attrs[name] = decodeEntities(value);
});
if (handler.start) handler.start( tagName, attrs, unary );
}
function parseEndTag( tag, tagName ) {
var pos = 0, i;
tagName = angular.lowercase(tagName);
if ( tagName )
// Find the closest opened tag of the same type
for ( pos = stack.length - 1; pos >= 0; pos-- )
if ( stack[ pos ] == tagName )
break;
if ( pos >= 0 ) {
// Close all the open elements, up the stack
for ( i = stack.length - 1; i >= pos; i-- )
if (handler.end) handler.end( stack[ i ] );
// Remove the open elements from the stack
stack.length = pos;
}
}
}
/**
* decodes all entities into regular string
* @param value
* @returns {string} A string with decoded entities.
*/
var hiddenPre=document.createElement("pre");
function decodeEntities(value) {
hiddenPre.innerHTML=value.replace(/</g,"&lt;");
return hiddenPre.innerText || hiddenPre.textContent || '';
}
/**
* Escapes all potentially dangerous characters, so that the
* resulting string can be safely inserted into attribute or
* element text.
* @param value
* @returns escaped text
*/
function encodeEntities(value) {
return value.
replace(/&/g, '&amp;').
replace(NON_ALPHANUMERIC_REGEXP, function(value){
return '&#' + value.charCodeAt(0) + ';';
}).
replace(/</g, '&lt;').
replace(/>/g, '&gt;');
}
/**
* create an HTML/XML writer which writes to buffer
* @param {Array} buf use buf.jain('') to get out sanitized html string
* @returns {object} in the form of {
* start: function(tag, attrs, unary) {},
* end: function(tag) {},
* chars: function(text) {},
* comment: function(text) {}
* }
*/
function htmlSanitizeWriter(buf){
var ignore = false;
var out = angular.bind(buf, buf.push);
return {
start: function(tag, attrs, unary){
tag = angular.lowercase(tag);
if (!ignore && specialElements[tag]) {
ignore = tag;
}
if (!ignore && validElements[tag] == true) {
out('<');
out(tag);
angular.forEach(attrs, function(value, key){
var lkey=angular.lowercase(key);
if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {
out(' ');
out(key);
out('="');
out(encodeEntities(value));
out('"');
}
});
out(unary ? '/>' : '>');
}
},
end: function(tag){
tag = angular.lowercase(tag);
if (!ignore && validElements[tag] == true) {
out('</');
out(tag);
out('>');
}
if (tag == ignore) {
ignore = false;
}
},
chars: function(chars){
if (!ignore) {
out(encodeEntities(chars));
}
}
};
}
// define ngSanitize module and register $sanitize service
angular.module('ngSanitize', []).value('$sanitize', $sanitize);
/**
* @ngdoc directive
* @name ngSanitize.directive:ngBindHtml
*
* @description
* Creates a binding that will sanitize the result of evaluating the `expression` with the
* {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.
*
* See {@link ngSanitize.$sanitize $sanitize} docs for examples.
*
* @element ANY
* @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
*/
angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {
return function(scope, element, attr) {
element.addClass('ng-binding').data('$binding', attr.ngBindHtml);
scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {
value = $sanitize(value);
element.html(value || '');
});
};
}]);
/**
* @ngdoc filter
* @name ngSanitize.filter:linky
* @function
*
* @description
* Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
* plain email address links.
*
* @param {string} text Input text.
* @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.
* @returns {string} Html-linkified text.
*
* @usage
<span ng-bind-html="linky_expression | linky"></span>
*
* @example
<doc:example module="ngSanitize">
<doc:source>
<script>
function Ctrl($scope) {
$scope.snippet =
'Pretty text with some links:\n'+
'http://angularjs.org/,\n'+
'mailto:us@somewhere.org,\n'+
'another@somewhere.org,\n'+
'and one more: ftp://127.0.0.1/.';
$scope.snippetWithTarget = 'http://angularjs.org/';
}
</script>
<div ng-controller="Ctrl">
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
<table>
<tr>
<td>Filter</td>
<td>Source</td>
<td>Rendered</td>
</tr>
<tr id="linky-filter">
<td>linky filter</td>
<td>
<pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
</td>
<td>
<div ng-bind-html="snippet | linky"></div>
</td>
</tr>
<tr id="linky-target">
<td>linky target</td>
<td>
<pre>&lt;div ng-bind-html="snippetWithTarget | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
</td>
<td>
<div ng-bind-html="snippetWithTarget | linky:'_blank'"></div>
</td>
</tr>
<tr id="escaped-html">
<td>no filter</td>
<td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
<td><div ng-bind="snippet"></div></td>
</tr>
</table>
</doc:source>
<doc:scenario>
it('should linkify the snippet with urls', function() {
expect(using('#linky-filter').binding('snippet | linky')).
toBe('Pretty text with some links:&#10;' +
'<a href="http://angularjs.org/">http://angularjs.org/</a>,&#10;' +
'<a href="mailto:us@somewhere.org">us@somewhere.org</a>,&#10;' +
'<a href="mailto:another@somewhere.org">another@somewhere.org</a>,&#10;' +
'and one more: <a href="ftp://127.0.0.1/">ftp://127.0.0.1/</a>.');
});
it ('should not linkify snippet without the linky filter', function() {
expect(using('#escaped-html').binding('snippet')).
toBe("Pretty text with some links:\n" +
"http://angularjs.org/,\n" +
"mailto:us@somewhere.org,\n" +
"another@somewhere.org,\n" +
"and one more: ftp://127.0.0.1/.");
});
it('should update', function() {
input('snippet').enter('new http://link.');
expect(using('#linky-filter').binding('snippet | linky')).
toBe('new <a href="http://link">http://link</a>.');
expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
});
it('should work with the target property', function() {
expect(using('#linky-target').binding("snippetWithTarget | linky:'_blank'")).
toBe('<a target="_blank" href="http://angularjs.org/">http://angularjs.org/</a>');
});
</doc:scenario>
</doc:example>
*/
angular.module('ngSanitize').filter('linky', function() {
var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,
MAILTO_REGEXP = /^mailto:/;
return function(text, target) {
if (!text) return text;
var match;
var raw = text;
var html = [];
// TODO(vojta): use $sanitize instead
var writer = htmlSanitizeWriter(html);
var url;
var i;
var properties = {};
if (angular.isDefined(target)) {
properties.target = target;
}
while ((match = raw.match(LINKY_URL_REGEXP))) {
// We can not end in these as they are sometimes found at the end of the sentence
url = match[0];
// if we did not match ftp/http/mailto then assume mailto
if (match[2] == match[3]) url = 'mailto:' + url;
i = match.index;
writer.chars(raw.substr(0, i));
properties.href = url;
writer.start('a', properties);
writer.chars(match[0].replace(MAILTO_REGEXP, ''));
writer.end('a');
raw = raw.substring(i + match[0].length);
}
writer.chars(raw);
return html.join('');
};
});
})(window, window.angular);

View File

@ -0,0 +1,13 @@
/*
AngularJS v1.1.4
(c) 2010-2012 Google, Inc. http://angularjs.org
License: MIT
*/
(function(I,h){'use strict';function i(a){var d={},a=a.split(","),c;for(c=0;c<a.length;c++)d[a[c]]=!0;return d}function z(a,d){function c(a,b,c,f){b=h.lowercase(b);if(m[b])for(;e.last()&&n[e.last()];)g("",e.last());o[b]&&e.last()==b&&g("",b);(f=p[b]||!!f)||e.push(b);var j={};c.replace(A,function(a,b,d,c,g){j[b]=k(d||c||g||"")});d.start&&d.start(b,j,f)}function g(a,b){var c=0,g;if(b=h.lowercase(b))for(c=e.length-1;c>=0;c--)if(e[c]==b)break;if(c>=0){for(g=e.length-1;g>=c;g--)d.end&&d.end(e[g]);e.length=
c}}var b,f,e=[],j=a;for(e.last=function(){return e[e.length-1]};a;){f=!0;if(!e.last()||!q[e.last()]){if(a.indexOf("<\!--")===0)b=a.indexOf("--\>"),b>=0&&(d.comment&&d.comment(a.substring(4,b)),a=a.substring(b+3),f=!1);else if(B.test(a)){if(b=a.match(r))a=a.substring(b[0].length),b[0].replace(r,g),f=!1}else if(C.test(a)&&(b=a.match(s)))a=a.substring(b[0].length),b[0].replace(s,c),f=!1;f&&(b=a.indexOf("<"),f=b<0?a:a.substring(0,b),a=b<0?"":a.substring(b),d.chars&&d.chars(k(f)))}else a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+
e.last()+"[^>]*>","i"),function(a,b){b=b.replace(D,"$1").replace(E,"$1");d.chars&&d.chars(k(b));return""}),g("",e.last());if(a==j)throw"Parse Error: "+a;j=a}g()}function k(a){l.innerHTML=a.replace(/</g,"&lt;");return l.innerText||l.textContent||""}function t(a){return a.replace(/&/g,"&amp;").replace(F,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"&lt;").replace(/>/g,"&gt;")}function u(a){var d=!1,c=h.bind(a,a.push);return{start:function(a,b,f){a=h.lowercase(a);!d&&q[a]&&(d=a);!d&&v[a]==
!0&&(c("<"),c(a),h.forEach(b,function(a,b){var d=h.lowercase(b);if(G[d]==!0&&(w[d]!==!0||a.match(H)))c(" "),c(b),c('="'),c(t(a)),c('"')}),c(f?"/>":">"))},end:function(a){a=h.lowercase(a);!d&&v[a]==!0&&(c("</"),c(a),c(">"));a==d&&(d=!1)},chars:function(a){d||c(t(a))}}}var s=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,r=/^<\s*\/\s*([\w:-]+)[^>]*>/,A=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,C=/^</,B=/^<\s*\//,D=/<\!--(.*?)--\>/g,
E=/<!\[CDATA\[(.*?)]]\>/g,H=/^((ftp|https?):\/\/|mailto:|tel:|#)/,F=/([^\#-~| |!])/g,p=i("area,br,col,hr,img,wbr"),x=i("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),y=i("rp,rt"),o=h.extend({},y,x),m=h.extend({},x,i("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),n=h.extend({},y,i("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")),
q=i("script,style"),v=h.extend({},p,m,n,o),w=i("background,cite,href,longdesc,src,usemap"),G=h.extend({},w,i("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,span,start,summary,target,title,type,valign,value,vspace,width")),l=document.createElement("pre");h.module("ngSanitize",[]).value("$sanitize",function(a){var d=[];
z(a,u(d));return d.join("")});h.module("ngSanitize").directive("ngBindHtml",["$sanitize",function(a){return function(d,c,g){c.addClass("ng-binding").data("$binding",g.ngBindHtml);d.$watch(g.ngBindHtml,function(b){b=a(b);c.html(b||"")})}}]);h.module("ngSanitize").filter("linky",function(){var a=/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,d=/^mailto:/;return function(c,g){if(!c)return c;var b,f=c,e=[],j=u(e),i,k,l={};if(h.isDefined(g))l.target=g;for(;b=f.match(a);)i=
b[0],b[2]==b[3]&&(i="mailto:"+i),k=b.index,j.chars(f.substr(0,k)),l.href=i,j.start("a",l),j.chars(b[0].replace(d,"")),j.end("a"),f=f.substring(k+b[0].length);j.chars(f);return e.join("")}})})(window,window.angular);

27862
lib/ui/static/lib/angular/angular-scenario.js vendored Executable file

File diff suppressed because it is too large Load Diff

16314
lib/ui/static/lib/angular/angular.js vendored Executable file

File diff suppressed because it is too large Load Diff

173
lib/ui/static/lib/angular/angular.min.js vendored Executable file
View File

@ -0,0 +1,173 @@
/*
AngularJS v1.1.4
(c) 2010-2012 Google, Inc. http://angularjs.org
License: MIT
*/
(function(M,V,s){'use strict';function gc(){var b=M.angular;M.angular=hc;return b}function o(b,a,c){var d;if(b)if(I(b))for(d in b)d!="prototype"&&d!="length"&&d!="name"&&b.hasOwnProperty(d)&&a.call(c,b[d],d);else if(b.forEach&&b.forEach!==o)b.forEach(a,c);else if(!b||typeof b.length!=="number"?0:typeof b.hasOwnProperty!="function"&&typeof b.constructor!="function"||b instanceof P||ca&&b instanceof ca||Da.call(b)!=="[object Object]"||typeof b.callee==="function")for(d=0;d<b.length;d++)a.call(c,b[d],
d);else for(d in b)b.hasOwnProperty(d)&&a.call(c,b[d],d);return b}function rb(b){var a=[],c;for(c in b)b.hasOwnProperty(c)&&a.push(c);return a.sort()}function ic(b,a,c){for(var d=rb(b),e=0;e<d.length;e++)a.call(c,b[d[e]],d[e]);return d}function sb(b){return function(a,c){b(c,a)}}function Ea(){for(var b=Z.length,a;b;){b--;a=Z[b].charCodeAt(0);if(a==57)return Z[b]="A",Z.join("");if(a==90)Z[b]="0";else return Z[b]=String.fromCharCode(a+1),Z.join("")}Z.unshift("0");return Z.join("")}function y(b){o(arguments,
function(a){a!==b&&o(a,function(a,d){b[d]=a})});return b}function K(b){return parseInt(b,10)}function Fa(b,a){return y(new (y(function(){},{prototype:b})),a)}function t(){}function pa(b){return b}function Q(b){return function(){return b}}function u(b){return typeof b=="undefined"}function w(b){return typeof b!="undefined"}function L(b){return b!=null&&typeof b=="object"}function x(b){return typeof b=="string"}function Za(b){return typeof b=="number"}function qa(b){return Da.apply(b)=="[object Date]"}
function C(b){return Da.apply(b)=="[object Array]"}function I(b){return typeof b=="function"}function ra(b){return b&&b.document&&b.location&&b.alert&&b.setInterval}function S(b){return x(b)?b.replace(/^\s*/,"").replace(/\s*$/,""):b}function jc(b){return b&&(b.nodeName||b.bind&&b.find)}function $a(b,a,c){var d=[];o(b,function(b,f,i){d.push(a.call(c,b,f,i))});return d}function Ga(b,a){if(b.indexOf)return b.indexOf(a);for(var c=0;c<b.length;c++)if(a===b[c])return c;return-1}function sa(b,a){var c=Ga(b,
a);c>=0&&b.splice(c,1);return a}function W(b,a){if(ra(b)||b&&b.$evalAsync&&b.$watch)throw Error("Can't copy Window or Scope");if(a){if(b===a)throw Error("Can't copy equivalent objects or arrays");if(C(b))for(var c=a.length=0;c<b.length;c++)a.push(W(b[c]));else for(c in o(a,function(b,c){delete a[c]}),b)a[c]=W(b[c])}else(a=b)&&(C(b)?a=W(b,[]):qa(b)?a=new Date(b.getTime()):L(b)&&(a=W(b,{})));return a}function kc(b,a){var a=a||{},c;for(c in b)b.hasOwnProperty(c)&&c.substr(0,2)!=="$$"&&(a[c]=b[c]);return a}
function ja(b,a){if(b===a)return!0;if(b===null||a===null)return!1;if(b!==b&&a!==a)return!0;var c=typeof b,d;if(c==typeof a&&c=="object")if(C(b)){if((c=b.length)==a.length){for(d=0;d<c;d++)if(!ja(b[d],a[d]))return!1;return!0}}else if(qa(b))return qa(a)&&b.getTime()==a.getTime();else{if(b&&b.$evalAsync&&b.$watch||a&&a.$evalAsync&&a.$watch||ra(b)||ra(a))return!1;c={};for(d in b)if(!(d.charAt(0)==="$"||I(b[d]))){if(!ja(b[d],a[d]))return!1;c[d]=!0}for(d in a)if(!c[d]&&d.charAt(0)!=="$"&&a[d]!==s&&!I(a[d]))return!1;
return!0}return!1}function ab(b,a){var c=arguments.length>2?ka.call(arguments,2):[];return I(a)&&!(a instanceof RegExp)?c.length?function(){return arguments.length?a.apply(b,c.concat(ka.call(arguments,0))):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}:a}function lc(b,a){var c=a;/^\$+/.test(b)?c=s:ra(a)?c="$WINDOW":a&&V===a?c="$DOCUMENT":a&&a.$evalAsync&&a.$watch&&(c="$SCOPE");return c}function da(b,a){return JSON.stringify(b,lc,a?" ":null)}function tb(b){return x(b)?
JSON.parse(b):b}function Ha(b){b&&b.length!==0?(b=J(""+b),b=!(b=="f"||b=="0"||b=="false"||b=="no"||b=="n"||b=="[]")):b=!1;return b}function ta(b){b=v(b).clone();try{b.html("")}catch(a){}var c=v("<div>").append(b).html();try{return b[0].nodeType===3?J(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+J(b)})}catch(d){return J(c)}}function bb(b){var a={},c,d;o((b||"").split("&"),function(b){b&&(c=b.split("="),d=decodeURIComponent(c[0]),a[d]=w(c[1])?decodeURIComponent(c[1]):!0)});
return a}function ub(b){var a=[];o(b,function(b,d){a.push(ua(d,!0)+(b===!0?"":"="+ua(b,!0)))});return a.length?a.join("&"):""}function cb(b){return ua(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function ua(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,a?"%20":"+")}function mc(b,a){function c(a){a&&d.push(a)}var d=[b],e,f,i=["ng:app","ng-app","x-ng-app","data-ng-app"],h=/\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;
o(i,function(a){i[a]=!0;c(V.getElementById(a));a=a.replace(":","\\:");b.querySelectorAll&&(o(b.querySelectorAll("."+a),c),o(b.querySelectorAll("."+a+"\\:"),c),o(b.querySelectorAll("["+a+"]"),c))});o(d,function(a){if(!e){var b=h.exec(" "+a.className+" ");b?(e=a,f=(b[2]||"").replace(/\s+/g,",")):o(a.attributes,function(b){if(!e&&i[b.name])e=a,f=b.value})}});e&&a(e,f?[f]:[])}function vb(b,a){var c=function(){b=v(b);a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);a.unshift("ng");
var c=wb(a);c.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return c},d=/^NG_DEFER_BOOTSTRAP!/;if(M&&!d.test(M.name))return c();M.name=M.name.replace(d,"");Ia.resumeBootstrap=function(b){o(b,function(b){a.push(b)});c()}}function db(b,a){a=a||"_";return b.replace(nc,function(b,d){return(d?a:"")+b.toLowerCase()})}function eb(b,a,c){if(!b)throw Error("Argument '"+(a||"?")+"' is "+(c||"required"));return b}function va(b,
a,c){c&&C(b)&&(b=b[b.length-1]);eb(I(b),a,"not a function, got "+(b&&typeof b=="object"?b.constructor.name||"Object":typeof b));return b}function oc(b){function a(a,b,e){return a[b]||(a[b]=e())}return a(a(b,"angular",Object),"module",function(){var b={};return function(d,e,f){e&&b.hasOwnProperty(d)&&(b[d]=null);return a(b,d,function(){function a(c,d,e){return function(){b[e||"push"]([c,d,arguments]);return m}}if(!e)throw Error("No module: "+d);var b=[],c=[],g=a("$injector","invoke"),m={_invokeQueue:b,
_runBlocks:c,requires:e,name:d,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),animation:a("$animationProvider","register"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:g,run:function(a){c.push(a);return this}};f&&g(f);return m})}})}function Ja(b){return b.replace(pc,function(a,b,d,e){return e?
d.toUpperCase():d}).replace(qc,"Moz$1")}function fb(b,a){function c(){var e;for(var b=[this],c=a,i,h,j,g,m,k;b.length;){i=b.shift();h=0;for(j=i.length;h<j;h++){g=v(i[h]);c?g.triggerHandler("$destroy"):c=!c;m=0;for(e=(k=g.children()).length,g=e;m<g;m++)b.push(ca(k[m]))}}return d.apply(this,arguments)}var d=ca.fn[b],d=d.$original||d;c.$original=d;ca.fn[b]=c}function P(b){if(b instanceof P)return b;if(!(this instanceof P)){if(x(b)&&b.charAt(0)!="<")throw Error("selectors not implemented");return new P(b)}if(x(b)){var a=
V.createElement("div");a.innerHTML="<div>&#160;</div>"+b;a.removeChild(a.firstChild);gb(this,a.childNodes);this.remove()}else gb(this,b)}function hb(b){return b.cloneNode(!0)}function wa(b){xb(b);for(var a=0,b=b.childNodes||[];a<b.length;a++)wa(b[a])}function yb(b,a,c){var d=$(b,"events");$(b,"handle")&&(u(a)?o(d,function(a,c){ib(b,c,a);delete d[c]}):u(c)?(ib(b,a,d[a]),delete d[a]):sa(d[a],c))}function xb(b){var a=b[Ka],c=La[a];c&&(c.handle&&(c.events.$destroy&&c.handle({},"$destroy"),yb(b)),delete La[a],
b[Ka]=s)}function $(b,a,c){var d=b[Ka],d=La[d||-1];if(w(c))d||(b[Ka]=d=++rc,d=La[d]={}),d[a]=c;else return d&&d[a]}function zb(b,a,c){var d=$(b,"data"),e=w(c),f=!e&&w(a),i=f&&!L(a);!d&&!i&&$(b,"data",d={});if(e)d[a]=c;else if(f)if(i)return d&&d[a];else y(d,a);else return d}function Ma(b,a){return(" "+b.className+" ").replace(/[\n\t]/g," ").indexOf(" "+a+" ")>-1}function Ab(b,a){a&&o(a.split(" "),function(a){b.className=S((" "+b.className+" ").replace(/[\n\t]/g," ").replace(" "+S(a)+" "," "))})}function Bb(b,
a){a&&o(a.split(" "),function(a){if(!Ma(b,a))b.className=S(b.className+" "+S(a))})}function gb(b,a){if(a)for(var a=!a.nodeName&&w(a.length)&&!ra(a)?a:[a],c=0;c<a.length;c++)b.push(a[c])}function Cb(b,a){return Na(b,"$"+(a||"ngController")+"Controller")}function Na(b,a,c){b=v(b);for(b[0].nodeType==9&&(b=b.find("html"));b.length;){if(c=b.data(a))return c;b=b.parent()}}function Db(b,a){var c=Oa[a.toLowerCase()];return c&&Eb[b.nodeName]&&c}function sc(b,a){var c=function(c,e){if(!c.preventDefault)c.preventDefault=
function(){c.returnValue=!1};if(!c.stopPropagation)c.stopPropagation=function(){c.cancelBubble=!0};if(!c.target)c.target=c.srcElement||V;if(u(c.defaultPrevented)){var f=c.preventDefault;c.preventDefault=function(){c.defaultPrevented=!0;f.call(c)};c.defaultPrevented=!1}c.isDefaultPrevented=function(){return c.defaultPrevented};o(a[e||c.type],function(a){a.call(b,c)});X<=8?(c.preventDefault=null,c.stopPropagation=null,c.isDefaultPrevented=null):(delete c.preventDefault,delete c.stopPropagation,delete c.isDefaultPrevented)};
c.elem=b;return c}function la(b){var a=typeof b,c;if(a=="object"&&b!==null)if(typeof(c=b.$$hashKey)=="function")c=b.$$hashKey();else{if(c===s)c=b.$$hashKey=Ea()}else c=b;return a+":"+c}function Pa(b){o(b,this.put,this)}function Fb(b){var a,c;if(typeof b=="function"){if(!(a=b.$inject))a=[],c=b.toString().replace(tc,""),c=c.match(uc),o(c[1].split(vc),function(b){b.replace(wc,function(b,c,d){a.push(d)})}),b.$inject=a}else C(b)?(c=b.length-1,va(b[c],"fn"),a=b.slice(0,c)):va(b,"fn",!0);return a}function wb(b){function a(a){return function(b,
c){if(L(b))o(b,sb(a));else return a(b,c)}}function c(a,b){if(I(b)||C(b))b=k.instantiate(b);if(!b.$get)throw Error("Provider "+a+" must define $get factory method.");return m[a+h]=b}function d(a,b){return c(a,{$get:b})}function e(a){var b=[];o(a,function(a){if(!g.get(a))if(g.put(a,!0),x(a)){var c=xa(a);b=b.concat(e(c.requires)).concat(c._runBlocks);try{for(var d=c._invokeQueue,c=0,h=d.length;c<h;c++){var f=d[c],n=k.get(f[0]);n[f[1]].apply(n,f[2])}}catch(j){throw j.message&&(j.message+=" from "+a),
j;}}else if(I(a))try{b.push(k.invoke(a))}catch(i){throw i.message&&(i.message+=" from "+a),i;}else if(C(a))try{b.push(k.invoke(a))}catch(l){throw l.message&&(l.message+=" from "+String(a[a.length-1])),l;}else va(a,"module")});return b}function f(a,b){function c(d){if(typeof d!=="string")throw Error("Service name expected");if(a.hasOwnProperty(d)){if(a[d]===i)throw Error("Circular dependency: "+j.join(" <- "));return a[d]}else try{return j.unshift(d),a[d]=i,a[d]=b(d)}finally{j.shift()}}function d(a,
b,e){var g=[],h=Fb(a),f,j,n;j=0;for(f=h.length;j<f;j++)n=h[j],g.push(e&&e.hasOwnProperty(n)?e[n]:c(n));a.$inject||(a=a[f]);switch(b?-1:g.length){case 0:return a();case 1:return a(g[0]);case 2:return a(g[0],g[1]);case 3:return a(g[0],g[1],g[2]);case 4:return a(g[0],g[1],g[2],g[3]);case 5:return a(g[0],g[1],g[2],g[3],g[4]);case 6:return a(g[0],g[1],g[2],g[3],g[4],g[5]);case 7:return a(g[0],g[1],g[2],g[3],g[4],g[5],g[6]);case 8:return a(g[0],g[1],g[2],g[3],g[4],g[5],g[6],g[7]);case 9:return a(g[0],g[1],
g[2],g[3],g[4],g[5],g[6],g[7],g[8]);case 10:return a(g[0],g[1],g[2],g[3],g[4],g[5],g[6],g[7],g[8],g[9]);default:return a.apply(b,g)}}return{invoke:d,instantiate:function(a,b){var c=function(){},e;c.prototype=(C(a)?a[a.length-1]:a).prototype;c=new c;e=d(a,c,b);return L(e)?e:c},get:c,annotate:Fb}}var i={},h="Provider",j=[],g=new Pa,m={$provide:{provider:a(c),factory:a(d),service:a(function(a,b){return d(a,["$injector",function(a){return a.instantiate(b)}])}),value:a(function(a,b){return d(a,Q(b))}),
constant:a(function(a,b){m[a]=b;l[a]=b}),decorator:function(a,b){var c=k.get(a+h),d=c.$get;c.$get=function(){var a=q.invoke(d,c);return q.invoke(b,null,{$delegate:a})}}}},k=m.$injector=f(m,function(){throw Error("Unknown provider: "+j.join(" <- "));}),l={},q=l.$injector=f(l,function(a){a=k.get(a+h);return q.invoke(a.$get,a)});o(e(b),function(a){q.invoke(a||t)});return q}function xc(){var b=!0;this.disableAutoScrolling=function(){b=!1};this.$get=["$window","$location","$rootScope",function(a,c,d){function e(a){var b=
null;o(a,function(a){!b&&J(a.nodeName)==="a"&&(b=a)});return b}function f(){var b=c.hash(),d;b?(d=i.getElementById(b))?d.scrollIntoView():(d=e(i.getElementsByName(b)))?d.scrollIntoView():b==="top"&&a.scrollTo(0,0):a.scrollTo(0,0)}var i=a.document;b&&d.$watch(function(){return c.hash()},function(){d.$evalAsync(f)});return f}]}function Gb(b){this.register=function(a,c){b.factory(Ja(a)+"Animation",c)};this.$get=["$injector",function(a){return function(b){if(b)try{return a.get(Ja(b)+"Animation")}catch(d){}}}]}
function yc(b,a,c,d){function e(a){try{a.apply(null,ka.call(arguments,1))}finally{if(n--,n===0)for(;B.length;)try{B.pop()()}catch(b){c.error(b)}}}function f(a,b){(function z(){o(r,function(a){a()});p=b(z,a)})()}function i(){E!=h.url()&&(E=h.url(),o(G,function(a){a(h.url())}))}var h=this,j=a[0],g=b.location,m=b.history,k=b.setTimeout,l=b.clearTimeout,q={};h.isMock=!1;var n=0,B=[];h.$$completeOutstandingRequest=e;h.$$incOutstandingRequestCount=function(){n++};h.notifyWhenNoOutstandingRequests=function(a){o(r,
function(a){a()});n===0?a():B.push(a)};var r=[],p;h.addPollFn=function(a){u(p)&&f(100,k);r.push(a);return a};var E=g.href,D=a.find("base");h.url=function(a,b){if(a){if(E!=a)return E=a,d.history?b?m.replaceState(null,"",a):(m.pushState(null,"",a),D.attr("href",D.attr("href"))):b?g.replace(a):g.href=a,h}else return g.href.replace(/%27/g,"'")};var G=[],R=!1;h.onUrlChange=function(a){R||(d.history&&v(b).bind("popstate",i),d.hashchange?v(b).bind("hashchange",i):h.addPollFn(i),R=!0);G.push(a);return a};
h.baseHref=function(){var a=D.attr("href");return a?a.replace(/^https?\:\/\/[^\/]*/,""):""};var A={},H="",F=h.baseHref();h.cookies=function(a,b){var d,e,g,h;if(a)if(b===s)j.cookie=escape(a)+"=;path="+F+";expires=Thu, 01 Jan 1970 00:00:00 GMT";else{if(x(b))d=(j.cookie=escape(a)+"="+escape(b)+";path="+F).length+1,d>4096&&c.warn("Cookie '"+a+"' possibly not set or overflowed because it was too large ("+d+" > 4096 bytes)!")}else{if(j.cookie!==H){H=j.cookie;d=H.split("; ");A={};for(g=0;g<d.length;g++)e=
d[g],h=e.indexOf("="),h>0&&(A[unescape(e.substring(0,h))]=unescape(e.substring(h+1)))}return A}};h.defer=function(a,b){var c;n++;c=k(function(){delete q[c];e(a)},b||0);q[c]=!0;return c};h.defer.cancel=function(a){return q[a]?(delete q[a],l(a),e(t),!0):!1}}function zc(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new yc(b,d,a,c)}]}function Ac(){this.$get=function(){function b(b,d){function e(a){if(a!=k){if(l){if(l==a)l=a.n}else l=a;f(a.n,a.p);f(a,k);k=a;k.n=null}}function f(a,
b){if(a!=b){if(a)a.p=b;if(b)b.n=a}}if(b in a)throw Error("cacheId "+b+" taken");var i=0,h=y({},d,{id:b}),j={},g=d&&d.capacity||Number.MAX_VALUE,m={},k=null,l=null;return a[b]={put:function(a,b){var c=m[a]||(m[a]={key:a});e(c);if(!u(b))return a in j||i++,j[a]=b,i>g&&this.remove(l.key),b},get:function(a){var b=m[a];if(b)return e(b),j[a]},remove:function(a){var b=m[a];if(b){if(b==k)k=b.p;if(b==l)l=b.n;f(b.n,b.p);delete m[a];delete j[a];i--}},removeAll:function(){j={};i=0;m={};k=l=null},destroy:function(){m=
h=j=null;delete a[b]},info:function(){return y({},h,{size:i})}}}var a={};b.info=function(){var b={};o(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]};return b}}function Bc(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function Hb(b){var a={},c="Directive",d=/^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,e=/(([\d\w\-_]+)(?:\:([^;]+))?;?)/,f="Template must have exactly one root element. was: ",i=/^\s*(https?|ftp|mailto|file):/;this.directive=function j(d,e){x(d)?
(eb(e,"directive"),a.hasOwnProperty(d)||(a[d]=[],b.factory(d+c,["$injector","$exceptionHandler",function(b,c){var e=[];o(a[d],function(a){try{var f=b.invoke(a);if(I(f))f={compile:Q(f)};else if(!f.compile&&f.link)f.compile=Q(f.link);f.priority=f.priority||0;f.name=f.name||d;f.require=f.require||f.controller&&f.name;f.restrict=f.restrict||"A";e.push(f)}catch(j){c(j)}});return e}])),a[d].push(e)):o(d,sb(j));return this};this.urlSanitizationWhitelist=function(a){return w(a)?(i=a,this):i};this.$get=["$injector",
"$interpolate","$exceptionHandler","$http","$templateCache","$parse","$controller","$rootScope","$document",function(b,g,m,k,l,q,n,B,r){function p(a,b,c){a instanceof v||(a=v(a));o(a,function(b,c){b.nodeType==3&&b.nodeValue.match(/\S+/)&&(a[c]=v(b).wrap("<span></span>").parent()[0])});var d=D(a,b,a,c);return function(b,c){eb(b,"scope");for(var e=c?za.clone.call(a):a,g=0,f=e.length;g<f;g++){var j=e[g];(j.nodeType==1||j.nodeType==9)&&e.eq(g).data("$scope",b)}E(e,"ng-scope");c&&c(e,b);d&&d(b,e,e);return e}}
function E(a,b){try{a.addClass(b)}catch(c){}}function D(a,b,c,d){function e(a,c,d,f){var j,i,l,m,n,k,q,p=[];n=0;for(k=c.length;n<k;n++)p.push(c[n]);q=n=0;for(k=g.length;n<k;q++)i=p[q],c=g[n++],j=g[n++],c?(c.scope?(l=a.$new(L(c.scope)),v(i).data("$scope",l)):l=a,(m=c.transclude)||!f&&b?c(j,l,i,d,function(b){return function(c){var d=a.$new();d.$$transcluded=!0;return b(d,c).bind("$destroy",ab(d,d.$destroy))}}(m||b)):c(j,l,i,s,f)):j&&j(a,i.childNodes,s,f)}for(var g=[],f,j,i,l=0;l<a.length;l++)j=new ya,
f=G(a[l],[],j,d),j=(f=f.length?R(f,a[l],j,b,c):null)&&f.terminal||!a[l].childNodes||!a[l].childNodes.length?null:D(a[l].childNodes,f?f.transclude:b),g.push(f),g.push(j),i=i||f||j;return i?e:null}function G(a,b,c,g){var f=c.$attr,j;switch(a.nodeType){case 1:A(b,aa(jb(a).toLowerCase()),"E",g);var i,l,n;j=a.attributes;for(var m=0,k=j&&j.length;m<k;m++)if(i=j[m],i.specified)l=i.name,n=aa(l),ha.test(n)&&(l=n.substr(6).toLowerCase()),n=aa(l.toLowerCase()),f[n]=l,c[n]=i=S(X&&l=="href"?decodeURIComponent(a.getAttribute(l,
2)):i.value),Db(a,n)&&(c[n]=!0),z(a,b,i,n),A(b,n,"A",g);a=a.className;if(x(a)&&a!=="")for(;j=e.exec(a);)n=aa(j[2]),A(b,n,"C",g)&&(c[n]=S(j[3])),a=a.substr(j.index+j[0].length);break;case 3:ga(b,a.nodeValue);break;case 8:try{if(j=d.exec(a.nodeValue))n=aa(j[1]),A(b,n,"M",g)&&(c[n]=S(j[2]))}catch(q){}}b.sort(N);return b}function R(a,b,c,d,e){function j(a,b){if(a)a.require=z.require,B.push(a);if(b)b.require=z.require,r.push(b)}function i(a,b){var c,d="data",e=!1;if(x(a)){for(;(c=a.charAt(0))=="^"||c==
"?";)a=a.substr(1),c=="^"&&(d="inheritedData"),e=e||c=="?";c=b[d]("$"+a+"Controller");if(!c&&!e)throw Error("No controller: "+a);}else C(a)&&(c=[],o(a,function(a){c.push(i(a,b))}));return c}function l(a,d,e,f,j){var k,p,D,G,H;k=b===e?c:kc(c,new ya(v(e),c.$attr));p=k.$$element;if(ba){var z=/^\s*([@=&])(\??)\s*(\w*)\s*$/,F=d.$parent||d;o(ba.scope,function(a,b){var c=a.match(z)||[],e=c[3]||b,f=c[2]=="?",c=c[1],j,l,i;d.$$isolateBindings[b]=c+e;switch(c){case "@":k.$observe(e,function(a){d[b]=a});k.$$observers[e].$$scope=
F;k[e]&&(d[b]=g(k[e])(F));break;case "=":if(f&&!k[e])break;l=q(k[e]);i=l.assign||function(){j=d[b]=l(F);throw Error(Ib+k[e]+" (directive: "+ba.name+")");};j=d[b]=l(F);d.$watch(function(){var a=l(F);a!==d[b]&&(a!==j?j=d[b]=a:i(F,a=j=d[b]));return a});break;case "&":l=q(k[e]);d[b]=function(a){return l(F,a)};break;default:throw Error("Invalid isolate scope definition for directive "+ba.name+": "+a);}})}ha&&o(ha,function(a){var b={$scope:d,$element:p,$attrs:k,$transclude:j};H=a.controller;H=="@"&&(H=
k[a.name]);p.data("$"+a.name+"Controller",n(H,b))});f=0;for(D=B.length;f<D;f++)try{G=B[f],G(d,p,k,G.require&&i(G.require,p))}catch(E){m(E,ta(p))}a&&a(d,e.childNodes,s,j);f=0;for(D=r.length;f<D;f++)try{G=r[f],G(d,p,k,G.require&&i(G.require,p))}catch(N){m(N,ta(p))}}for(var k=-Number.MAX_VALUE,B=[],r=[],D=null,ba=null,N=null,A=c.$$element=v(b),z,T,R,ga,ia=d,ha,t,y,w=0,u=a.length;w<u;w++){z=a[w];R=s;if(k>z.priority)break;if(y=z.scope)ea("isolated scope",ba,z,A),L(y)&&(E(A,"ng-isolate-scope"),ba=z),E(A,
"ng-scope"),D=D||z;T=z.name;if(y=z.controller)ha=ha||{},ea("'"+T+"' controller",ha[T],z,A),ha[T]=z;if(y=z.transclude)ea("transclusion",ga,z,A),ga=z,k=z.priority,y=="element"?(R=v(b),A=c.$$element=v(V.createComment(" "+T+": "+c[T]+" ")),b=A[0],fa(e,v(R[0]),b),ia=p(R,d,k)):(R=v(hb(b)).contents(),A.html(""),ia=p(R,d));if(z.template)if(ea("template",N,z,A),N=z,y=I(z.template)?z.template(A,c):z.template,y=Jb(y),z.replace){R=v("<div>"+S(y)+"</div>").contents();b=R[0];if(R.length!=1||b.nodeType!==1)throw Error(f+
y);fa(e,A,b);T={$attr:{}};a=a.concat(G(b,a.splice(w+1,a.length-(w+1)),T));H(c,T);u=a.length}else A.html(y);if(z.templateUrl)ea("template",N,z,A),N=z,l=F(a.splice(w,a.length-w),l,A,c,e,z.replace,ia),u=a.length;else if(z.compile)try{t=z.compile(A,c,ia),I(t)?j(null,t):t&&j(t.pre,t.post)}catch(J){m(J,ta(A))}if(z.terminal)l.terminal=!0,k=Math.max(k,z.priority)}l.scope=D&&D.scope;l.transclude=ga&&ia;return l}function A(d,e,g,f){var l=!1;if(a.hasOwnProperty(e))for(var i,e=b.get(e+c),n=0,k=e.length;n<k;n++)try{if(i=
e[n],(f===s||f>i.priority)&&i.restrict.indexOf(g)!=-1)d.push(i),l=!0}catch(q){m(q)}return l}function H(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;o(a,function(d,e){e.charAt(0)!="$"&&(b[e]&&(d+=(e==="style"?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});o(b,function(b,g){g=="class"?(E(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):g=="style"?e.attr("style",e.attr("style")+";"+b):g.charAt(0)!="$"&&!a.hasOwnProperty(g)&&(a[g]=b,d[g]=c[g])})}function F(a,b,c,d,e,g,j){var i=[],n,m,q=c[0],p=a.shift(),ya=y({},
p,{controller:null,templateUrl:null,transclude:null,scope:null}),p=I(p.templateUrl)?p.templateUrl(c,d):p.templateUrl;c.html("");k.get(p,{cache:l}).success(function(l){var k,p,l=Jb(l);if(g){p=v("<div>"+S(l)+"</div>").contents();k=p[0];if(p.length!=1||k.nodeType!==1)throw Error(f+l);l={$attr:{}};fa(e,c,k);G(k,a,l);H(d,l)}else k=q,c.html(l);a.unshift(ya);n=R(a,k,d,j);for(m=D(c[0].childNodes,j);i.length;){var B=i.shift(),l=i.shift();p=i.shift();var r=i.shift(),F=k;l!==q&&(F=hb(k),fa(p,v(l),F));n(function(){b(m,
B,F,e,r)},B,F,e,r)}i=null}).error(function(a,b,c,d){throw Error("Failed to load template: "+d.url);});return function(a,c,d,e,g){i?(i.push(c),i.push(d),i.push(e),i.push(g)):n(function(){b(m,c,d,e,g)},c,d,e,g)}}function N(a,b){return b.priority-a.priority}function ea(a,b,c,d){if(b)throw Error("Multiple directives ["+b.name+", "+c.name+"] asking for "+a+" on: "+ta(d));}function ga(a,b){var c=g(b,!0);c&&a.push({priority:0,compile:Q(function(a,b){var d=b.parent(),e=d.data("$binding")||[];e.push(c);E(d.data("$binding",
e),"ng-binding");a.$watch(c,function(a){b[0].nodeValue=a})})})}function z(a,b,c,d){var e=g(c,!0);e&&b.push({priority:100,compile:Q(function(a,b,c){b=c.$$observers||(c.$$observers={});if(e=g(c[d],!0))c[d]=e(a),(b[d]||(b[d]=[])).$$inter=!0,(c.$$observers&&c.$$observers[d].$$scope||a).$watch(e,function(a){c.$set(d,a)})})})}function fa(a,b,c){var d=b[0],e=d.parentNode,g,f;if(a){g=0;for(f=a.length;g<f;g++)if(a[g]==d){a[g]=c;break}}e&&e.replaceChild(c,d);c[v.expando]=d[v.expando];b[0]=c}var ya=function(a,
b){this.$$element=a;this.$attr=b||{}};ya.prototype={$normalize:aa,$set:function(a,b,c,d){var e=Db(this.$$element[0],a),g=this.$$observers;e&&(this.$$element.prop(a,b),d=e);this[a]=b;d?this.$attr[a]=d:(d=this.$attr[a])||(this.$attr[a]=d=db(a,"-"));if(jb(this.$$element[0])==="A"&&a==="href")ba.setAttribute("href",b),e=ba.href,e.match(i)||(this[a]=b="unsafe:"+e);c!==!1&&(b===null||b===s?this.$$element.removeAttr(d):this.$$element.attr(d,b));g&&o(g[a],function(a){try{a(b)}catch(c){m(c)}})},$observe:function(a,
b){var c=this,d=c.$$observers||(c.$$observers={}),e=d[a]||(d[a]=[]);e.push(b);B.$evalAsync(function(){e.$$inter||b(c[a])});return b}};var ba=r[0].createElement("a"),T=g.startSymbol(),ia=g.endSymbol(),Jb=T=="{{"||ia=="}}"?pa:function(a){return a.replace(/\{\{/g,T).replace(/}}/g,ia)},ha=/^ngAttr[A-Z]/;return p}]}function aa(b){return Ja(b.replace(Cc,""))}function Dc(){var b={};this.register=function(a,c){L(a)?y(b,a):b[a]=c};this.$get=["$injector","$window",function(a,c){return function(d,e){if(x(d)){var f=
d,d=b.hasOwnProperty(f)?b[f]:kb(e.$scope,f,!0)||kb(c,f,!0);va(d,f,!0)}return a.instantiate(d,e)}}]}function Ec(){this.$get=["$window",function(b){return v(b.document)}]}function Fc(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Gc(){var b="{{",a="}}";this.startSymbol=function(a){return a?(b=a,this):b};this.endSymbol=function(b){return b?(a=b,this):a};this.$get=["$parse","$exceptionHandler",function(c,d){function e(e,j){for(var g,m,k=0,l=[],q=e.length,n=
!1,B=[];k<q;)(g=e.indexOf(b,k))!=-1&&(m=e.indexOf(a,g+f))!=-1?(k!=g&&l.push(e.substring(k,g)),l.push(k=c(n=e.substring(g+f,m))),k.exp=n,k=m+i,n=!0):(k!=q&&l.push(e.substring(k)),k=q);if(!(q=l.length))l.push(""),q=1;if(!j||n)return B.length=q,k=function(a){try{for(var b=0,c=q,g;b<c;b++){if(typeof(g=l[b])=="function")g=g(a),g==null||g==s?g="":typeof g!="string"&&(g=da(g));B[b]=g}return B.join("")}catch(f){d(Error("Error while interpolating: "+e+"\n"+f.toString()))}},k.exp=e,k.parts=l,k}var f=b.length,
i=a.length;e.startSymbol=function(){return b};e.endSymbol=function(){return a};return e}]}function Kb(b){for(var b=b.split("/"),a=b.length;a--;)b[a]=cb(b[a]);return b.join("/")}function Aa(b,a){var c=lb.exec(b),c={protocol:c[1],host:c[3],port:K(c[5])||Ba[c[1]]||null,path:c[6]||"/",search:c[8],hash:c[10]};if(a)a.$$protocol=c.protocol,a.$$host=c.host,a.$$port=c.port;return c}function ma(b,a,c){return b+"://"+a+(c==Ba[b]?"":":"+c)}function Hc(b,a,c){var d=Aa(b);return decodeURIComponent(d.path)!=a||
u(d.hash)||d.hash.indexOf(c)!==0?b:ma(d.protocol,d.host,d.port)+a.substr(0,a.lastIndexOf("/"))+d.hash.substr(c.length)}function Ic(b,a,c){var d=Aa(b);if(decodeURIComponent(d.path)==a&&!u(d.hash)&&d.hash.indexOf(c)===0)return b;else{var e=d.search&&"?"+d.search||"",f=d.hash&&"#"+d.hash||"",i=a.substr(0,a.lastIndexOf("/")),h=d.path.substr(i.length);if(d.path.indexOf(i)!==0)throw Error('Invalid url "'+b+'", missing path prefix "'+i+'" !');return ma(d.protocol,d.host,d.port)+a+"#"+c+h+e+f}}function mb(b,
a,c){a=a||"";this.$$parse=function(b){var c=Aa(b,this);if(c.path.indexOf(a)!==0)throw Error('Invalid url "'+b+'", missing path prefix "'+a+'" !');this.$$path=decodeURIComponent(c.path.substr(a.length));this.$$search=bb(c.search);this.$$hash=c.hash&&decodeURIComponent(c.hash)||"";this.$$compose()};this.$$compose=function(){var b=ub(this.$$search),c=this.$$hash?"#"+cb(this.$$hash):"";this.$$url=Kb(this.$$path)+(b?"?"+b:"")+c;this.$$absUrl=ma(this.$$protocol,this.$$host,this.$$port)+a+this.$$url};this.$$rewriteAppUrl=
function(a){if(a.indexOf(c)==0)return a};this.$$parse(b)}function Qa(b,a,c){var d;this.$$parse=function(b){var c=Aa(b,this);if(c.hash&&c.hash.indexOf(a)!==0)throw Error('Invalid url "'+b+'", missing hash prefix "'+a+'" !');d=c.path+(c.search?"?"+c.search:"");c=Jc.exec((c.hash||"").substr(a.length));this.$$path=c[1]?(c[1].charAt(0)=="/"?"":"/")+decodeURIComponent(c[1]):"";this.$$search=bb(c[3]);this.$$hash=c[5]&&decodeURIComponent(c[5])||"";this.$$compose()};this.$$compose=function(){var b=ub(this.$$search),
c=this.$$hash?"#"+cb(this.$$hash):"";this.$$url=Kb(this.$$path)+(b?"?"+b:"")+c;this.$$absUrl=ma(this.$$protocol,this.$$host,this.$$port)+d+(this.$$url?"#"+a+this.$$url:"")};this.$$rewriteAppUrl=function(a){if(a.indexOf(c)==0)return a};this.$$parse(b)}function Lb(b,a,c,d){Qa.apply(this,arguments);this.$$rewriteAppUrl=function(b){if(b.indexOf(c)==0)return c+d+"#"+a+b.substr(c.length)}}function Ra(b){return function(){return this[b]}}function Mb(b,a){return function(c){if(u(c))return this[b];this[b]=
a(c);this.$$compose();return this}}function Kc(){var b="",a=!1;this.hashPrefix=function(a){return w(a)?(b=a,this):b};this.html5Mode=function(b){return w(b)?(a=b,this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement",function(c,d,e,f){function i(a){c.$broadcast("$locationChangeSuccess",h.absUrl(),a)}var h,j,g,m=d.url(),k=Aa(m);a?(j=d.baseHref()||"/",g=j.substr(0,j.lastIndexOf("/")),k=ma(k.protocol,k.host,k.port)+g+"/",h=e.history?new mb(Hc(m,j,b),g,k):new Lb(Ic(m,j,b),b,k,j.substr(g.length+
1))):(k=ma(k.protocol,k.host,k.port)+(k.path||"")+(k.search?"?"+k.search:"")+"#"+b+"/",h=new Qa(m,b,k));f.bind("click",function(a){if(!a.ctrlKey&&!(a.metaKey||a.which==2)){for(var b=v(a.target);J(b[0].nodeName)!=="a";)if(b[0]===f[0]||!(b=b.parent())[0])return;var d=b.prop("href"),e=h.$$rewriteAppUrl(d);d&&!b.attr("target")&&e&&(h.$$parse(e),c.$apply(),a.preventDefault(),M.angular["ff-684208-preventDefault"]=!0)}});h.absUrl()!=m&&d.url(h.absUrl(),!0);d.onUrlChange(function(a){h.absUrl()!=a&&(c.$evalAsync(function(){var b=
h.absUrl();h.$$parse(a);i(b)}),c.$$phase||c.$digest())});var l=0;c.$watch(function(){var a=d.url(),b=h.$$replace;if(!l||a!=h.absUrl())l++,c.$evalAsync(function(){c.$broadcast("$locationChangeStart",h.absUrl(),a).defaultPrevented?h.$$parse(a):(d.url(h.absUrl(),b),i(a))});h.$$replace=!1;return l});return h}]}function Lc(){var b=!0,a=this;this.debugEnabled=function(a){return w(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&(a.stack?a=a.message&&a.stack.indexOf(a.message)===
-1?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||t;return e.apply?function(){var a=[];o(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,b)}}return{log:e("log"),warn:e("warn"),info:e("info"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}function Mc(b,a){function c(a){return a.indexOf(r)!=-1}function d(a){a=a||
1;return n+a<b.length?b.charAt(n+a):!1}function e(a){return"0"<=a&&a<="9"}function f(a){return a==" "||a=="\r"||a=="\t"||a=="\n"||a=="\u000b"||a=="\u00a0"}function i(a){return"a"<=a&&a<="z"||"A"<=a&&a<="Z"||"_"==a||a=="$"}function h(a){return a=="-"||a=="+"||e(a)}function j(a,c,d){d=d||n;throw Error("Lexer Error: "+a+" at column"+(w(c)?"s "+c+"-"+n+" ["+b.substring(c,d)+"]":" "+d)+" in expression ["+b+"].");}function g(){for(var a="",c=n;n<b.length;){var g=J(b.charAt(n));if(g=="."||e(g))a+=g;else{var f=
d();if(g=="e"&&h(f))a+=g;else if(h(g)&&f&&e(f)&&a.charAt(a.length-1)=="e")a+=g;else if(h(g)&&(!f||!e(f))&&a.charAt(a.length-1)=="e")j("Invalid exponent");else break}n++}a*=1;l.push({index:c,text:a,json:!0,fn:function(){return a}})}function m(){for(var c="",d=n,g,h,j;n<b.length;){var k=b.charAt(n);if(k=="."||i(k)||e(k))k=="."&&(g=n),c+=k;else break;n++}if(g)for(h=n;h<b.length;){k=b.charAt(h);if(k=="("){j=c.substr(g-d+1);c=c.substr(0,g-d);n=h;break}if(f(k))h++;else break}d={index:d,text:c};if(Ca.hasOwnProperty(c))d.fn=
d.json=Ca[c];else{var m=Nb(c,a);d.fn=y(function(a,b){return m(a,b)},{assign:function(a,b){return Ob(a,c,b)}})}l.push(d);j&&(l.push({index:g,text:".",json:!1}),l.push({index:g+1,text:j,json:!1}))}function k(a){var c=n;n++;for(var d="",e=a,g=!1;n<b.length;){var h=b.charAt(n);e+=h;if(g)h=="u"?(h=b.substring(n+1,n+5),h.match(/[\da-f]{4}/i)||j("Invalid unicode escape [\\u"+h+"]"),n+=4,d+=String.fromCharCode(parseInt(h,16))):(g=Nc[h],d+=g?g:h),g=!1;else if(h=="\\")g=!0;else if(h==a){n++;l.push({index:c,
text:e,string:d,json:!0,fn:function(){return d}});return}else d+=h;n++}j("Unterminated quote",c)}for(var l=[],q,n=0,B=[],r,p=":";n<b.length;){r=b.charAt(n);if(c("\"'"))k(r);else if(e(r)||c(".")&&e(d()))g();else if(i(r)){if(m(),"{,".indexOf(p)!=-1&&B[0]=="{"&&(q=l[l.length-1]))q.json=q.text.indexOf(".")==-1}else if(c("(){}[].,;:"))l.push({index:n,text:r,json:":[,".indexOf(p)!=-1&&c("{[")||c("}]:,")}),c("{[")&&B.unshift(r),c("}]")&&B.shift(),n++;else if(f(r)){n++;continue}else{var E=r+d(),D=E+d(2),
G=Ca[r],o=Ca[E],A=Ca[D];A?(l.push({index:n,text:D,fn:A}),n+=3):o?(l.push({index:n,text:E,fn:o}),n+=2):G?(l.push({index:n,text:r,fn:G,json:"[,:".indexOf(p)!=-1&&c("+-")}),n+=1):j("Unexpected next character ",n,n+1)}p=r}return l}function Oc(b,a,c,d){function e(a,c){throw Error("Syntax Error: Token '"+c.text+"' "+a+" at column "+(c.index+1)+" of the expression ["+b+"] starting at ["+b.substring(c.index)+"].");}function f(){if(F.length===0)throw Error("Unexpected end of expression: "+b);return F[0]}function i(a,
b,c,d){if(F.length>0){var e=F[0],g=e.text;if(g==a||g==b||g==c||g==d||!a&&!b&&!c&&!d)return e}return!1}function h(b,c,d,g){return(b=i(b,c,d,g))?(a&&!b.json&&e("is not valid json",b),F.shift(),b):!1}function j(a){h(a)||e("is unexpected, expecting ["+a+"]",i())}function g(a,b){return y(function(c,d){return a(c,d,b)},{constant:b.constant})}function m(a,b,c){return y(function(d,e){return b(d,e,a,c)},{constant:a.constant&&c.constant})}function k(){for(var a=[];;)if(F.length>0&&!i("}",")",";","]")&&a.push(fa()),
!h(";"))return a.length==1?a[0]:function(b,c){for(var d,e=0;e<a.length;e++){var g=a[e];g&&(d=g(b,c))}return d}}function l(){for(var a=h(),b=c(a.text),d=[];;)if(a=h(":"))d.push(N());else{var e=function(a,c,e){for(var e=[e],g=0;g<d.length;g++)e.push(d[g](a,c));return b.apply(a,e)};return function(){return e}}}function q(){for(var a=n(),b;;)if(b=h("||"))a=m(a,b.fn,n());else return a}function n(){var a=B(),b;if(b=h("&&"))a=m(a,b.fn,n());return a}function B(){var a=r(),b;if(b=h("==","!=","===","!=="))a=
m(a,b.fn,B());return a}function r(){var a;a=p();for(var b;b=h("+","-");)a=m(a,b.fn,p());if(b=h("<",">","<=",">="))a=m(a,b.fn,r());return a}function p(){for(var a=E(),b;b=h("*","/","%");)a=m(a,b.fn,E());return a}function E(){var a;return h("+")?D():(a=h("-"))?m(A,a.fn,E()):(a=h("!"))?g(a.fn,E()):D()}function D(){var a;if(h("("))a=fa(),j(")");else if(h("["))a=G();else if(h("{"))a=o();else{var b=h();(a=b.fn)||e("not a primary expression",b);if(b.json)a.constant=a.literal=!0}for(var c;b=h("(","[",".");)b.text===
"("?(a=ea(a,c),c=null):b.text==="["?(c=a,a=z(a)):b.text==="."?(c=a,a=ga(a)):e("IMPOSSIBLE");return a}function G(){var a=[],b=!0;if(f().text!="]"){do{var c=N();a.push(c);c.constant||(b=!1)}while(h(","))}j("]");return y(function(b,c){for(var d=[],e=0;e<a.length;e++)d.push(a[e](b,c));return d},{literal:!0,constant:b})}function o(){var a=[],b=!0;if(f().text!="}"){do{var c=h(),c=c.string||c.text;j(":");var d=N();a.push({key:c,value:d});d.constant||(b=!1)}while(h(","))}j("}");return y(function(b,c){for(var d=
{},e=0;e<a.length;e++){var g=a[e],h=g.value(b,c);d[g.key]=h}return d},{literal:!0,constant:b})}var A=Q(0),H,F=Mc(b,d),N=function(){var a=q(),c,d;return(d=h("="))?(a.assign||e("implies assignment but ["+b.substring(0,d.index)+"] can not be assigned to",d),c=q(),function(b,d){return a.assign(b,c(b,d),d)}):a},ea=function(a,b){var c=[];if(f().text!=")"){do c.push(N());while(h(","))}j(")");return function(d,e){for(var g=[],h=b?b(d,e):d,f=0;f<c.length;f++)g.push(c[f](d,e));f=a(d,e)||t;return f.apply?f.apply(h,
g):f(g[0],g[1],g[2],g[3],g[4])}},ga=function(a){var b=h().text,c=Nb(b,d);return y(function(b,d){return c(a(b,d),d)},{assign:function(c,d,e){return Ob(a(c,e),b,d)}})},z=function(a){var b=N();j("]");return y(function(c,d){var e=a(c,d),g=b(c,d),h;if(!e)return s;if((e=e[g])&&e.then){h=e;if(!("$$v"in e))h.$$v=s,h.then(function(a){h.$$v=a});e=e.$$v}return e},{assign:function(c,d,e){return a(c,e)[b(c,e)]=d}})},fa=function(){for(var a=N(),b;;)if(b=h("|"))a=m(a,b.fn,l());else return a};a?(N=q,ea=ga=z=fa=function(){e("is not valid json",
{text:b,index:0})},H=D()):H=k();F.length!==0&&e("is an unexpected token",F[0]);H.literal=!!H.literal;H.constant=!!H.constant;return H}function Ob(b,a,c){for(var a=a.split("."),d=0;a.length>1;d++){var e=a.shift(),f=b[e];f||(f={},b[e]=f);b=f}return b[a.shift()]=c}function kb(b,a,c){if(!a)return b;for(var a=a.split("."),d,e=b,f=a.length,i=0;i<f;i++)d=a[i],b&&(b=(e=b)[d]);return!c&&I(b)?ab(e,b):b}function Pb(b,a,c,d,e){return function(f,i){var h=i&&i.hasOwnProperty(b)?i:f,j;if(h===null||h===s)return h;
if((h=h[b])&&h.then){if(!("$$v"in h))j=h,j.$$v=s,j.then(function(a){j.$$v=a});h=h.$$v}if(!a||h===null||h===s)return h;if((h=h[a])&&h.then){if(!("$$v"in h))j=h,j.$$v=s,j.then(function(a){j.$$v=a});h=h.$$v}if(!c||h===null||h===s)return h;if((h=h[c])&&h.then){if(!("$$v"in h))j=h,j.$$v=s,j.then(function(a){j.$$v=a});h=h.$$v}if(!d||h===null||h===s)return h;if((h=h[d])&&h.then){if(!("$$v"in h))j=h,j.$$v=s,j.then(function(a){j.$$v=a});h=h.$$v}if(!e||h===null||h===s)return h;if((h=h[e])&&h.then){if(!("$$v"in
h))j=h,j.$$v=s,j.then(function(a){j.$$v=a});h=h.$$v}return h}}function Nb(b,a){if(nb.hasOwnProperty(b))return nb[b];var c=b.split("."),d=c.length,e;if(a)e=d<6?Pb(c[0],c[1],c[2],c[3],c[4]):function(a,b){var e=0,g;do g=Pb(c[e++],c[e++],c[e++],c[e++],c[e++])(a,b),b=s,a=g;while(e<d);return g};else{var f="var l, fn, p;\n";o(c,function(a,b){f+="if(s === null || s === undefined) return s;\nl=s;\ns="+(b?"s":'((k&&k.hasOwnProperty("'+a+'"))?k:s)')+'["'+a+'"];\nif (s && s.then) {\n if (!("$$v" in s)) {\n p=s;\n p.$$v = undefined;\n p.then(function(v) {p.$$v=v;});\n}\n s=s.$$v\n}\n'});
f+="return s;";e=Function("s","k",f);e.toString=function(){return f}}return nb[b]=e}function Pc(){var b={};this.$get=["$filter","$sniffer",function(a,c){return function(d){switch(typeof d){case "string":return b.hasOwnProperty(d)?b[d]:b[d]=Oc(d,!1,a,c.csp);case "function":return d;default:return t}}}]}function Qc(){this.$get=["$rootScope","$exceptionHandler",function(b,a){return Rc(function(a){b.$evalAsync(a)},a)}]}function Rc(b,a){function c(a){return a}function d(a){return i(a)}var e=function(){var h=
[],j,g;return g={resolve:function(a){if(h){var c=h;h=s;j=f(a);c.length&&b(function(){for(var a,b=0,d=c.length;b<d;b++)a=c[b],j.then(a[0],a[1])})}},reject:function(a){g.resolve(i(a))},promise:{then:function(b,g){var f=e(),i=function(d){try{f.resolve((b||c)(d))}catch(e){a(e),f.reject(e)}},n=function(b){try{f.resolve((g||d)(b))}catch(c){a(c),f.reject(c)}};h?h.push([i,n]):j.then(i,n);return f.promise}}}},f=function(a){return a&&a.then?a:{then:function(c){var d=e();b(function(){d.resolve(c(a))});return d.promise}}},
i=function(a){return{then:function(c,g){var f=e();b(function(){f.resolve((g||d)(a))});return f.promise}}};return{defer:e,reject:i,when:function(h,j,g){var m=e(),k,l=function(b){try{return(j||c)(b)}catch(d){return a(d),i(d)}},q=function(b){try{return(g||d)(b)}catch(c){return a(c),i(c)}};b(function(){f(h).then(function(a){k||(k=!0,m.resolve(f(a).then(l,q)))},function(a){k||(k=!0,m.resolve(q(a)))})});return m.promise},all:function(a){var b=e(),c=0,d=C(a)?[]:{};o(a,function(a,e){c++;f(a).then(function(a){d.hasOwnProperty(e)||
(d[e]=a,--c||b.resolve(d))},function(a){d.hasOwnProperty(e)||b.reject(a)})});c===0&&b.resolve(d);return b.promise}}}function Sc(){var b={};this.when=function(a,c){b[a]=y({reloadOnSearch:!0,caseInsensitiveMatch:!1},c);if(a){var d=a[a.length-1]=="/"?a.substr(0,a.length-1):a+"/";b[d]={redirectTo:a}}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache",function(a,c,d,e,f,i,h){function j(a,b,c){for(var b=
"^"+b.replace(/[-\/\\^$:*+?.()|[\]{}]/g,"\\$&")+"$",d="",e=[],g={},f=/\\([:*])(\w+)/g,h,j=0;(h=f.exec(b))!==null;){d+=b.slice(j,h.index);switch(h[1]){case ":":d+="([^\\/]*)";break;case "*":d+="(.*)"}e.push(h[2]);j=f.lastIndex}d+=b.substr(j);var i=a.match(RegExp(d,c.caseInsensitiveMatch?"i":""));i&&o(e,function(a,b){g[a]=i[b+1]});return i?g:null}function g(){var b=m(),g=q.current;if(b&&g&&b.$$route===g.$$route&&ja(b.pathParams,g.pathParams)&&!b.reloadOnSearch&&!l)g.params=b.params,W(g.params,d),a.$broadcast("$routeUpdate",
g);else if(b||g)l=!1,a.$broadcast("$routeChangeStart",b,g),(q.current=b)&&b.redirectTo&&(x(b.redirectTo)?c.path(k(b.redirectTo,b.params)).search(b.params).replace():c.url(b.redirectTo(b.pathParams,c.path(),c.search())).replace()),e.when(b).then(function(){if(b){var a=y({},b.resolve),c;o(a,function(b,c){a[c]=x(b)?f.get(b):f.invoke(b)});if(w(c=b.template))I(c)&&(c=c(b.params));else if(w(c=b.templateUrl))if(I(c)&&(c=c(b.params)),w(c))b.loadedTemplateUrl=c,c=i.get(c,{cache:h}).then(function(a){return a.data});
w(c)&&(a.$template=c);return e.all(a)}}).then(function(c){if(b==q.current){if(b)b.locals=c,W(b.params,d);a.$broadcast("$routeChangeSuccess",b,g)}},function(c){b==q.current&&a.$broadcast("$routeChangeError",b,g,c)})}function m(){var a,d;o(b,function(b,e){if(!d&&(a=j(c.path(),e,b)))d=Fa(b,{params:y({},c.search(),a),pathParams:a}),d.$$route=b});return d||b[null]&&Fa(b[null],{params:{},pathParams:{}})}function k(a,b){var c=[];o((a||"").split(":"),function(a,d){if(d==0)c.push(a);else{var e=a.match(/(\w+)(.*)/),
g=e[1];c.push(b[g]);c.push(e[2]||"");delete b[g]}});return c.join("")}var l=!1,q={routes:b,reload:function(){l=!0;a.$evalAsync(g)}};a.$on("$locationChangeSuccess",g);return q}]}function Tc(){this.$get=Q({})}function Uc(){var b=10;this.digestTtl=function(a){arguments.length&&(b=a);return b};this.$get=["$injector","$exceptionHandler","$parse",function(a,c,d){function e(){this.$id=Ea();this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null;
this["this"]=this.$root=this;this.$$destroyed=!1;this.$$asyncQueue=[];this.$$listeners={};this.$$isolateBindings={}}function f(a){if(j.$$phase)throw Error(j.$$phase+" already in progress");j.$$phase=a}function i(a,b){var c=d(a);va(c,b);return c}function h(){}e.prototype={$new:function(a){if(I(a))throw Error("API-CHANGE: Use $controller to instantiate controllers.");a?(a=new e,a.$root=this.$root):(a=function(){},a.prototype=this,a=new a,a.$id=Ea());a["this"]=a;a.$$listeners={};a.$parent=this;a.$$watchers=
a.$$nextSibling=a.$$childHead=a.$$childTail=null;a.$$prevSibling=this.$$childTail;this.$$childHead?this.$$childTail=this.$$childTail.$$nextSibling=a:this.$$childHead=this.$$childTail=a;return a},$watch:function(a,b,c){var d=i(a,"watch"),e=this.$$watchers,f={fn:b,last:h,get:d,exp:a,eq:!!c};if(!I(b)){var j=i(b||t,"listener");f.fn=function(a,b,c){j(c)}}if(typeof a=="string"&&d.constant){var r=f.fn;f.fn=function(a,b,c){r.call(this,a,b,c);sa(e,f)}}if(!e)e=this.$$watchers=[];e.unshift(f);return function(){sa(e,
f)}},$watchCollection:function(a,b){var c=this,e,f,h=0,j=d(a),i=[],p={},o=0;return this.$watch(function(){f=j(c);var a,b;if(L(f))if(C(f)){if(e!==i)e=i,o=e.length=0,h++;a=f.length;if(o!==a)h++,e.length=o=a;for(b=0;b<a;b++)e[b]!==f[b]&&(h++,e[b]=f[b])}else{e!==p&&(e=p={},o=0,h++);a=0;for(b in f)f.hasOwnProperty(b)&&(a++,e.hasOwnProperty(b)?e[b]!==f[b]&&(h++,e[b]=f[b]):(o++,e[b]=f[b],h++));if(o>a)for(b in h++,e)e.hasOwnProperty(b)&&!f.hasOwnProperty(b)&&(o--,delete e[b])}else e!==f&&(e=f,h++);return h},
function(){b(f,e,c)})},$digest:function(){var a,d,e,i,q=this.$$asyncQueue,n,o,r=b,p,E=[],D,G;f("$digest");do{o=!1;for(p=this;q.length;)try{p.$eval(q.shift())}catch(s){c(s)}do{if(i=p.$$watchers)for(n=i.length;n--;)try{if(a=i[n],(d=a.get(p))!==(e=a.last)&&!(a.eq?ja(d,e):typeof d=="number"&&typeof e=="number"&&isNaN(d)&&isNaN(e)))o=!0,a.last=a.eq?W(d):d,a.fn(d,e===h?d:e,p),r<5&&(D=4-r,E[D]||(E[D]=[]),G=I(a.exp)?"fn: "+(a.exp.name||a.exp.toString()):a.exp,G+="; newVal: "+da(d)+"; oldVal: "+da(e),E[D].push(G))}catch(A){c(A)}if(!(i=
p.$$childHead||p!==this&&p.$$nextSibling))for(;p!==this&&!(i=p.$$nextSibling);)p=p.$parent}while(p=i);if(o&&!r--)throw j.$$phase=null,Error(b+" $digest() iterations reached. Aborting!\nWatchers fired in the last 5 iterations: "+da(E));}while(o||q.length);j.$$phase=null},$destroy:function(){if(!(j==this||this.$$destroyed)){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;if(a.$$childHead==this)a.$$childHead=this.$$nextSibling;if(a.$$childTail==this)a.$$childTail=this.$$prevSibling;
if(this.$$prevSibling)this.$$prevSibling.$$nextSibling=this.$$nextSibling;if(this.$$nextSibling)this.$$nextSibling.$$prevSibling=this.$$prevSibling;this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null}},$eval:function(a,b){return d(a)(this,b)},$evalAsync:function(a){this.$$asyncQueue.push(a)},$apply:function(a){try{return f("$apply"),this.$eval(a)}catch(b){c(b)}finally{j.$$phase=null;try{j.$digest()}catch(d){throw c(d),d;}}},$on:function(a,b){var c=this.$$listeners[a];
c||(this.$$listeners[a]=c=[]);c.push(b);return function(){c[Ga(c,b)]=null}},$emit:function(a,b){var d=[],e,f=this,h=!1,i={name:a,targetScope:f,stopPropagation:function(){h=!0},preventDefault:function(){i.defaultPrevented=!0},defaultPrevented:!1},j=[i].concat(ka.call(arguments,1)),p,o;do{e=f.$$listeners[a]||d;i.currentScope=f;p=0;for(o=e.length;p<o;p++)if(e[p])try{if(e[p].apply(null,j),h)return i}catch(D){c(D)}else e.splice(p,1),p--,o--;f=f.$parent}while(f);return i},$broadcast:function(a,b){var d=
this,e=this,f={name:a,targetScope:this,preventDefault:function(){f.defaultPrevented=!0},defaultPrevented:!1},h=[f].concat(ka.call(arguments,1)),i,j;do{d=e;f.currentScope=d;e=d.$$listeners[a]||[];i=0;for(j=e.length;i<j;i++)if(e[i])try{e[i].apply(null,h)}catch(p){c(p)}else e.splice(i,1),i--,j--;if(!(e=d.$$childHead||d!==this&&d.$$nextSibling))for(;d!==this&&!(e=d.$$nextSibling);)d=d.$parent}while(d=e);return f}};var j=new e;return j}]}function Vc(){this.$get=["$window","$document",function(b,a){var c=
{},d=K((/android (\d+)/.exec(J((b.navigator||{}).userAgent))||[])[1]),e=a[0]||{},f,i=/^(Moz|webkit|O|ms)(?=[A-Z])/,h=e.body&&e.body.style,j=!1;if(h){for(var g in h)if(j=i.exec(g)){f=j[0];f=f.substr(0,1).toUpperCase()+f.substr(1);break}j=!!(f+"Transition"in h)}return{history:!(!b.history||!b.history.pushState||d<4),hashchange:"onhashchange"in b&&(!e.documentMode||e.documentMode>7),hasEvent:function(a){if(a=="input"&&X==9)return!1;if(u(c[a])){var b=e.createElement("div");c[a]="on"+a in b}return c[a]},
csp:e.securityPolicy?e.securityPolicy.isActive:!1,vendorPrefix:f,supportsTransitions:j}}]}function Wc(){this.$get=Q(M)}function Qb(b){var a={},c,d,e;if(!b)return a;o(b.split("\n"),function(b){e=b.indexOf(":");c=J(S(b.substr(0,e)));d=S(b.substr(e+1));c&&(a[c]?a[c]+=", "+d:a[c]=d)});return a}function Xc(b,a){var c=Yc.exec(b);if(c==null)return!0;var d={protocol:c[2],host:c[4],port:K(c[6])||Ba[c[2]]||null,relativeProtocol:c[2]===s||c[2]===""},c=lb.exec(a),c={protocol:c[1],host:c[3],port:K(c[5])||Ba[c[1]]||
null};return(d.protocol==c.protocol||d.relativeProtocol)&&d.host==c.host&&(d.port==c.port||d.relativeProtocol&&c.port==Ba[c.protocol])}function Rb(b){var a=L(b)?b:s;return function(c){a||(a=Qb(b));return c?a[J(c)]||null:a}}function Sb(b,a,c){if(I(c))return c(b,a);o(c,function(c){b=c(b,a)});return b}function Zc(){var b=/^\s*(\[|\{[^\{])/,a=/[\}\]]\s*$/,c=/^\)\]\}',?\n/,d=this.defaults={transformResponse:[function(d){x(d)&&(d=d.replace(c,""),b.test(d)&&a.test(d)&&(d=tb(d,!0)));return d}],transformRequest:[function(a){return L(a)&&
Da.apply(a)!=="[object File]"?da(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:{"Content-Type":"application/json;charset=utf-8"},put:{"Content-Type":"application/json;charset=utf-8"}},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN"},e=this.interceptors=[],f=this.responseInterceptors=[];this.$get=["$httpBackend","$browser","$cacheFactory","$rootScope","$q","$injector",function(a,b,c,g,m,k){function l(a){function c(a){var b=y({},a,{data:Sb(a.data,a.headers,e.transformResponse)});
return 200<=a.status&&a.status<300?b:m.reject(b)}var e={transformRequest:d.transformRequest,transformResponse:d.transformResponse},g={};y(e,a);e.headers=g;e.method=na(e.method);y(g,d.headers.common,d.headers[J(e.method)],a.headers);(a=Xc(e.url,b.url())?b.cookies()[e.xsrfCookieName||d.xsrfCookieName]:s)&&(g[e.xsrfHeaderName||d.xsrfHeaderName]=a);var f=[function(a){var b=Sb(a.data,Rb(g),a.transformRequest);u(a.data)&&delete g["Content-Type"];if(u(a.withCredentials)&&!u(d.withCredentials))a.withCredentials=
d.withCredentials;return q(a,b,g).then(c,c)},s],j=m.when(e);for(o(r,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&&f.push(a.response,a.responseError)});f.length;)var a=f.shift(),i=f.shift(),j=j.then(a,i);j.success=function(a){j.then(function(b){a(b.data,b.status,b.headers,e)});return j};j.error=function(a){j.then(null,function(b){a(b.data,b.status,b.headers,e)});return j};return j}function q(b,c,e){function f(a,b,c){o&&(200<=a&&a<300?o.put(s,
[a,b,Qb(c)]):o.remove(s));h(b,a,c);g.$apply()}function h(a,c,d){c=Math.max(c,0);(200<=c&&c<300?k.resolve:k.reject)({data:a,status:c,headers:Rb(d),config:b})}function j(){var a=Ga(l.pendingRequests,b);a!==-1&&l.pendingRequests.splice(a,1)}var k=m.defer(),q=k.promise,o,r,s=n(b.url,b.params);l.pendingRequests.push(b);q.then(j,j);if((b.cache||d.cache)&&b.cache!==!1&&b.method=="GET")o=L(b.cache)?b.cache:L(d.cache)?d.cache:B;if(o)if(r=o.get(s))if(r.then)return r.then(j,j),r;else C(r)?h(r[1],r[0],W(r[2])):
h(r,200,{});else o.put(s,q);r||a(b.method,s,c,f,e,b.timeout,b.withCredentials,b.responseType);return q}function n(a,b){if(!b)return a;var c=[];ic(b,function(a,b){a==null||a==s||(C(a)||(a=[a]),o(a,function(a){L(a)&&(a=da(a));c.push(ua(b)+"="+ua(a))}))});return a+(a.indexOf("?")==-1?"?":"&")+c.join("&")}var B=c("$http"),r=[];o(e,function(a){r.unshift(x(a)?k.get(a):k.invoke(a))});o(f,function(a,b){var c=x(a)?k.get(a):k.invoke(a);r.splice(b,0,{response:function(a){return c(m.when(a))},responseError:function(a){return c(m.reject(a))}})});
l.pendingRequests=[];(function(a){o(arguments,function(a){l[a]=function(b,c){return l(y(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){o(arguments,function(a){l[a]=function(b,c,d){return l(y(d||{},{method:a,url:b,data:c}))}})})("post","put");l.defaults=d;return l}]}function $c(){this.$get=["$browser","$window","$document",function(b,a,c){return ad(b,bd,b.defer,a.angular.callbacks,c[0],a.location.protocol.replace(":",""))}]}function ad(b,a,c,d,e,f){function i(a,b){var c=
e.createElement("script"),d=function(){e.body.removeChild(c);b&&b()};c.type="text/javascript";c.src=a;X?c.onreadystatechange=function(){/loaded|complete/.test(c.readyState)&&d()}:c.onload=c.onerror=d;e.body.appendChild(c)}return function(e,j,g,m,k,l,q,n){function B(a,c,d,e){c=(j.match(lb)||["",f])[1]=="file"?d?200:404:c;a(c==1223?204:c,d,e);b.$$completeOutstandingRequest(t)}b.$$incOutstandingRequestCount();j=j||b.url();if(J(e)=="jsonp"){var r="_"+(d.counter++).toString(36);d[r]=function(a){d[r].data=
a};i(j.replace("JSON_CALLBACK","angular.callbacks."+r),function(){d[r].data?B(m,200,d[r].data):B(m,-2);delete d[r]})}else{var p=new a;p.open(e,j,!0);o(k,function(a,b){a&&p.setRequestHeader(b,a)});var s;p.onreadystatechange=function(){if(p.readyState==4){var a=p.getAllResponseHeaders(),b=["Cache-Control","Content-Language","Content-Type","Expires","Last-Modified","Pragma"];a||(a="",o(b,function(b){var c=p.getResponseHeader(b);c&&(a+=b+": "+c+"\n")}));B(m,s||p.status,p.responseType?p.response:p.responseText,
a)}};if(q)p.withCredentials=!0;if(n)p.responseType=n;p.send(g||"");l>0&&c(function(){s=-1;p.abort()},l)}}}function cd(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January,February,March,April,May,June,July,August,September,October,November,December".split(","),
SHORTMONTH:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(","),DAY:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(","),SHORTDAY:"Sun,Mon,Tue,Wed,Thu,Fri,Sat".split(","),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a"},pluralCat:function(b){return b===1?"one":"other"}}}}function dd(){this.$get=["$rootScope","$browser","$q",
"$exceptionHandler",function(b,a,c,d){function e(e,h,j){var g=c.defer(),m=g.promise,k=w(j)&&!j,h=a.defer(function(){try{g.resolve(e())}catch(a){g.reject(a),d(a)}k||b.$apply()},h),j=function(){delete f[m.$$timeoutId]};m.$$timeoutId=h;f[h]=g;m.then(j,j);return m}var f={};e.cancel=function(b){return b&&b.$$timeoutId in f?(f[b.$$timeoutId].reject("canceled"),a.defer.cancel(b.$$timeoutId)):!1};return e}]}function Tb(b){function a(a,e){return b.factory(a+c,e)}var c="Filter";this.register=a;this.$get=["$injector",
function(a){return function(b){return a.get(b+c)}}];a("currency",Ub);a("date",Vb);a("filter",ed);a("json",fd);a("limitTo",gd);a("lowercase",hd);a("number",Wb);a("orderBy",Xb);a("uppercase",id)}function ed(){return function(b,a,c){if(!C(b))return b;var d=[];d.check=function(a){for(var b=0;b<d.length;b++)if(!d[b](a))return!1;return!0};switch(typeof c){case "function":break;case "boolean":if(c==!0){c=function(a,b){return Ia.equals(a,b)};break}default:c=function(a,b){b=(""+b).toLowerCase();return(""+
a).toLowerCase().indexOf(b)>-1}}var e=function(a,b){if(typeof b=="string"&&b.charAt(0)==="!")return!e(a,b.substr(1));switch(typeof a){case "boolean":case "number":case "string":return c(a,b);case "object":switch(typeof b){case "object":return c(a,b);default:for(var d in a)if(d.charAt(0)!=="$"&&e(a[d],b))return!0}return!1;case "array":for(d=0;d<a.length;d++)if(e(a[d],b))return!0;return!1;default:return!1}};switch(typeof a){case "boolean":case "number":case "string":a={$:a};case "object":for(var f in a)f==
"$"?function(){if(a[f]){var b=f;d.push(function(c){return e(c,a[b])})}}():function(){if(a[f]){var b=f;d.push(function(c){return e(kb(c,b),a[b])})}}();break;case "function":d.push(a);break;default:return b}for(var i=[],h=0;h<b.length;h++){var j=b[h];d.check(j)&&i.push(j)}return i}}function Ub(b){var a=b.NUMBER_FORMATS;return function(b,d){if(u(d))d=a.CURRENCY_SYM;return Yb(b,a.PATTERNS[1],a.GROUP_SEP,a.DECIMAL_SEP,2).replace(/\u00A4/g,d)}}function Wb(b){var a=b.NUMBER_FORMATS;return function(b,d){return Yb(b,
a.PATTERNS[0],a.GROUP_SEP,a.DECIMAL_SEP,d)}}function Yb(b,a,c,d,e){if(isNaN(b)||!isFinite(b))return"";var f=b<0,b=Math.abs(b),i=b+"",h="",j=[],g=!1;if(i.indexOf("e")!==-1){var m=i.match(/([\d\.]+)e(-?)(\d+)/);m&&m[2]=="-"&&m[3]>e+1?i="0":(h=i,g=!0)}if(!g){i=(i.split(Zb)[1]||"").length;u(e)&&(e=Math.min(Math.max(a.minFrac,i),a.maxFrac));var i=Math.pow(10,e),b=Math.round(b*i)/i,b=(""+b).split(Zb),i=b[0],b=b[1]||"",g=0,m=a.lgSize,k=a.gSize;if(i.length>=m+k)for(var g=i.length-m,l=0;l<g;l++)(g-l)%k===
0&&l!==0&&(h+=c),h+=i.charAt(l);for(l=g;l<i.length;l++)(i.length-l)%m===0&&l!==0&&(h+=c),h+=i.charAt(l);for(;b.length<e;)b+="0";e&&e!=="0"&&(h+=d+b.substr(0,e))}j.push(f?a.negPre:a.posPre);j.push(h);j.push(f?a.negSuf:a.posSuf);return j.join("")}function ob(b,a,c){var d="";b<0&&(d="-",b=-b);for(b=""+b;b.length<a;)b="0"+b;c&&(b=b.substr(b.length-a));return d+b}function O(b,a,c,d){return function(e){e=e["get"+b]();if(c>0||e>-c)e+=c;e===0&&c==-12&&(e=12);return ob(e,a,d)}}function Sa(b,a){return function(c,
d){var e=c["get"+b](),f=na(a?"SHORT"+b:b);return d[f][e]}}function Vb(b){function a(a){var b;if(b=a.match(c)){var a=new Date(0),f=0,i=0,h=b[8]?a.setUTCFullYear:a.setFullYear,j=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=K(b[9]+b[10]),i=K(b[9]+b[11]));h.call(a,K(b[1]),K(b[2])-1,K(b[3]));j.call(a,K(b[4]||0)-f,K(b[5]||0)-i,K(b[6]||0),K(b[7]||0))}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e){var f="",i=[],h,j,e=e||
"mediumDate",e=b.DATETIME_FORMATS[e]||e;x(c)&&(c=jd.test(c)?K(c):a(c));Za(c)&&(c=new Date(c));if(!qa(c))return c;for(;e;)(j=kd.exec(e))?(i=i.concat(ka.call(j,1)),e=i.pop()):(i.push(e),e=null);o(i,function(a){h=ld[a];f+=h?h(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return f}}function fd(){return function(b){return da(b,!0)}}function gd(){return function(b,a){if(!C(b)&&!x(b))return b;a=K(a);if(x(b))return a?a>=0?b.slice(0,a):b.slice(a,b.length):"";var c=[],d,e;a>b.length?a=
b.length:a<-b.length&&(a=-b.length);a>0?(d=0,e=a):(d=b.length+a,e=b.length);for(;d<e;d++)c.push(b[d]);return c}}function Xb(b){return function(a,c,d){function e(a,b){return Ha(b)?function(b,c){return a(c,b)}:a}if(!C(a))return a;if(!c)return a;for(var c=C(c)?c:[c],c=$a(c,function(a){var c=!1,d=a||pa;if(x(a)){if(a.charAt(0)=="+"||a.charAt(0)=="-")c=a.charAt(0)=="-",a=a.substring(1);d=b(a)}return e(function(a,b){var c;c=d(a);var e=d(b),f=typeof c,h=typeof e;f==h?(f=="string"&&(c=c.toLowerCase()),f==
"string"&&(e=e.toLowerCase()),c=c===e?0:c<e?-1:1):c=f<h?-1:1;return c},c)}),f=[],i=0;i<a.length;i++)f.push(a[i]);return f.sort(e(function(a,b){for(var d=0;d<c.length;d++){var e=c[d](a,b);if(e!==0)return e}return 0},d))}}function Y(b){I(b)&&(b={link:b});b.restrict=b.restrict||"AC";return Q(b)}function $b(b,a){function c(a,c){c=c?"-"+db(c,"-"):"";b.removeClass((a?Ta:Ua)+c).addClass((a?Ua:Ta)+c)}var d=this,e=b.parent().controller("form")||Va,f=0,i=d.$error={},h=[];d.$name=a.name;d.$dirty=!1;d.$pristine=
!0;d.$valid=!0;d.$invalid=!1;e.$addControl(d);b.addClass(oa);c(!0);d.$addControl=function(a){h.push(a);a.$name&&!d.hasOwnProperty(a.$name)&&(d[a.$name]=a)};d.$removeControl=function(a){a.$name&&d[a.$name]===a&&delete d[a.$name];o(i,function(b,c){d.$setValidity(c,!0,a)});sa(h,a)};d.$setValidity=function(a,b,h){var k=i[a];if(b){if(k&&(sa(k,h),!k.length)){f--;if(!f)c(b),d.$valid=!0,d.$invalid=!1;i[a]=!1;c(!0,a);e.$setValidity(a,!0,d)}}else{f||c(b);if(k){if(Ga(k,h)!=-1)return}else i[a]=k=[],f++,c(!1,
a),e.$setValidity(a,!1,d);k.push(h);d.$valid=!1;d.$invalid=!0}};d.$setDirty=function(){b.removeClass(oa).addClass(Wa);d.$dirty=!0;d.$pristine=!1;e.$setDirty()};d.$setPristine=function(){b.removeClass(Wa).addClass(oa);d.$dirty=!1;d.$pristine=!0;o(h,function(a){a.$setPristine()})}}function U(b){return u(b)||b===""||b===null||b!==b}function Xa(b,a,c,d,e,f){var i=function(){var e=a.val();if(Ha(c.ngTrim||"T"))e=S(e);d.$viewValue!==e&&b.$apply(function(){d.$setViewValue(e)})};if(e.hasEvent("input"))a.bind("input",
i);else{var h;a.bind("keydown",function(a){a=a.keyCode;a===91||15<a&&a<19||37<=a&&a<=40||h||(h=f.defer(function(){i();h=null}))});a.bind("change",i)}d.$render=function(){a.val(U(d.$viewValue)?"":d.$viewValue)};var j=c.ngPattern,g=function(a,b){return U(b)||a.test(b)?(d.$setValidity("pattern",!0),b):(d.$setValidity("pattern",!1),s)};j&&(j.match(/^\/(.*)\/$/)?(j=RegExp(j.substr(1,j.length-2)),e=function(a){return g(j,a)}):e=function(a){var c=b.$eval(j);if(!c||!c.test)throw Error("Expected "+j+" to be a RegExp but was "+
c);return g(c,a)},d.$formatters.push(e),d.$parsers.push(e));if(c.ngMinlength){var m=K(c.ngMinlength),e=function(a){return!U(a)&&a.length<m?(d.$setValidity("minlength",!1),s):(d.$setValidity("minlength",!0),a)};d.$parsers.push(e);d.$formatters.push(e)}if(c.ngMaxlength){var k=K(c.ngMaxlength),e=function(a){return!U(a)&&a.length>k?(d.$setValidity("maxlength",!1),s):(d.$setValidity("maxlength",!0),a)};d.$parsers.push(e);d.$formatters.push(e)}}function pb(b,a){b="ngClass"+b;return Y(function(c,d,e){function f(b){if(a===
!0||c.$index%2===a)j&&b!==j&&i(j),h(b);j=b}function i(a){L(a)&&!C(a)&&(a=$a(a,function(a,b){if(a)return b}));d.removeClass(C(a)?a.join(" "):a)}function h(a){L(a)&&!C(a)&&(a=$a(a,function(a,b){if(a)return b}));a&&d.addClass(C(a)?a.join(" "):a)}var j=s;c.$watch(e[b],f,!0);e.$observe("class",function(){var a=c.$eval(e[b]);f(a,a)});b!=="ngClass"&&c.$watch("$index",function(d,f){var j=d%2;j!==f%2&&(j==a?h(c.$eval(e[b])):i(c.$eval(e[b])))})})}var J=function(b){return x(b)?b.toLowerCase():b},na=function(b){return x(b)?
b.toUpperCase():b},X=K((/msie (\d+)/.exec(J(navigator.userAgent))||[])[1]),v,ca,ka=[].slice,Ya=[].push,Da=Object.prototype.toString,hc=M.angular,Ia=M.angular||(M.angular={}),xa,jb,Z=["0","0","0"];t.$inject=[];pa.$inject=[];jb=X<9?function(b){b=b.nodeName?b:b[0];return b.scopeName&&b.scopeName!="HTML"?na(b.scopeName+":"+b.nodeName):b.nodeName}:function(b){return b.nodeName?b.nodeName:b[0].nodeName};var nc=/[A-Z]/g,md={full:"1.1.4",major:1,minor:1,dot:4,codeName:"quantum-manipulation"},La=P.cache={},
Ka=P.expando="ng-"+(new Date).getTime(),rc=1,ac=M.document.addEventListener?function(b,a,c){b.addEventListener(a,c,!1)}:function(b,a,c){b.attachEvent("on"+a,c)},ib=M.document.removeEventListener?function(b,a,c){b.removeEventListener(a,c,!1)}:function(b,a,c){b.detachEvent("on"+a,c)},pc=/([\:\-\_]+(.))/g,qc=/^moz([A-Z])/,za=P.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;V.readyState==="complete"?setTimeout(a):(this.bind("DOMContentLoaded",a),P(M).bind("load",a))},toString:function(){var b=
[];o(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return b>=0?v(this[b]):v(this[this.length+b])},length:0,push:Ya,sort:[].sort,splice:[].splice},Oa={};o("multiple,selected,checked,disabled,readOnly,required,open".split(","),function(b){Oa[J(b)]=b});var Eb={};o("input,select,option,textarea,button,form,details".split(","),function(b){Eb[na(b)]=!0});o({data:zb,inheritedData:Na,scope:function(b){return Na(b,"$scope")},controller:Cb,injector:function(b){return Na(b,"$injector")},
removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Ma,css:function(b,a,c){a=Ja(a);if(w(c))b.style[a]=c;else{var d;X<=8&&(d=b.currentStyle&&b.currentStyle[a],d===""&&(d="auto"));d=d||b.style[a];X<=8&&(d=d===""?s:d);return d}},attr:function(b,a,c){var d=J(a);if(Oa[d])if(w(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||t).specified?d:s;else if(w(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),b===null?
s:b},prop:function(b,a,c){if(w(c))b[a]=c;else return b[a]},text:y(X<9?function(b,a){if(b.nodeType==1){if(u(a))return b.innerText;b.innerText=a}else{if(u(a))return b.nodeValue;b.nodeValue=a}}:function(b,a){if(u(a))return b.textContent;b.textContent=a},{$dv:""}),val:function(b,a){if(u(a))return b.value;b.value=a},html:function(b,a){if(u(a))return b.innerHTML;for(var c=0,d=b.childNodes;c<d.length;c++)wa(d[c]);b.innerHTML=a}},function(b,a){P.prototype[a]=function(a,d){var e,f;if((b.length==2&&b!==Ma&&
b!==Cb?a:d)===s)if(L(a)){for(e=0;e<this.length;e++)if(b===zb)b(this[e],a);else for(f in a)b(this[e],f,a[f]);return this}else{if(this.length)return b(this[0],a,d)}else{for(e=0;e<this.length;e++)b(this[e],a,d);return this}return b.$dv}});o({removeData:xb,dealoc:wa,bind:function a(c,d,e){var f=$(c,"events"),i=$(c,"handle");f||$(c,"events",f={});i||$(c,"handle",i=sc(c,f));o(d.split(" "),function(d){var j=f[d];if(!j){if(d=="mouseenter"||d=="mouseleave"){var g=0;f.mouseenter=[];f.mouseleave=[];a(c,"mouseover",
function(a){g++;g==1&&i(a,"mouseenter")});a(c,"mouseout",function(a){g--;g==0&&i(a,"mouseleave")})}else ac(c,d,i),f[d]=[];j=f[d]}j.push(e)})},unbind:yb,replaceWith:function(a,c){var d,e=a.parentNode;wa(a);o(new P(c),function(c){d?e.insertBefore(c,d.nextSibling):e.replaceChild(c,a);d=c})},children:function(a){var c=[];o(a.childNodes,function(a){a.nodeType===1&&c.push(a)});return c},contents:function(a){return a.childNodes||[]},append:function(a,c){o(new P(c),function(c){(a.nodeType===1||a.nodeType===
11)&&a.appendChild(c)})},prepend:function(a,c){if(a.nodeType===1){var d=a.firstChild;o(new P(c),function(c){d?a.insertBefore(c,d):(a.appendChild(c),d=c)})}},wrap:function(a,c){var c=v(c)[0],d=a.parentNode;d&&d.replaceChild(c,a);c.appendChild(a)},remove:function(a){wa(a);var c=a.parentNode;c&&c.removeChild(a)},after:function(a,c){var d=a,e=a.parentNode;o(new P(c),function(a){e.insertBefore(a,d.nextSibling);d=a})},addClass:Bb,removeClass:Ab,toggleClass:function(a,c,d){u(d)&&(d=!Ma(a,c));(d?Bb:Ab)(a,
c)},parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},next:function(a){if(a.nextElementSibling)return a.nextElementSibling;for(a=a.nextSibling;a!=null&&a.nodeType!==1;)a=a.nextSibling;return a},find:function(a,c){return a.getElementsByTagName(c)},clone:hb,triggerHandler:function(a,c){var d=($(a,"events")||{})[c];o(d,function(c){c.call(a,null)})}},function(a,c){P.prototype[c]=function(c,e){for(var f,i=0;i<this.length;i++)f==s?(f=a(this[i],c,e),f!==s&&(f=v(f))):gb(f,a(this[i],c,e));
return f==s?this:f}});Pa.prototype={put:function(a,c){this[la(a)]=c},get:function(a){return this[la(a)]},remove:function(a){var c=this[a=la(a)];delete this[a];return c}};var uc=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,vc=/,/,wc=/^\s*(_?)(\S+?)\1\s*$/,tc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;Gb.$inject=["$provide"];var nd=function(){this.$get=["$animation","$window","$sniffer",function(a,c,d){function e(a){a.css("display","")}function f(a){a.css("display","none")}function i(a,c,d){d?d.after(a):c.append(a)}
function h(a){a.remove()}function j(a,c,d){i(a,c,d)}return function(g,m){function k(e,f,h){var i=l&&g.$eval(l),e=l?L(i)?i[e]:i+"-"+e:"",j=(i=a(e))&&i.setup,k=i&&i.start;if(e){var m=e+"-setup",q=e+"-start";return function(a,e,g){function i(){h(a,e,g);a.removeClass(m);a.removeClass(q)}if(!d.supportsTransitions&&!j&&!k)f(a,e,g),h(a,e,g);else{a.addClass(m);f(a,e,g);if(a.length==0)return i();var l=(j||t)(a);c.setTimeout(function(){a.addClass(q);if(k)k(a,i,l);else if(I(c.getComputedStyle)){var e=d.vendorPrefix+
"Transition",f=0;o(a,function(a){a=c.getComputedStyle(a)||{};f=Math.max(parseFloat(a.transitionDuration)||parseFloat(a[e+"Duration"])||0,f)});c.setTimeout(i,f*1E3)}else i()},1)}}}else return function(a,c,d){f(a,c,d);h(a,c,d)}}var l=m.ngAnimate,q={};q.enter=k("enter",i,t);q.leave=k("leave",t,h);q.move=k("move",j,t);q.show=k("show",e,t);q.hide=k("hide",t,f);return q}}]},Ib="Non-assignable model expression: ";Hb.$inject=["$provide"];var Cc=/^(x[\:\-_]|data[\:\-_])/i,lb=/^([^:]+):\/\/(\w+:{0,1}\w*@)?(\{?[\w\.-]*\}?)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/,
bc=/^([^\?#]*)?(\?([^#]*))?(#(.*))?$/,Jc=bc,Ba={http:80,https:443,ftp:21};mb.prototype={$$replace:!1,absUrl:Ra("$$absUrl"),url:function(a,c){if(u(a))return this.$$url;var d=bc.exec(a);d[1]&&this.path(decodeURIComponent(d[1]));if(d[2]||d[1])this.search(d[3]||"");this.hash(d[5]||"",c);return this},protocol:Ra("$$protocol"),host:Ra("$$host"),port:Ra("$$port"),path:Mb("$$path",function(a){return a.charAt(0)=="/"?a:"/"+a}),search:function(a,c){if(u(a))return this.$$search;w(c)?c===null?delete this.$$search[a]:
this.$$search[a]=c:this.$$search=x(a)?bb(a):a;this.$$compose();return this},hash:Mb("$$hash",pa),replace:function(){this.$$replace=!0;return this}};Qa.prototype=Fa(mb.prototype);Lb.prototype=Fa(Qa.prototype);var Ca={"null":function(){return null},"true":function(){return!0},"false":function(){return!1},undefined:t,"+":function(a,c,d,e){d=d(a,c);e=e(a,c);return w(d)?w(e)?d+e:d:w(e)?e:s},"-":function(a,c,d,e){d=d(a,c);e=e(a,c);return(w(d)?d:0)-(w(e)?e:0)},"*":function(a,c,d,e){return d(a,c)*e(a,c)},
"/":function(a,c,d,e){return d(a,c)/e(a,c)},"%":function(a,c,d,e){return d(a,c)%e(a,c)},"^":function(a,c,d,e){return d(a,c)^e(a,c)},"=":t,"===":function(a,c,d,e){return d(a,c)===e(a,c)},"!==":function(a,c,d,e){return d(a,c)!==e(a,c)},"==":function(a,c,d,e){return d(a,c)==e(a,c)},"!=":function(a,c,d,e){return d(a,c)!=e(a,c)},"<":function(a,c,d,e){return d(a,c)<e(a,c)},">":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,
c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"&":function(a,c,d,e){return d(a,c)&e(a,c)},"|":function(a,c,d,e){return e(a,c)(a,c,d(a,c))},"!":function(a,c,d){return!d(a,c)}},Nc={n:"\n",f:"\u000c",r:"\r",t:"\t",v:"\u000b","'":"'",'"':'"'},nb={},Yc=/^(([^:]+):)?\/\/(\w+:{0,1}\w*@)?([\w\.-]*)?(:([0-9]+))?(.*)$/,bd=M.XMLHttpRequest||function(){try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(a){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(c){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(d){}throw Error("This browser does not support XMLHttpRequest.");
};Tb.$inject=["$provide"];Ub.$inject=["$locale"];Wb.$inject=["$locale"];var Zb=".",ld={yyyy:O("FullYear",4),yy:O("FullYear",2,0,!0),y:O("FullYear",1),MMMM:Sa("Month"),MMM:Sa("Month",!0),MM:O("Month",2,1),M:O("Month",1,1),dd:O("Date",2),d:O("Date",1),HH:O("Hours",2),H:O("Hours",1),hh:O("Hours",2,-12),h:O("Hours",1,-12),mm:O("Minutes",2),m:O("Minutes",1),ss:O("Seconds",2),s:O("Seconds",1),sss:O("Milliseconds",3),EEEE:Sa("Day"),EEE:Sa("Day",!0),a:function(a,c){return a.getHours()<12?c.AMPMS[0]:c.AMPMS[1]},
Z:function(a){var a=-1*a.getTimezoneOffset(),c=a>=0?"+":"";c+=ob(Math[a>0?"floor":"ceil"](a/60),2)+ob(Math.abs(a%60),2);return c}},kd=/((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,jd=/^\d+$/;Vb.$inject=["$locale"];var hd=Q(J),id=Q(na);Xb.$inject=["$parse"];var od=Q({restrict:"E",compile:function(a,c){X<=8&&(!c.href&&!c.name&&c.$set("href",""),a.append(V.createComment("IE fix")));return function(a,c){c.bind("click",function(a){c.attr("href")||a.preventDefault()})}}}),
qb={};o(Oa,function(a,c){var d=aa("ng-"+c);qb[d]=function(){return{priority:100,compile:function(){return function(a,f,i){a.$watch(i[d],function(a){i.$set(c,!!a)})}}}}});o(["src","href"],function(a){var c=aa("ng-"+a);qb[c]=function(){return{priority:99,link:function(d,e,f){f.$observe(c,function(c){c&&(f.$set(a,c),X&&e.prop(a,f[a]))})}}}});var Va={$addControl:t,$removeControl:t,$setValidity:t,$setDirty:t,$setPristine:t};$b.$inject=["$element","$attrs","$scope"];var Ya=function(a){return["$timeout",
function(c){var d={name:"form",restrict:"E",controller:$b,compile:function(){return{pre:function(a,d,i,h){if(!i.action){var j=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1};ac(d[0],"submit",j);d.bind("$destroy",function(){c(function(){ib(d[0],"submit",j)},0,!1)})}var g=d.parent().controller("form"),m=i.name||i.ngForm;m&&(a[m]=h);g&&d.bind("$destroy",function(){g.$removeControl(h);m&&(a[m]=s);y(h,Va)})}}}};return a?y(W(d),{restrict:"EAC"}):d}]},pd=Ya(),qd=Ya(!0),rd=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,
sd=/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/,td=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,cc={text:Xa,number:function(a,c,d,e,f,i){Xa(a,c,d,e,f,i);e.$parsers.push(function(a){var c=U(a);return c||td.test(a)?(e.$setValidity("number",!0),a===""?null:c?a:parseFloat(a)):(e.$setValidity("number",!1),s)});e.$formatters.push(function(a){return U(a)?"":""+a});if(d.min){var h=parseFloat(d.min),a=function(a){return!U(a)&&a<h?(e.$setValidity("min",!1),s):(e.$setValidity("min",!0),a)};e.$parsers.push(a);
e.$formatters.push(a)}if(d.max){var j=parseFloat(d.max),d=function(a){return!U(a)&&a>j?(e.$setValidity("max",!1),s):(e.$setValidity("max",!0),a)};e.$parsers.push(d);e.$formatters.push(d)}e.$formatters.push(function(a){return U(a)||Za(a)?(e.$setValidity("number",!0),a):(e.$setValidity("number",!1),s)})},url:function(a,c,d,e,f,i){Xa(a,c,d,e,f,i);a=function(a){return U(a)||rd.test(a)?(e.$setValidity("url",!0),a):(e.$setValidity("url",!1),s)};e.$formatters.push(a);e.$parsers.push(a)},email:function(a,
c,d,e,f,i){Xa(a,c,d,e,f,i);a=function(a){return U(a)||sd.test(a)?(e.$setValidity("email",!0),a):(e.$setValidity("email",!1),s)};e.$formatters.push(a);e.$parsers.push(a)},radio:function(a,c,d,e){u(d.name)&&c.attr("name",Ea());c.bind("click",function(){c[0].checked&&a.$apply(function(){e.$setViewValue(d.value)})});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e){var f=d.ngTrueValue,i=d.ngFalseValue;x(f)||(f=!0);x(i)||(i=!1);c.bind("click",
function(){a.$apply(function(){e.$setViewValue(c[0].checked)})});e.$render=function(){c[0].checked=e.$viewValue};e.$formatters.push(function(a){return a===f});e.$parsers.push(function(a){return a?f:i})},hidden:t,button:t,submit:t,reset:t},dc=["$browser","$sniffer",function(a,c){return{restrict:"E",require:"?ngModel",link:function(d,e,f,i){i&&(cc[J(f.type)]||cc.text)(d,e,f,i,c,a)}}}],Ua="ng-valid",Ta="ng-invalid",oa="ng-pristine",Wa="ng-dirty",ud=["$scope","$exceptionHandler","$attrs","$element","$parse",
function(a,c,d,e,f){function i(a,c){c=c?"-"+db(c,"-"):"";e.removeClass((a?Ta:Ua)+c).addClass((a?Ua:Ta)+c)}this.$modelValue=this.$viewValue=Number.NaN;this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$name=d.name;var h=f(d.ngModel),j=h.assign;if(!j)throw Error(Ib+d.ngModel+" ("+ta(e)+")");this.$render=t;var g=e.inheritedData("$formController")||Va,m=0,k=this.$error={};e.addClass(oa);i(!0);this.$setValidity=function(a,
c){if(k[a]!==!c){if(c){if(k[a]&&m--,!m)i(!0),this.$valid=!0,this.$invalid=!1}else i(!1),this.$invalid=!0,this.$valid=!1,m++;k[a]=!c;i(c,a);g.$setValidity(a,c,this)}};this.$setPristine=function(){this.$dirty=!1;this.$pristine=!0;e.removeClass(Wa).addClass(oa)};this.$setViewValue=function(d){this.$viewValue=d;if(this.$pristine)this.$dirty=!0,this.$pristine=!1,e.removeClass(oa).addClass(Wa),g.$setDirty();o(this.$parsers,function(a){d=a(d)});if(this.$modelValue!==d)this.$modelValue=d,j(a,d),o(this.$viewChangeListeners,
function(a){try{a()}catch(d){c(d)}})};var l=this;a.$watch(function(){var c=h(a);if(l.$modelValue!==c){var d=l.$formatters,e=d.length;for(l.$modelValue=c;e--;)c=d[e](c);if(l.$viewValue!==c)l.$viewValue=c,l.$render()}})}],vd=function(){return{require:["ngModel","^?form"],controller:ud,link:function(a,c,d,e){var f=e[0],i=e[1]||Va;i.$addControl(f);c.bind("$destroy",function(){i.$removeControl(f)})}}},wd=Q({require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),
ec=function(){return{require:"?ngModel",link:function(a,c,d,e){if(e){d.required=!0;var f=function(a){if(d.required&&(U(a)||a===!1))e.$setValidity("required",!1);else return e.$setValidity("required",!0),a};e.$formatters.push(f);e.$parsers.unshift(f);d.$observe("required",function(){f(e.$viewValue)})}}}},xd=function(){return{require:"ngModel",link:function(a,c,d,e){var f=(a=/\/(.*)\//.exec(d.ngList))&&RegExp(a[1])||d.ngList||",";e.$parsers.push(function(a){var c=[];a&&o(a.split(f),function(a){a&&c.push(S(a))});
return c});e.$formatters.push(function(a){return C(a)?a.join(", "):s})}}},yd=/^(true|false|\d+)$/,zd=function(){return{priority:100,compile:function(a,c){return yd.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value",a,!1)})}}}},Ad=Y(function(a,c,d){c.addClass("ng-binding").data("$binding",d.ngBind);a.$watch(d.ngBind,function(a){c.text(a==s?"":a)})}),Bd=["$interpolate",function(a){return function(c,d,e){c=a(d.attr(e.$attr.ngBindTemplate));
d.addClass("ng-binding").data("$binding",c);e.$observe("ngBindTemplate",function(a){d.text(a)})}}],Cd=[function(){return function(a,c,d){c.addClass("ng-binding").data("$binding",d.ngBindHtmlUnsafe);a.$watch(d.ngBindHtmlUnsafe,function(a){c.html(a||"")})}}],Dd=pb("",!0),Ed=pb("Odd",0),Fd=pb("Even",1),Gd=Y({compile:function(a,c){c.$set("ngCloak",s);a.removeClass("ng-cloak")}}),Hd=[function(){return{scope:!0,controller:"@"}}],Id=["$sniffer",function(a){return{priority:1E3,compile:function(){a.csp=!0}}}],
fc={};o("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress".split(" "),function(a){var c=aa("ng-"+a);fc[c]=["$parse",function(d){return function(e,f,i){var h=d(i[c]);f.bind(J(a),function(a){e.$apply(function(){h(e,{$event:a})})})}}]});var Jd=Y(function(a,c,d){c.bind("submit",function(){a.$apply(d.ngSubmit)})}),Kd=["$http","$templateCache","$anchorScroll","$compile","$animator",function(a,c,d,e,f){return{restrict:"ECA",terminal:!0,compile:function(i,
h){var j=h.ngInclude||h.src,g=h.onload||"",m=h.autoscroll;return function(h,i,o){var n=f(h,o),s=0,r,p=function(){r&&(r.$destroy(),r=null);n.leave(i.contents(),i)};h.$watch(j,function(f){var j=++s;f?a.get(f,{cache:c}).success(function(a){j===s&&(r&&r.$destroy(),r=h.$new(),n.leave(i.contents(),i),a=v("<div/>").html(a).contents(),n.enter(a,i),e(a)(r),w(m)&&(!m||h.$eval(m))&&d(),r.$emit("$includeContentLoaded"),h.$eval(g))}).error(function(){j===s&&p()}):p()})}}}}],Ld=Y({compile:function(){return{pre:function(a,
c,d){a.$eval(d.ngInit)}}}}),Md=Y({terminal:!0,priority:1E3}),Nd=["$locale","$interpolate",function(a,c){var d=/{}/g;return{restrict:"EA",link:function(e,f,i){var h=i.count,j=f.attr(i.$attr.when),g=i.offset||0,m=e.$eval(j),k={},l=c.startSymbol(),q=c.endSymbol();o(m,function(a,e){k[e]=c(a.replace(d,l+h+"-"+g+q))});e.$watch(function(){var c=parseFloat(e.$eval(h));return isNaN(c)?"":(m[c]||(c=a.pluralCat(c-g)),k[c](e,f,!0))},function(a){f.text(a)})}}}],Od=["$parse","$animator",function(a,c){return{transclude:"element",
priority:1E3,terminal:!0,compile:function(d,e,f){return function(d,e,j){var g=c(d,j),m=j.ngRepeat,k=m.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/),l,q,n,s,r,p={$id:la};if(!k)throw Error("Expected ngRepeat in form of '_item_ in _collection_[ track by _id_]' but got '"+m+"'.");j=k[1];n=k[2];(k=k[4])?(l=a(k),q=function(a,c,e){r&&(p[r]=a);p[s]=c;p.$index=e;return l(d,p)}):q=function(a,c){return la(c)};k=j.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);if(!k)throw Error("'item' in 'item in collection' should be identifier or (key, value) but got '"+
j+"'.");s=k[3]||k[1];r=k[2];var y={};d.$watchCollection(n,function(a){var c,j,k=e,l,n={},p,t,v,z,w,u,x=[];if(C(a))w=a;else{w=[];for(v in a)a.hasOwnProperty(v)&&v.charAt(0)!="$"&&w.push(v);w.sort()}p=w.length;j=x.length=w.length;for(c=0;c<j;c++)if(v=a===w?c:w[c],z=a[v],l=q(v,z,c),u=y[l])delete y[l],n[l]=u,x[c]=u;else if(n.hasOwnProperty(l))throw o(x,function(a){a&&a.element&&(y[a.id]=a)}),Error("Duplicates in a repeater are not allowed. Repeater: "+m);else x[c]={id:l};for(v in y)if(y.hasOwnProperty(v))u=
y[v],g.leave(u.element),u.element[0].$$NG_REMOVED=!0,u.scope.$destroy();c=0;for(j=w.length;c<j;c++){v=a===w?c:w[c];z=a[v];u=x[c];if(u.element){t=u.scope;l=k[0];do l=l.nextSibling;while(l&&l.$$NG_REMOVED);u.element[0]!=l&&g.move(u.element,null,k);k=u.element}else t=d.$new();t[s]=z;r&&(t[r]=v);t.$index=c;t.$first=c===0;t.$last=c===p-1;t.$middle=!(t.$first||t.$last);u.element||f(t,function(a){g.enter(a,null,k);k=a;u.scope=t;u.element=a;n[u.id]=u})}y=n})}}}}],Pd=["$animator",function(a){return function(c,
d,e){var f=a(c,e);c.$watch(e.ngShow,function(a){f[Ha(a)?"show":"hide"](d)})}}],Qd=["$animator",function(a){return function(c,d,e){var f=a(c,e);c.$watch(e.ngHide,function(a){f[Ha(a)?"hide":"show"](d)})}}],Rd=Y(function(a,c,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&o(d,function(a,d){c.css(d,"")});a&&c.css(a)},!0)}),Sd=["$animator",function(a){return{restrict:"EA",require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(c,d,e,f){var i=a(c,e),h,j,g=[];c.$watch(e.ngSwitch||
e.on,function(a){for(var d=0,l=g.length;d<l;d++)g[d].$destroy(),i.leave(j[d]);j=[];g=[];if(h=f.cases["!"+a]||f.cases["?"])c.$eval(e.change),o(h,function(a){var d=c.$new();g.push(d);a.transclude(d,function(c){var d=a.element;j.push(c);i.enter(c,d.parent(),d)})})})}}}],Td=Y({transclude:"element",priority:500,require:"^ngSwitch",compile:function(a,c,d){return function(a,f,i,h){h.cases["!"+c.ngSwitchWhen]=h.cases["!"+c.ngSwitchWhen]||[];h.cases["!"+c.ngSwitchWhen].push({transclude:d,element:f})}}}),Ud=
Y({transclude:"element",priority:500,require:"^ngSwitch",compile:function(a,c,d){return function(a,c,i,h){h.cases["?"]=h.cases["?"]||[];h.cases["?"].push({transclude:d,element:c})}}}),Vd=Y({controller:["$transclude","$element",function(a,c){a(function(a){c.append(a)})}]}),Wd=["$http","$templateCache","$route","$anchorScroll","$compile","$controller","$animator",function(a,c,d,e,f,i,h){return{restrict:"ECA",terminal:!0,link:function(a,c,m){function k(){var h=d.current&&d.current.locals,k=h&&h.$template;
if(k){n.leave(c.contents(),c);l&&(l.$destroy(),l=null);n.enter(v("<div></div>").html(k).contents(),c);var k=f(c.contents()),m=d.current;l=m.scope=a.$new();if(m.controller)h.$scope=l,h=i(m.controller,h),c.children().data("$ngControllerController",h);k(l);l.$emit("$viewContentLoaded");l.$eval(o);e()}else n.leave(c.contents(),c),l&&(l.$destroy(),l=null)}var l,o=m.onload||"",n=h(a,m);a.$on("$routeChangeSuccess",k);k()}}}],Xd=["$templateCache",function(a){return{restrict:"E",terminal:!0,compile:function(c,
d){d.type=="text/ng-template"&&a.put(d.id,c[0].text)}}}],Yd=Q({terminal:!0}),Zd=["$compile","$parse",function(a,c){var d=/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*)$/,e={$setViewValue:t};return{restrict:"E",require:["select","?ngModel"],controller:["$element","$scope","$attrs",function(a,c,d){var j=this,g={},m=e,k;j.databound=d.ngModel;j.init=function(a,c,d){m=a;k=d};j.addOption=function(c){g[c]=
!0;m.$viewValue==c&&(a.val(c),k.parent()&&k.remove())};j.removeOption=function(a){this.hasOption(a)&&(delete g[a],m.$viewValue==a&&this.renderUnknownOption(a))};j.renderUnknownOption=function(c){c="? "+la(c)+" ?";k.val(c);a.prepend(k);a.val(c);k.prop("selected",!0)};j.hasOption=function(a){return g.hasOwnProperty(a)};c.$on("$destroy",function(){j.renderUnknownOption=t})}],link:function(e,i,h,j){function g(a,c,d,e){d.$render=function(){var a=d.$viewValue;e.hasOption(a)?(x.parent()&&x.remove(),c.val(a),
a===""&&p.prop("selected",!0)):u(a)&&p?c.val(""):e.renderUnknownOption(a)};c.bind("change",function(){a.$apply(function(){x.parent()&&x.remove();d.$setViewValue(c.val())})})}function m(a,c,d){var e;d.$render=function(){var a=new Pa(d.$viewValue);o(c.find("option"),function(c){c.selected=w(a.get(c.value))})};a.$watch(function(){ja(e,d.$viewValue)||(e=W(d.$viewValue),d.$render())});c.bind("change",function(){a.$apply(function(){var a=[];o(c.find("option"),function(c){c.selected&&a.push(c.value)});d.$setViewValue(a)})})}
function k(e,f,h){function g(){var a={"":[]},c=[""],d,i,t,v,u;t=h.$modelValue;v=p(e)||[];var w=l?rb(v):v,z,x,A;x={};u=!1;var B,C;if(n)u=new Pa(t);else if(t===null||r)a[""].push({selected:t===null,id:"",label:""}),u=!0;for(A=0;z=w.length,A<z;A++){x[k]=v[l?x[l]=w[A]:A];d=m(e,x)||"";if(!(i=a[d]))i=a[d]=[],c.push(d);n?d=u.remove(o(e,x))!=s:(d=t===o(e,x),u=u||d);B=j(e,x);B=B===s?"":B;i.push({id:l?w[A]:A,label:B,selected:d})}!n&&!u&&a[""].unshift({id:"?",label:"",selected:!0});x=0;for(w=c.length;x<w;x++){d=
c[x];i=a[d];if(q.length<=x)t={element:D.clone().attr("label",d),label:i.label},v=[t],q.push(v),f.append(t.element);else if(v=q[x],t=v[0],t.label!=d)t.element.attr("label",t.label=d);B=null;A=0;for(z=i.length;A<z;A++)if(d=i[A],u=v[A+1]){B=u.element;if(u.label!==d.label)B.text(u.label=d.label);if(u.id!==d.id)B.val(u.id=d.id);if(u.element.selected!==d.selected)B.prop("selected",u.selected=d.selected)}else d.id===""&&r?C=r:(C=y.clone()).val(d.id).attr("selected",d.selected).text(d.label),v.push({element:C,
label:d.label,id:d.id,selected:d.selected}),B?B.after(C):t.element.append(C),B=C;for(A++;v.length>A;)v.pop().element.remove()}for(;q.length>x;)q.pop()[0].element.remove()}var i;if(!(i=t.match(d)))throw Error("Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_' but got '"+t+"'.");var j=c(i[2]||i[1]),k=i[4]||i[6],l=i[5],m=c(i[3]||""),o=c(i[2]?i[1]:k),p=c(i[7]),q=[[{element:f,label:""}]];r&&(a(r)(e),r.removeClass("ng-scope"),r.remove());f.html("");f.bind("change",
function(){e.$apply(function(){var a,c=p(e)||[],d={},g,i,j,m,r,t;if(n){i=[];m=0;for(t=q.length;m<t;m++){a=q[m];j=1;for(r=a.length;j<r;j++)if((g=a[j].element)[0].selected)g=g.val(),l&&(d[l]=g),d[k]=c[g],i.push(o(e,d))}}else g=f.val(),g=="?"?i=s:g==""?i=null:(d[k]=c[g],l&&(d[l]=g),i=o(e,d));h.$setViewValue(i)})});h.$render=g;e.$watch(g)}if(j[1]){for(var l=j[0],q=j[1],n=h.multiple,t=h.ngOptions,r=!1,p,y=v(V.createElement("option")),D=v(V.createElement("optgroup")),x=y.clone(),j=0,C=i.children(),A=C.length;j<
A;j++)if(C[j].value==""){p=r=C.eq(j);break}l.init(q,r,x);if(n&&(h.required||h.ngRequired)){var H=function(a){q.$setValidity("required",!h.required||a&&a.length);return a};q.$parsers.push(H);q.$formatters.unshift(H);h.$observe("required",function(){H(q.$viewValue)})}t?k(e,i,q):n?m(e,i,q):g(e,i,q,l)}}}}],$d=["$interpolate",function(a){var c={addOption:t,removeOption:t};return{restrict:"E",priority:100,compile:function(d,e){if(u(e.value)){var f=a(d.text(),!0);f||e.$set("value",d.text())}return function(a,
d,e){var g=d.parent(),m=g.data("$selectController")||g.parent().data("$selectController");m&&m.databound?d.prop("selected",!1):m=c;f?a.$watch(f,function(a,c){e.$set("value",a);a!==c&&m.removeOption(c);m.addOption(a)}):m.addOption(e.value);d.bind("$destroy",function(){m.removeOption(e.value)})}}}}],ae=Q({restrict:"E",terminal:!0});(ca=M.jQuery)?(v=ca,y(ca.fn,{scope:za.scope,controller:za.controller,injector:za.injector,inheritedData:za.inheritedData}),fb("remove",!0),fb("empty"),fb("html")):v=P;Ia.element=
v;(function(a){y(a,{bootstrap:vb,copy:W,extend:y,equals:ja,element:v,forEach:o,injector:wb,noop:t,bind:ab,toJson:da,fromJson:tb,identity:pa,isUndefined:u,isDefined:w,isString:x,isFunction:I,isObject:L,isNumber:Za,isElement:jc,isArray:C,version:md,isDate:qa,lowercase:J,uppercase:na,callbacks:{counter:0},noConflict:gc});xa=oc(M);try{xa("ngLocale")}catch(c){xa("ngLocale",[]).provider("$locale",cd)}xa("ng",["ngLocale"],["$provide",function(a){a.provider("$compile",Hb).directive({a:od,input:dc,textarea:dc,
form:pd,script:Xd,select:Zd,style:ae,option:$d,ngBind:Ad,ngBindHtmlUnsafe:Cd,ngBindTemplate:Bd,ngClass:Dd,ngClassEven:Fd,ngClassOdd:Ed,ngCsp:Id,ngCloak:Gd,ngController:Hd,ngForm:qd,ngHide:Qd,ngInclude:Kd,ngInit:Ld,ngNonBindable:Md,ngPluralize:Nd,ngRepeat:Od,ngShow:Pd,ngSubmit:Jd,ngStyle:Rd,ngSwitch:Sd,ngSwitchWhen:Td,ngSwitchDefault:Ud,ngOptions:Yd,ngView:Wd,ngTransclude:Vd,ngModel:vd,ngList:xd,ngChange:wd,required:ec,ngRequired:ec,ngValue:zd}).directive(qb).directive(fc);a.provider({$anchorScroll:xc,
$animation:Gb,$animator:nd,$browser:zc,$cacheFactory:Ac,$controller:Dc,$document:Ec,$exceptionHandler:Fc,$filter:Tb,$interpolate:Gc,$http:Zc,$httpBackend:$c,$location:Kc,$log:Lc,$parse:Pc,$route:Sc,$routeParams:Tc,$rootScope:Uc,$q:Qc,$sniffer:Vc,$templateCache:Bc,$timeout:dd,$window:Wc})}])})(Ia);v(V).ready(function(){mc(V,vb)})})(window,document);angular.element(document).find("head").append('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\:form{display:block;}</style>');

View File

@ -0,0 +1,107 @@
/*global angular:true, browser:true */
/**
* @license HTTP Auth Interceptor Module for AngularJS
* (c) 2012 Witold Szczerba
* License: MIT
*
* https://github.com/witoldsz/angular-http-auth/blob/master/README.md
*
*/
(function () {
'use strict';
angular.module('http-auth-interceptor', ['http-auth-interceptor-buffer'])
.factory('authService', ['$rootScope','httpBuffer', function($rootScope, httpBuffer) {
return {
/**
* call this function to indicate that authentication was successfull and trigger a
* retry of all deferred requests.
* @param data an optional argument to pass on to $broadcast which may be useful for
* example if you need to pass through details of the user that was logged in
*/
loginConfirmed: function(data) {
$rootScope.$broadcast('event:auth-loginConfirmed', data);
httpBuffer.retryAll();
}
};
}])
/**
* $http interceptor.
* On 401 response (without 'ignoreAuthModule' option) stores the request
* and broadcasts 'event:angular-auth-loginRequired'.
*/
.config(['$httpProvider', function($httpProvider) {
var interceptor = ['$rootScope', '$q', 'httpBuffer', function($rootScope, $q, httpBuffer) {
function success(response) {
return response;
}
function error(response) {
if (response.status === 401 && !response.config.ignoreAuthModule) {
var deferred = $q.defer();
httpBuffer.append(response.config, deferred);
$rootScope.$broadcast('event:auth-loginRequired');
return deferred.promise;
}
// otherwise, default behaviour
return $q.reject(response);
}
return function(promise) {
return promise.then(success, error);
};
}];
$httpProvider.responseInterceptors.push(interceptor);
}]);
/**
* Private module, an utility, required internally by 'http-auth-interceptor'.
*/
angular.module('http-auth-interceptor-buffer', [])
.factory('httpBuffer', ['$injector', function($injector) {
/** Holds all the requests, so they can be re-requested in future. */
var buffer = [];
/** Service initialized later because of circular dependency problem. */
var $http;
function retryHttpRequest(config, deferred) {
function successCallback(response) {
deferred.resolve(response);
}
function errorCallback(response) {
deferred.reject(response);
}
$http = $http || $injector.get('$http');
$http(config).then(successCallback, errorCallback);
}
return {
/**
* Appends HTTP request configuration object with deferred response attached to buffer.
*/
append: function(config, deferred) {
buffer.push({
config: config,
deferred: deferred
});
},
/**
* Retries all the buffered requests clears the buffer.
*/
retryAll: function() {
for (var i = 0; i < buffer.length; ++i) {
retryHttpRequest(buffer[i].config, buffer[i].deferred);
}
buffer = [];
}
};
}]);
})();

View File

@ -0,0 +1,96 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* User authentication functions
*
*/
angular.module('AuthService', ['ngCookies'])
.factory('Authorization', ['$http', '$rootScope', '$location', '$cookieStore', function($http, $rootScope, $location, $cookieStore) {
return {
setToken: function(token) {
// set the session cookie
var today = new Date();
today.setTime(today.getTime() + ($AnsibleConfig.session_timeout * 1000));
$cookieStore.remove('token');
$cookieStore.remove('token_expire');
$cookieStore.put('token', token);
$cookieStore.put('token_expire', today.getTime());
$rootScope.userLoggedIn = true;
},
isTokenValid: function() {
// check if token exists and is not expired
var response = false;
if ( $cookieStore.get('token') && $cookieStore.get('token_expire') ) {
var token = $cookieStore.get('token');
var exp = new Date($cookieStore.get('token_expire'));
var today = new Date();
if (today < exp) {
this.setToken(token); //push expiration into the future while user is active
response = true;
}
}
return response;
},
didSessionExpire: function() {
// use only to test why user was sent to login page.
var response = false;
if ($cookieStore.get('token_expire')) {
var exp = new Date($cookieStore.get('token_expire'));
var today = new Date();
if (exp < today) {
response = true;
}
}
return response;
},
getToken: function() {
if ( this.isTokenValid() ) {
return $cookieStore.get('token');
}
else {
return null;
}
},
retrieveToken: function(username, password) {
return $http({ method: 'POST', url: '/api/v1/authtoken/',
data: {"username": username, "password": password} });
},
logout: function() {
$rootScope.current_user = {};
$cookieStore.remove('token');
$cookieStore.remove('token_expire');
$cookieStore.remove('current_user');
$rootScope.userLoggedIn = false;
},
getUser: function() {
return $http({
method: 'GET',
url: '/api/v1/me/',
headers: { 'Authorization': 'Token ' + this.getToken() },
});
},
setUserInfo: function(response) {
// store the response values in $rootScope so we can get to them later
$rootScope.current_user = response.results[0];
$cookieStore.put('current_user', response.results[0]); //keep in session cookie incase user hits refresh
},
restoreUserInfo: function() {
$rootScope.current_user = $cookieStore.get('current_user');
},
getUserInfo: function(key) {
// Access values returned from the Me API call
return ($rootScope.current_user[key]) ? $rootScope.current_user[key] : null;
}
}
}]);

View File

@ -0,0 +1,56 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Custom directives for form validation
*
*/
angular.module('AWDirectives', [])
// awpassmatch: Add to password_confirm field. Will test if value
// matches that of 'input[name="password"]'
.directive('awpassmatch', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift( function(viewValue) {
var password = $('input[name="password"]').val();
if (viewValue == password) {
// it is valid
ctrl.$setValidity('awpassmatch', true);
return viewValue;
} else {
// it is invalid, return undefined (no model update)
ctrl.$setValidity('awpassmatch', false);
return undefined;
}
});
}
}
})
// caplitalize Add to any input field where the first letter of each
// word should be capitalized. Use in place of css test-transform.
// For some reason "text-transform: capitalize" in breadcrumbs
// causes a break at each blank space. And of course,
// "autocapitalize='word'" only works in iOS. Use this as a fix.
.directive('capitalize', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift( function(viewValue) {
var values = viewValue.split(" ");
var result = "";
for (i = 0; i < values.length; i++){
result += values[i].charAt(0).toUpperCase() + values[i].substr(1) + ' ';
}
result = result.trim();
if (result != viewValue) {
ctrl.$setViewValue(result);
ctrl.$render();
}
return result;
});
}
}
});

View File

@ -0,0 +1,22 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Custom filters
*
*/
angular.module('AWFilters', [])
//
// capitalize -capitalize the first letter of each word
//
.filter('capitalize', function() {
return function(input) {
var values = input.split(" ");
var result = "";
for (i = 0; i < values.length; i++){
result += values[i].charAt(0).toUpperCase() + values[i].substr(1) + ' ';
}
result = result.trim();
return result;
}
});

View File

@ -0,0 +1,404 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* FormGenerator
* Pass in a form definition from FormDefinitions and out pops an html template.
* See js/form-definitions.js for form example. For now produces a Twitter Bootstrap
* horizontal form.
*
*/
angular.module('FormGenerator', ['GeneratorHelpers'])
.factory('GenerateForm', [ '$compile', 'SearchWidget', 'PaginateWidget', function($compile, SearchWidget, PaginateWidget) {
return {
setForm: function(form) {
this.form = form;
},
attr: function(obj, key) {
var result;
switch(key) {
case 'ngClick':
result = "ng-click=\"" + obj[key] + "\" ";
break;
case 'ngChange':
result = "ng-change=\"" + obj[key] + "\" ";
break;
case 'ngShow':
result = "ng-show=\"" + obj[key] + "\" ";
break;
case 'trueValue':
result = "ng-true-value=\"" + obj[key] + "\" ";
break;
case 'falseValue':
result = "ng-false-value=\"" + obj[key] + "\" ";
break;
default:
result = key + "=\"" + obj[key] + "\" ";
}
return result;
},
icon: function(icon) {
return "<i class=\"" + icon + "\"></i> ";
},
has: function(key) {
return (this.form[key] && this.form[key] != null && this.form[key] != undefined) ? true : false;
},
inject: function(form, options) {
//
// Use to inject the form as html into the view. View MUST have an ng-bind for 'htmlTemplate'.
// Returns scope of form.
//
var element = angular.element(document.getElementById('htmlTemplate'));
this.setForm(form);
element.html(this.build(options)); // Inject the html
this.scope = element.scope(); // Set scope specific to the element we're compiling, avoids circular reference
// From here use 'scope' to manipulate the form, as the form is not in '$scope'
$compile(element)(this.scope);
if (options.related) {
this.addListeners();
}
if (options.mode == 'add') {
this.applyDefaults();
}
this.mode = options.mode;
return this.scope;
},
applyDefaults: function() {
for (fld in this.form.fields) {
if (this.form.fields[fld].default) {
this.scope[fld] = this.form.fields[fld].default;
}
}
},
reset: function() {
// The form field values cannot be reset with jQuery. Each field is tied to a model, so to clear the field
// value, you have clear the model.
this.scope[this.form.name + '_form'].$setPristine();
for (var fld in this.form.fields) {
this.scope[fld] = '';
this.scope[fld + '_api_error'] = '';
this.scope[this.form.fields[fld].sourceModel + '_' + this.form.fields[fld].sourceField] = '';
if ( this.form.fields[fld].type == 'lookup' &&
this.scope[this.form.name + '_form'][this.form.fields[fld].sourceModel + '_' + this.form.fields[fld].sourceField] ) {
this.scope[this.form.name + '_form'][this.form.fields[fld].sourceModel + '_' + this.form.fields[fld].sourceField].$setPristine();
}
if (this.scope[this.form.name + '_form'][fld]) {
this.scope[this.form.name + '_form'][fld].$setPristine();
}
}
if (this.mode == 'add') {
this.applyDefaults();
}
},
addListeners: function() {
// Listen for accordion collapse events and toggle the header icon
$('.collapse')
.on('show', function() {
var element = $(this).parent().find('.accordion-heading i');
element.removeClass('icon-angle-down');
element.addClass('icon-angle-up');
})
.on('hide', function() {
var element = $(this).parent().find('.accordion-heading i');
element.removeClass('icon-angle-up');
element.addClass('icon-angle-down');
});
},
build: function(options) {
//
// Generate HTML. Do NOT call this function directly. Called by inject(). Returns an HTML
// string to be injected into the current view.
//
var html = '';
//Breadcrumbs
html += "<div class=\"nav-path\">\n";
html += "<ul class=\"breadcrumb\">\n";
html += "<li ng-repeat=\"crumb in breadcrumbs\"><a href=\"{{ '#' + crumb.path }}\">{{ crumb.title | capitalize }}</a> " +
"<span class=\"divider\">/</span></li>\n";
html += "<li class=\"active\">";
if (options.mode == 'edit') {
html += this.form.editTitle;
}
else {
html += this.form.addTitle;
}
html += "</li>\n</ul>\n</div>\n";
// Start the well
if ( this.has('well') ) {
html += "<div class=\"well\">\n";
}
html += "<form class=\"form-horizontal\" name=\"" + this.form.name + '_form" id="' + this.form.name + '" novalidate>' + "\n";
html += "<div ng-show=\"flashMessage != null && flashMessage != undefined\" class=\"alert alert-info\">{{ flashMessage }}</div>\n";
//fields
for (var fld in this.form.fields) {
var field = this.form.fields[fld];
//Assuming horizontal form for now. This will need to be more flexible later.
//text type fields
if (field.type == 'text' || field.type == 'password' || field.type == 'email') {
if ( (! field.readonly) || (field.readonly && options.mode == 'edit') ) {
html += "<div class=\"control-group\""
html += (field.ngShow) ? this.attr(field,'ngShow') : "";
html += ">\n";
html += "<label class=\"control-label\" for=\"" + fld + '">' + field.label + '</label>' + "\n";
html += "<div class=\"controls\">\n";
html += "<input ";
html += this.attr(field,'type');
html += "ng-model=\"" + fld + '" ';
html += 'name="' + fld + '" ';
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.id) ? this.attr(field,'id') : "";
html += (field.placeholder) ? this.attr(field,'placeholder') : "";
html += (options.mode == 'edit' && field.editRequired) ? "required " : "";
html += (options.mode == 'add' && field.addRequired) ? "required " : "";
html += (field.readonly) ? "readonly " : "";
html += (field.awPassMatch) ? "awpassmatch " : "";
html += (field.capitalize) ? "capitalize " : "";
html += "/><br />\n";
// Add error messages
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ) {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</span>\n";
}
if (field.type == "email") {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.email\">A valid email address is required!</span>\n";
}
if (field.awPassMatch) {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld +
".$error.awpassmatch\">Must match Password value</span>\n";
}
html += "<span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span>\n";
html += "</div>\n";
html += "</div>\n";
}
}
//checkbox
if (field.type == 'checkbox') {
if ( (! field.readonly) || (field.readonly && options.mode == 'edit') ) {
html += "<div class=\"control-group\" "
html += (field.ngShow) ? this.attr(field,'ngShow') : "";
html += ">\n";
html += "<div class=\"controls\">\n";
html += "<label class=\"checkbox\">";
html += "<input ";
html += this.attr(field,'type');
html += "ng-model=\"" + fld + '" ';
html += "name=\"" + fld + '" ';
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.id) ? this.attr(field,'id') : "";
html += this.attr(field,'trueValue');
html += this.attr(field,'falseValue');
html += (field.checked) ? "checked " : "";
html += (field.readonly) ? "readonly " : "";
html += " /> " + field.label + "\n";
html += "</label>\n";
html += "<span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span>\n";
html += "</div>\n";
html += "</div>\n";
}
}
//lookup type fields
if (field.type == 'lookup') {
html += "<div class=\"control-group\""
html += (field.ngShow) ? this.attr(field,'ngShow') : "";
html += ">\n";
html += "<label class=\"control-label\" for=\"" + fld + '">' + field.label + '</label>' + "\n";
html += "<div class=\"controls\">\n";
html += "<div class=\"input-prepend\">\n";
html += "<button class=\"btn\" " + this.attr(field,'ngClick') + "><i class=\"icon-search\"></i></button>\n";
html += "<input class=\"input-medium\" type=\"text\" ";
html += "ng-model=\"" + field.sourceModel + '_' + field.sourceField + "\" ";
html += "name=\"" + field.sourceModel + '_' + field.sourceField + "\" ";
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.id) ? this.attr(field,'id') : "";
html += (field.placeholder) ? this.attr(field,'placeholder') : "";
html += (options.mode == 'edit' && field.editRequired) ? "required " : "";
html += (options.mode == 'add' && field.addRequired) ? "required " : "";
html += " readonly />\n";
html += "</div>\n";
// Add error messages
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ) {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</span>\n";
}
html += "<span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span>\n";
html += "</div>\n";
html += "</div>\n";
}
}
//buttons
if (this.has('buttons')) {
html += "<div class=\"control-group\">\n";
html += "<div class=\"controls buttons\">\n";
}
for (var btn in this.form.buttons) {
var button = this.form.buttons[btn];
//button
html += "<button ";
if (button.class) {
html += this.attr(button,'class');
}
if (button.ngClick) {
html += this.attr(button,'ngClick');
}
if (button.ngDisabled) {
if (btn !== 'reset') {
html += "ng-disabled=\"" + this.form.name + "_form.$pristine || " + this.form.name + "_form.$invalid\" ";
}
else {
html += "ng-disabled=\"" + this.form.name + "_form.$pristine\" ";
}
}
html += ">";
if (button.icon) {
html += this.icon(button.icon);
}
html += button.label + "</button>\n";
}
if (this.has('buttons')) {
html += "</div>\n";
html += "</div>\n";
}
html += "</form>\n";
if ( this.has('well') ) {
html += "</div>\n";
}
if (options.related && this.form.related) {
html += this.buildCollections();
}
return html;
},
buildCollections: function() {
//
// Create TB accordians with imbedded lists for related collections
// Should not be called directly. Called internally by build().
//
var idx = 1;
var form = this.form;
var html = "<div class=\"accordion\" id=\"accordion\">\n";
for (var itm in form.related) {
if (form.related[itm].type == 'collection' || form.related[itm].type == 'tree') {
// Start the accordion group
html += "<div class=\"accordion-group\">\n";
html += "<div class=\"accordion-heading\">\n";
html += "<a class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#collapse" + idx + "\">";
html += "<i class=\"icon-angle-down icon-white\"></i>" + form.related[itm].title + "</a>\n";
html += "</div>\n";
html += "<div id=\"collapse" + idx + "\" class=\"accordion-body collapse";
if (form.related[itm].open) {
html += " in"; //open accordion on load
}
html += "\">\n";
html += "<div class=\"accordion-inner\">\n";
if (form.related[itm].type == 'tree') {
html += "<div id=\"tree-view\"></div>\n";
}
else {
html += "<div class=\"well\">\n";
html += SearchWidget({ iterator: form.related[itm].iterator, template: form.related[itm], mini: true });
// Add actions(s)
html += "<div class=\"text-right actions\">\n";
for (var action in form.related[itm].actions) {
html += "<button class=\"btn btn-mini btn-success\" ";
html += this.attr(form.related[itm]['actions'][action],'ngClick');
html += "><i class=\"" + form.related[itm]['actions'][action].icon + "\"></i></button>\n";
}
html += "</div>\n";
// Start the list
html += "<div class=\"list\">\n";
html += "<table class=\"table table-condensed\">\n";
html += "<thead>\n";
html += "<tr>\n";
html += "<th>#</th>\n";
for (var fld in form.related[itm].fields) {
html += "<th>" + form.related[itm]['fields'][fld].label + "</th>\n";
}
html += "<th></th>\n";
html += "</tr>\n";
html += "</thead>";
html += "<tbody>\n";
html += "<tr ng-repeat=\"" + form.related[itm].iterator + " in " + itm + "\" >\n";
html += "<td>{{ $index + (" + form.related[itm].iterator + "Page * " +
form.related[itm].iterator + "PageSize) + 1 }}.</td>\n";
var cnt = 1;
for (var fld in form.related[itm].fields) {
cnt++;
html += "<td>{{ " + form.related[itm].iterator + "." + fld + " }}</td>\n";
}
// Row level actions
html += "<td class=\"actions\">";
for (action in form.related[itm].fieldActions) {
html += "<button class=\"btn btn-mini";
if (form.related[itm]['fieldActions'][action].class) {
html += " " + form.related[itm]['fieldActions'][action].class;
}
html += "\" " + this.attr(form.related[itm]['fieldActions'][action],'ngClick') +
">" + this.icon(form.related[itm]['fieldActions'][action].icon) + "</button> ";
}
html += "</td>";
html += "</tr>\n";
// Message for when a related collection is empty
html += "<tr class=\"info\" ng-show=\"" + itm + " == null || " + itm + ".length == 0\">\n";
html += "<td colspan=\"" + cnt + "\"><div class=\"alert alert-info\">No records matched your search.</div></td>\n";
html += "</tr>\n";
// End List
html += "</tbody>\n";
html += "</table>\n";
html += "</div>\n"; // close well
html += "</div>\n"; // close list div
html += PaginateWidget({ set: itm, iterator: form.related[itm].iterator, mini: true });
}
// End Accordion Group
html += "</div>\n"; // accordion inner
html += "</div>\n"; // accordion body
html += "</div>\n"; // accordion group
idx++;
}
}
html += "</div>\n";
return html;
}
}}]);

View File

@ -0,0 +1,112 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* GeneratorHelpers
*
* Functions shared between FormGenerator and ListGenerator
*
*/
angular.module('GeneratorHelpers', [])
.factory('SearchWidget', function() {
return function(params) {
//
// Generate search widget
//
var iterator = params.iterator;
var form = params.template;
var useMini = params.mini;
var html= '';
html += "<div class=\"search-widget\">\n";
html += "<div class=\"input-prepend input-append\">\n";
html += "<div class=\"btn-group\">\n";
html += "<button class=\"btn ";
html += (useMini) ? "btn-mini " : "";
html += "dropdown-toggle\" data-toggle=\"dropdown\">\n";
html += "<span ng-bind=\"" + iterator + "SearchFieldLabel\"></span>\n";
html += "<span class=\"caret\"></span>\n";
html += "</button>\n";
html += "<ul class=\"dropdown-menu\">\n";
for ( var fld in form.fields) {
html += "<li><a href=\"\" ng-click=\"setSearchField('" + iterator + "','" + fld + "','" + form.fields[fld].label + "')\">"
+ form.fields[fld].label + "</a></li>\n";
}
html += "</ul>\n";
html += "</div>\n";
html += "<input class=\"input-medium";
html += (useMini) ? " field-mini-height" : "";
html += "\" ng-model=\"" + iterator + "SearchValue\" ng-change=\"search('" + iterator +
"')\" placeholder=\"Search\" type=\"text\" >\n";
html += "<div class=\"btn-group\">\n";
html += "<button class=\"btn ";
html += (useMini) ? "btn-mini " : "";
html += "dropdown-toggle\" data-toggle=\"dropdown\">\n";
html += "<span ng-bind=\"" + iterator + "SearchTypeLabel\"></span>\n";
html += "<span class=\"caret\"></span>\n";
html += "</button>\n";
html += "<ul class=\"dropdown-menu\">\n";
html += "<li><a href=\"\" ng-click=\"setSearchType('" + iterator + "','iexact','Exact Match')\">Exact Match</a></li>\n";
html += "<li><a href=\"\" ng-click=\"setSearchType('" + iterator + "','icontains','Contains')\">Contains</a></li>\n";
html += "</ul>\n";
html += "</div>\n";
html += "</div>\n";
html += "<div class=\"spin\" ng-show=\"" + iterator + "SearchSpin == true\"><i class=\"icon-spinner icon-spin\"></i></div>\n";
html += "</div>\n";
return html;
}
})
.factory('PaginateWidget', function() {
return function(params) {
var set = params.set;
var iterator = params.iterator;
var useMini = params.mini;
var mode = (params.mode) ? params.mode : null;
var html = '';
if (mode == 'lookup') {
html += "<div class=\"lookup-navigation";
}
else {
html += "<div class=\"footer-navigation";
}
html += (useMini) ? " related-footer" : "";
html += "\">\n";
html += "<form class=\"form-inline\">\n";
html += "<button class=\"previous btn";
html += (useMini) ? " btn-mini\" " : "\" ";
html += "ng-click=\"prevSet('" + set + "','" + iterator + "')\" " +
"ng-disabled=\"prevUrl == null || prevUrl == undefined\"><i class=\"icon-chevron-left\"></i> Prev</button>\n";
html += "<button class=\"next btn btn";
html += (useMini) ? " btn-mini\" " : "\" ";
html += " ng-click=\"nextSet('" + set + "','" + iterator + "')\"" +
"ng-disabled=\"nextUrl == null || nextUrl == undefined\">Next <i class=\"icon-chevron-right\"></i></button>\n";
if (mode != 'lookup') {
html += "<label class=\"page-size-label\">Rows per page:</label>\n";
html += "<select ng-model=\"" + iterator + "PageSize\" ng-change=\"changePageSize('" +
set + "'," + "'" + iterator + "')\" class=\"input-mini";
html += (useMini) ? " field-mini-height" : "";
html += " page-size\">\n";
html += "<option value=\"20\" selected>20</option>\n";
html += "<option value=\"40\">40</option>\n";
html += "<option value=\"60\">60</option>\n";
html += "<option value=\"80\">80</option>\n";
html += "</select>\n";
}
html += "<div class=\"";
html += (mode != "lookup") ? "page-number pull-right" : "page-number-small";
html += "\" >Page: {{ " + iterator + "Page + 1 }} of {{ " + iterator + "PageCount }}</div>\n";
html += "</form>\n";
html += "</div>\n";
return html;
}
});

View File

@ -0,0 +1,235 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* ListGenerator
* Pass in a list definition from ListDefinitions and out pops an html template.
* Use inject method to generate the html and inject into the current view.
*
*/
angular.module('ListGenerator', ['GeneratorHelpers'])
.factory('GenerateList', [ '$compile', '$rootScope', 'SearchWidget', 'PaginateWidget',
function($compile, $rootScope, SearchWidget, PaginateWidget) {
return {
setList: function(list) {
this.list = list;
},
attr: function(obj, key) {
var result;
switch (key) {
case 'ngClick':
result = "ng-click=\"" + obj[key] + "\" ";
break;
case 'ngBind':
result = "ng-bind=\"" + obj[key] + "\" ";
break;
case 'awToolTip':
result = "aw-tool-tip=\"" + obj[key] + "\" ";
break;
default:
result = key + "=\"" + obj[key] + "\" ";
}
return result;
},
icon: function(icon) {
return "<i class=\"" + icon + "\"></i> ";
},
has: function(key) {
return (this.form[key] && this.form[key] != null && this.form[key] != undefined) ? true : false;
},
hide: function() {
$('#lookup-modal').modal('hide');
},
inject: function(list, options) {
// options.mode = one of edit, select or lookup
//
// Modes edit and select will inject the list as html into element #htmlTemplate.
// 'lookup' mode injects the list html into #lookup-modal-body.
//
// For options.mode == 'lookup', include the following:
//
// hdr: <lookup dialog header>
//
if (options.mode == 'lookup') {
var element = angular.element(document.getElementById('lookup-modal-body'));
}
else {
var element = angular.element(document.getElementById('htmlTemplate'));
}
this.setList(list);
element.html(this.build(options)); // Inject the html
this.scope = element.scope(); // Set scope specific to the element we're compiling, avoids circular reference
// From here use 'scope' to manipulate the form, as the form is not in '$scope'
$compile(element)(this.scope);
if (options.mode == 'lookup') {
// options should include {hdr: <dialog header>, action: <function...> }
this.scope.lookupHeader = options.hdr;
$('#lookup-modal').modal();
}
return this.scope;
},
build: function(options) {
//
// Generate HTML. Do NOT call this function directly. Called by inject(). Returns an HTML
// string to be injected into the current view.
//
var html = '';
var list = this.list;
if (options.mode != 'lookup') {
//Breadcrumbs
html += "<div class=\"nav-path\">\n";
html += "<ul class=\"breadcrumb\">\n";
html += "<li ng-repeat=\"crumb in breadcrumbs\"><a href=\"{{ '#' + crumb.path }}\">{{ crumb.title | capitalize }}</a> " +
"<span class=\"divider\">/</span></li>\n";
html += "<li class=\"active\">";
if (options.mode == 'select') {
html += list.selectTitle;
}
else {
html += list.editTitle;
}
html += "</li>\n</ul>\n</div>\n";
}
//select instructions
if (options.mode == 'select') {
if (list.selectInstructions) {
html += "<div class=\"alert alert-info alert-block\">\n";
html += "<button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>\n";
html += "<strong>Hint: </strong>" + list.selectInstructions + "\n";
html += "</div>\n"
}
}
else {
if (options.mode == 'edit' && list.editInstructions) {
html += "<div class=\"alert alert-info alert-block\">\n";
html += "<button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>\n";
html += "<strong>Hint: </strong>" + list.editInstructions + "\n";
html += "</div>\n";
}
}
if (options.mode != 'lookup') {
html += "<div class=\"well\">\n";
}
if (options.mode == 'lookup') {
html += SearchWidget({ iterator: list.iterator, template: list, mini: true });
}
else {
html += SearchWidget({ iterator: list.iterator, template: list, mini: false });
}
if (options.mode != 'lookup') {
//actions
html += "<div class=\"text-right\">\n";
for (action in list.actions) {
if (list.actions[action].mode == 'all' || list.actions[action].mode == options.mode) {
html += "<button " + this.attr(list.actions[action], 'ngClick') +
this.attr(list.actions[action], 'class');
html += (list.actions[action].awToolTip) ? this.attr(list.actions[action],'awToolTip') : "";
html += " >" + this.icon(list.actions[action].icon) + "</button> ";
}
}
if (options.mode == 'select') {
html += " <button class=\"btn btn-mini btn-success\" ng-click=\"finishSelection()\"><i class=\"icon-ok\"></i> Finished</button>\n";
}
html += "</div>\n";
}
// table header row
html += "<table class=\"table table-condensed"
html += (options.mode == 'lookup') ? " table-hover" : "";
html += "\">\n";
html += "<thead>\n";
html += "<tr>\n";
html += "<th>#</th>\n";
for (var fld in list.fields) {
html += "<th>" + list.fields[fld].label + "</th>\n";
}
if (options.mode == 'select') {
html += "<th>Select</th>";
}
else if (options.mode == 'edit') {
html += "<th></th>\n";
}
html += "</tr>\n";
html += "</thead>\n";
// table body
html += "<tbody>\n";
html += "<tr ";
html += (options.mode == 'lookup') ? "ng-class=\"" + list.iterator + "_\{\{ " + list.iterator + ".id \}\}_class\" " : "";
html += "class=\"" + list.iterator + "_class\" ng-repeat=\"" + list.iterator + " in " + list.name + "\"";
html += (options.mode == 'lookup') ? " ng-click=\"toggle_" + list.iterator +"({{ " + list.iterator + ".id }})\"" : "";
html += ">\n";
html += "<td class=\"index-column\">{{ $index + (" + list.iterator + "Page * " + list.iterator + "PageSize) + 1 }}.</td>\n";
var cnt = 2;
for (fld in list.fields) {
cnt++;
if (! list.fields[fld].ngBind) {
html += "<td class=\"" + fld + "-column\">{{" + list.iterator + "." + fld + "}}</td>\n";
}
else {
html += "<td class=\"" + fld + "-column\">{{ " + list.fields[fld].ngBind + " }}</td>\n";
}
}
if (options.mode == 'select' ) {
html += "<td><input type=\"checkbox\" name=\"select\" ng-click=\"toggle_" + list.iterator +
"({{ " + list.iterator + ".id }})\" \></td>";
}
else if (options.mode == 'edit') {
// Row level actions
html += "<td class=\"actions\">";
for (action in list.fieldActions) {
html += "<button class=\"btn btn-mini";
if (list.fieldActions[action].class) {
html += " " + list.fieldActions[action].class;
}
html += "\" " + this.attr(list.fieldActions[action],'ngClick');
html += (list.fieldActions[action].awToolTip) ? this.attr(list.fieldActions[action],'awToolTip') : "";
html +=">";
html += (list.fieldActions[action].icon) ? this.icon(list.fieldActions[action].icon) : "";
html += (list.fieldActions[action].label) ? " " + list.fieldActions[action].label : "";
html +="</button> ";
}
html += "</td>";
}
html += "</tr>\n";
// Message for when a collection is empty
html += "<tr class=\"info\" ng-show=\"" + list.name + " == null || " + list.name + ".length == 0\">\n";
html += "<td colspan=\"" + cnt + "\"><div class=\"alert alert-info\">No " + list.iterator + " records matched your search.</div></td>\n";
html += "</tr>\n";
// End List
html += "</tbody>\n";
html += "</table>\n";
if (options.mode != 'lookup') {
html += "</div>\n"; //well
}
if (options.mode == 'lookup') {
html += PaginateWidget({ set: list.name, iterator: list.iterator, mini: true, mode: 'lookup' });
}
else {
html += PaginateWidget({ set: list.name, iterator: list.iterator, mini: true });
}
return html;
}
}}]);

View File

@ -0,0 +1,54 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* PromptDialog
* Prompt the user with a Yes/No dialog to confirm an action such
* as Delete. Assumes a hidden dialog already exists in $scope.
* See example at bottom. If user responds with Yes, execute action
* parameter.
*
* params: { hdr: 'header msg',
* body: 'body text/html',
* class: 'btn-class for Yes button', --defaults to btn-danger
* action: function() {} --action to take, if use clicks Yes
* }
*/
angular.module('PromptDialog', [])
.factory('Prompt', function(Alert) {
return function(params) {
//
var dialog = angular.element(document.getElementById('prompt-modal'));
var scope = dialog.scope();
scope.promptHeader = params.hdr;
scope.promptBody = params.body;
scope.promptBtnClass = (params.class == null || params.class == undefined) ? 'btn-danger' : params.class;
scope.id = params.id;
scope.url = params.url;
scope.promptAction = params.action;
$(dialog).modal({
backdrop: 'static',
keyboard: true,
show: true
});
}
});
<!-- Generic Modal dialog. Use to confirming an action (i.e. Delete) -->
// <div id="prompt-modal" class="modal hide">
// <div class="modal-header">
// <button type="button" class="close" data-target="#prompt-modal"
// data-dismiss="modal" aria-hidden="true">&times;</button>
// <h3 ng-bind="promptHeader"></h3>
// </div>
// <div class="modal-body" ng-bind="promptBody">
// </div>
// <div class="modal-footer">
// <a href="#" data-target="#prompt-modal" data-dismiss="modal" class="btn">No</a>
// <a href="" ng-click="promptAction()" class="btn {{ promptBtnClass }}">Yes</a>
// </div>
// </div>

View File

@ -0,0 +1,63 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Generic accessor for Ansible Commander services
*
*/
angular.module('RestServices',['ngCookies','AuthService'])
.factory('Rest', ['$http','$rootScope','$cookieStore','Authorization', function($http, $rootScope, $cookieStore, Authorization) {
return {
setUrl: function (url) {
this.url = url;
},
auth: { 'Authorization': 'Token ' + Authorization.getToken() },
pReplace: function() {
//in our url, replace :xx params with a value, assuming
// we can find it in user supplied params.
var key,rgx;
for (key in this.params) {
rgx = new RegExp("\\:" + key,'gm');
rgx.compile;
if (rgx.test(this.url)) {
this.url = this.url.replace(rgx,this.params[key]);
delete this.params[key];
}
}
},
get: function(args) {
args = (args) ? args : {};
this.params = (args.params != null || args.params != undefined) ? args.params : null;
this.pReplace();
return $http({method: 'GET',
url: this.url,
headers: this.auth,
params: this.params,
});
},
post: function(data) {
return $http({method: 'POST',
url: this.url,
headers: this.auth,
data: data });
},
put: function(data) {
return $http({method: 'PUT',
url: this.url,
headers: this.auth,
data: data });
},
delete: function(data) {
var url = this.url;
return $http({method: 'DELETE',
url: url,
headers: this.auth,
data: data});
}
}
}]);

View File

@ -0,0 +1,23 @@
/************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
*
* tooltip.js
*
* Custom directive to enable TB tooltips. To add a tooltip to an element, include the following directive in
* the element's attributes:
*
* aw-tool-tip="<< tooltip text here >>"
*
* Include the standard TB data-XXX attributes to controll a tooltip's appearance. We will default placement
* to the left and delay to 2 seconds.
*
*/
angular.module('AWToolTip', [])
.directive('awToolTip', function() {
return function(scope, element, attrs) {
var delay = (attrs.delay != undefined && attrs.delay != null) ? attrs.delay : $AnsibleConfig.tooltip_delay;
var placement = (attrs.placement != undefined && attrs.placement != null) ? attrs.placement : 'left';
$(element).tooltip({ placement: placement, delay: delay, title: attrs.awToolTip });
}
});

View File

@ -0,0 +1,126 @@
/************************************
*
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Utility functions
*
*/
angular.module('Utilities',[])
.factory('ClearScope', function() {
return function(id) {
var element = document.getElementById(id);
var scope = angular.element(element).scope();
scope.$destroy();
}
})
.factory('ToggleClass', function() {
return function(selector, cssClass) {
// Toggles the existance of a css class on a given element
if ( $(selector) && $(selector).hasClass(cssClass) ) {
$(selector).removeClass(cssClass);
}
else if ($(selector)) {
$(selector).addClass(cssClass);
}
}
})
.factory('Alert', ['$rootScope', function($rootScope) {
return function(hdr, msg) {
// Pass in the header and message you want displayed on TB modal dialog found in index.html.
// Assumes an id of 'alert-modal'
$rootScope.alertHeader = hdr;
$rootScope.alertBody = msg;
$('#alert-modal').modal({ show: true, keyboard: true, backdrop: 'static' });
}
}])
.factory('ProcessErrors', ['$log', 'Alert', function($log, Alert) {
return function(scope, data, status, form, defaultMsg) {
if (status == 403) {
Alert('Access Denied', 'The API responded with a 403 Access Denied error. You do not have permission to perform the ' +
'requested action. Please contact a system administrator.');
}
else if (data.non_field_errors) {
Alert('Error!', data.non_field_errors);
}
else if (form) {
var fieldErrors = false;
for (var field in form.fields ) {
if (data[field]) {
scope[field + '_api_error'] = data[field][0];
fieldErrors = true;
}
}
if ( (!fieldErrors) && defaultMsg) {
Alert(defaultMsg.hdr, defaultMsg.msg);
}
}
else {
Alert(defaultMsg.hdr, defaultMsg.msg);
}
}
}])
.factory('LoadBreadCrumbs', ['$rootScope', '$routeParams', '$location', function($rootScope, $routeParams, $location, Rest) {
return function(crumb) {
//Keep a list of path/title mappings. When we see /organizations/XX in the path, for example,
//we'll know the actual organization name it maps to.
if (crumb !== null && crumb !== undefined) {
var found = false;
for (var i=0; i < $rootScope.crumbCache.length; i++) {
if ($rootScope.crumbCache[i].path == crumb.path) {
found = true;
$rootScope.crumbCache[i] = crumb;
break;
}
}
if (found == false) {
$rootScope.crumbCache.push(crumb);
}
}
var paths = $location.path().replace(/^\//,'').split('/');
var ppath = '';
$rootScope.breadcrumbs = [];
if (paths.length > 1) {
var parent, child;
for (var i=0; i < paths.length - 1; i++) {
if (i > 0 && paths[i].match(/\d+/)) {
parent = paths[i-1];
child = parent.substring(0,parent.length - 1); //assumes parent ends with 's'
// find the correct title
for (var j=0; j < $rootScope.crumbCache.length; j++) {
if ($rootScope.crumbCache[j].path == '/' + parent + '/' + paths[i]) {
child = $rootScope.crumbCache[j].title;
break;
}
}
$rootScope.breadcrumbs.push({ title: child, path: ppath + '/' + paths[i] });
}
else {
$rootScope.breadcrumbs.push({ title: paths[i], path: ppath + '/' + paths[i] });
}
ppath += '/' + paths[i];
}
}
}
}])
.factory('ReturnToCaller', ['$location', function($location) {
return function(idx) {
// Split the current path by '/' and use the array elements from 0 up to and
// including idx as the new path. If no idx value supplied, use 0 to length - 1.
var paths = $location.path().replace(/^\//,'').split('/');
var newpath = '';
idx = (idx == null || idx == undefined) ? paths.length - 1 : idx + 1;
for (var i=0; i < idx; i++) {
newpath += '/' + paths[i]
}
$location.path(newpath);
}
}]);

9597
lib/ui/static/lib/jquery/jquery-1.9.1.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,10 @@
jsTree pre1.0
http://jstree.com/
Copyright (c) 2011 Ivan Bozhanov (vakata.com)
Dual licensed under the MIT and GPL licenses:
http://www.opensource.org/licenses/mit-license.php
http://www.gnu.org/licenses/gpl.html
This is the latest stable version before switching from GoogleCode to GitHub.

View File

@ -0,0 +1,20 @@
CREATE TABLE IF NOT EXISTS `tree` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`parent_id` bigint(20) unsigned NOT NULL,
`position` bigint(20) unsigned NOT NULL,
`left` bigint(20) unsigned NOT NULL,
`right` bigint(20) unsigned NOT NULL,
`level` bigint(20) unsigned NOT NULL,
`title` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
`type` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=13 ;
INSERT INTO `tree` (`id`, `parent_id`, `position`, `left`, `right`, `level`, `title`, `type`) VALUES
(1, 0, 2, 1, 14, 0, 'ROOT', ''),
(2, 1, 0, 2, 11, 1, 'C:', 'drive'),
(3, 2, 0, 3, 6, 2, '_demo', 'folder'),
(4, 3, 0, 4, 5, 3, 'index.html', 'default'),
(5, 2, 1, 7, 10, 2, '_docs', 'folder'),
(6, 1, 1, 12, 13, 1, 'D:', 'drive'),
(12, 5, 0, 8, 9, 3, 'zmei.html', 'default');

View File

@ -0,0 +1,146 @@
<?php
class _database {
private $link = false;
private $result = false;
private $row = false;
public $settings = array(
"servername"=> "localhost",
"serverport"=> "3306",
"username" => false,
"password" => false,
"database" => false,
"persist" => false,
"dieonerror"=> false,
"showerror" => false,
"error_file"=> true
);
function __construct() {
global $db_config;
$this->settings = array_merge($this->settings, $db_config);
if($this->settings["error_file"] === true) $this->settings["error_file"] = dirname(__FILE__)."/__mysql_errors.log";
}
function connect() {
if (!$this->link) {
$this->link = ($this->settings["persist"]) ?
mysql_pconnect(
$this->settings["servername"].":".$this->settings["serverport"],
$this->settings["username"],
$this->settings["password"]
) :
mysql_connect(
$this->settings["servername"].":".$this->settings["serverport"],
$this->settings["username"],
$this->settings["password"]
) or $this->error();
}
if (!mysql_select_db($this->settings["database"], $this->link)) $this->error();
if($this->link) mysql_query("SET NAMES 'utf8'");
return ($this->link) ? true : false;
}
function query($sql) {
if (!$this->link && !$this->connect()) $this->error();
if (!($this->result = mysql_query($sql, $this->link))) $this->error($sql);
return ($this->result) ? true : false;
}
function nextr() {
if(!$this->result) {
$this->error("No query pending");
return false;
}
unset($this->row);
$this->row = mysql_fetch_array($this->result, MYSQL_BOTH);
return ($this->row) ? true : false ;
}
function get_row($mode = "both") {
if(!$this->row) return false;
$return = array();
switch($mode) {
case "assoc":
foreach($this->row as $k => $v) {
if(!is_int($k)) $return[$k] = $v;
}
break;
case "num":
foreach($this->row as $k => $v) {
if(is_int($k)) $return[$k] = $v;
}
break;
default:
$return = $this->row;
break;
}
return array_map("stripslashes",$return);
}
function get_all($mode = "both", $key = false) {
if(!$this->result) {
$this->error("No query pending");
return false;
}
$return = array();
while($this->nextr()) {
if($key !== false) $return[$this->f($key)] = $this->get_row($mode);
else $return[] = $this->get_row($mode);
}
return $return;
}
function f($index) {
return stripslashes($this->row[$index]);
}
function go_to($row) {
if(!$this->result) {
$this->error("No query pending");
return false;
}
if(!mysql_data_seek($this->result, $row)) $this->error();
}
function nf() {
if ($numb = mysql_num_rows($this->result) === false) $this->error();
return mysql_num_rows($this->result);
}
function af() {
return mysql_affected_rows();
}
function error($string="") {
$error = mysql_error();
if($this->settings["show_error"]) echo $error;
if($this->settings["error_file"] !== false) {
$handle = @fopen($this->settings["error_file"], "a+");
if($handle) {
@fwrite($handle, "[".date("Y-m-d H:i:s")."] ".$string." <".$error.">\n");
@fclose($handle);
}
}
if($this->settings["dieonerror"]) {
if(isset($this->result)) mysql_free_result($this->result);
mysql_close($this->link);
die();
}
}
function insert_id() {
if(!$this->link) return false;
return mysql_insert_id();
}
function escape($string){
if(!$this->link) return addslashes($string);
return mysql_real_escape_string($string);
}
function destroy(){
if (isset($this->result)) mysql_free_result($this->result);
if (isset($this->link)) mysql_close($this->link);
}
}
?>

View File

@ -0,0 +1,152 @@
<?php
class _database {
private $data = false;
private $result = false;
private $row = false;
public $settings = array(
"servername"=> "localhost",
"serverport"=> "3306",
"username" => false,
"password" => false,
"database" => false,
"persist" => false,
"dieonerror"=> false,
"showerror" => false,
"error_file"=> true
);
function __construct() {
global $db_config;
$this->settings = array_merge($this->settings, $db_config);
if($this->settings["error_file"] === true) $this->settings["error_file"] = dirname(__FILE__)."/__mysql_errors.log";
}
function connect() {
$this->data = new mysqli(
$this->settings["servername"],
$this->settings["username"],
$this->settings["password"],
$this->settings["database"],
$this->settings["serverport"]
);
if(mysqli_connect_errno()) {
$this->error("Connection error: ".mysqli_connect_error() );
return false;
}
if(!$this->data->set_charset("utf8")) {
$this->error("Error loading character set utf8");
return false;
}
return true;
}
function query($sql) {
if(!$this->data && !$this->connect()) {
$this->error("Could node connect for query: ".$sql);
return false;
}
//echo $sql."<br />:";
if(!($this->result = $this->data->query($sql))) $this->error($sql);
return ($this->result) ? true : false;
}
function nextr(){
if(!$this->result) {
$this->error("No query pending");
return false;
}
unset($this->row);
$this->row = $this->result->fetch_array(MYSQL_BOTH);
return ($this->row) ? true : false ;
}
function get_row($mode = "both") {
if(!$this->row) return false;
$return = array();
switch($mode) {
case "assoc":
foreach($this->row as $k => $v) {
if(!is_int($k)) $return[$k] = $v;
}
break;
case "num":
foreach($this->row as $k => $v) {
if(is_int($k)) $return[$k] = $v;
}
break;
default:
$return = $this->row;
break;
}
return array_map("stripslashes",$return);
}
function get_all($mode = "both", $key = false) {
if(!$this->result) {
$this->error("No query pending");
return false;
}
$return = array();
while($this->nextr()) {
if($key !== false) $return[$this->f($key)] = $this->get_row($mode);
else $return[] = $this->get_row($mode);
}
return $return;
}
function f($index) {
return stripslashes($this->row[$index]);
}
function go_to($row) {
if(!$this->result) {
$this->error("No query pending");
return false;
}
if(!$this->data->data_seek($row)) $this->error();
}
function nf() {
if (!$this->result) {
$this->error("nf: no result set");
return false;
}
return $this->result->num_rows;
}
function af() {
return $this->data->affected_rows;
}
function error($string = "") {
$error = $this->data->error;
if($this->settings["show_error"]) echo $error;
if($this->settings["error_file"] !== false) {
$handle = @fopen($this->settings["error_file"], "a+");
if($handle) {
@fwrite($handle, "[".date("Y-m-d H:i:s")."] ".$string." <".$error.">\n");
@fclose($handle);
}
}
if($this->settings["dieonerror"]) {
if(isset($this->result)) $this->result->free();
@$this->data->close();
die();
}
}
function insert_id() {
return $this->data->insert_id;
}
function escape($string) {
if(!$this->data) return addslashes($string);
return $this->data->escape_string($string);
}
function destroy() {
if(isset($this->result)) $this->result->free();
if($this->data) $this->data->close();
}
}

View File

@ -0,0 +1,602 @@
<?php
class _tree_struct {
// Structure table and fields
protected $table = "";
protected $fields = array(
"id" => false,
"parent_id" => false,
"position" => false,
"left" => false,
"right" => false,
"level" => false
);
// Constructor
function __construct($table = "tree", $fields = array()) {
$this->table = $table;
if(!count($fields)) {
foreach($this->fields as $k => &$v) { $v = $k; }
}
else {
foreach($fields as $key => $field) {
switch($key) {
case "id":
case "parent_id":
case "position":
case "left":
case "right":
case "level":
$this->fields[$key] = $field;
break;
}
}
}
// Database
$this->db = new _database;
}
function _get_node($id) {
$this->db->query("SELECT `".implode("` , `", $this->fields)."` FROM `".$this->table."` WHERE `".$this->fields["id"]."` = ".(int) $id);
$this->db->nextr();
return $this->db->nf() === 0 ? false : $this->db->get_row("assoc");
}
function _get_children($id, $recursive = false) {
$children = array();
if($recursive) {
$node = $this->_get_node($id);
$this->db->query("SELECT `".implode("` , `", $this->fields)."` FROM `".$this->table."` WHERE `".$this->fields["left"]."` >= ".(int) $node[$this->fields["left"]]." AND `".$this->fields["right"]."` <= ".(int) $node[$this->fields["right"]]." ORDER BY `".$this->fields["left"]."` ASC");
}
else {
$this->db->query("SELECT `".implode("` , `", $this->fields)."` FROM `".$this->table."` WHERE `".$this->fields["parent_id"]."` = ".(int) $id." ORDER BY `".$this->fields["position"]."` ASC");
}
while($this->db->nextr()) $children[$this->db->f($this->fields["id"])] = $this->db->get_row("assoc");
return $children;
}
function _get_path($id) {
$node = $this->_get_node($id);
$path = array();
if(!$node === false) return false;
$this->db->query("SELECT `".implode("` , `", $this->fields)."` FROM `".$this->table."` WHERE `".$this->fields["left"]."` <= ".(int) $node[$this->fields["left"]]." AND `".$this->fields["right"]."` >= ".(int) $node[$this->fields["right"]]);
while($this->db->nextr()) $path[$this->db->f($this->fields["id"])] = $this->db->get_row("assoc");
return $path;
}
function _create($parent, $position) {
return $this->_move(0, $parent, $position);
}
function _remove($id) {
if((int)$id === 1) { return false; }
$data = $this->_get_node($id);
$lft = (int)$data[$this->fields["left"]];
$rgt = (int)$data[$this->fields["right"]];
$dif = $rgt - $lft + 1;
// deleting node and its children
$this->db->query("" .
"DELETE FROM `".$this->table."` " .
"WHERE `".$this->fields["left"]."` >= ".$lft." AND `".$this->fields["right"]."` <= ".$rgt
);
// shift left indexes of nodes right of the node
$this->db->query("".
"UPDATE `".$this->table."` " .
"SET `".$this->fields["left"]."` = `".$this->fields["left"]."` - ".$dif." " .
"WHERE `".$this->fields["left"]."` > ".$rgt
);
// shift right indexes of nodes right of the node and the node's parents
$this->db->query("" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["right"]."` = `".$this->fields["right"]."` - ".$dif." " .
"WHERE `".$this->fields["right"]."` > ".$lft
);
$pid = (int)$data[$this->fields["parent_id"]];
$pos = (int)$data[$this->fields["position"]];
// Update position of siblings below the deleted node
$this->db->query("" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["position"]."` = `".$this->fields["position"]."` - 1 " .
"WHERE `".$this->fields["parent_id"]."` = ".$pid." AND `".$this->fields["position"]."` > ".$pos
);
return true;
}
function _move($id, $ref_id, $position = 0, $is_copy = false) {
if((int)$ref_id === 0 || (int)$id === 1) { return false; }
$sql = array(); // Queries executed at the end
$node = $this->_get_node($id); // Node data
$nchildren = $this->_get_children($id); // Node children
$ref_node = $this->_get_node($ref_id); // Ref node data
$rchildren = $this->_get_children($ref_id);// Ref node children
$ndif = 2;
$node_ids = array(-1);
if($node !== false) {
$node_ids = array_keys($this->_get_children($id, true));
// TODO: should be !$is_copy && , but if copied to self - screws some right indexes
if(in_array($ref_id, $node_ids)) return false;
$ndif = $node[$this->fields["right"]] - $node[$this->fields["left"]] + 1;
}
if($position >= count($rchildren)) {
$position = count($rchildren);
}
// Not creating or copying - old parent is cleaned
if($node !== false && $is_copy == false) {
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["position"]."` = `".$this->fields["position"]."` - 1 " .
"WHERE " .
"`".$this->fields["parent_id"]."` = ".$node[$this->fields["parent_id"]]." AND " .
"`".$this->fields["position"]."` > ".$node[$this->fields["position"]];
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["left"]."` = `".$this->fields["left"]."` - ".$ndif." " .
"WHERE `".$this->fields["left"]."` > ".$node[$this->fields["right"]];
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["right"]."` = `".$this->fields["right"]."` - ".$ndif." " .
"WHERE " .
"`".$this->fields["right"]."` > ".$node[$this->fields["left"]]." AND " .
"`".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ";
}
// Preparing new parent
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["position"]."` = `".$this->fields["position"]."` + 1 " .
"WHERE " .
"`".$this->fields["parent_id"]."` = ".$ref_id." AND " .
"`".$this->fields["position"]."` >= ".$position." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$ref_ind = $ref_id === 0 ? (int)$rchildren[count($rchildren) - 1][$this->fields["right"]] + 1 : (int)$ref_node[$this->fields["right"]];
$ref_ind = max($ref_ind, 1);
$self = ($node !== false && !$is_copy && (int)$node[$this->fields["parent_id"]] == $ref_id && $position > $node[$this->fields["position"]]) ? 1 : 0;
foreach($rchildren as $k => $v) {
if($v[$this->fields["position"]] - $self == $position) {
$ref_ind = (int)$v[$this->fields["left"]];
break;
}
}
if($node !== false && !$is_copy && $node[$this->fields["left"]] < $ref_ind) {
$ref_ind -= $ndif;
}
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["left"]."` = `".$this->fields["left"]."` + ".$ndif." " .
"WHERE " .
"`".$this->fields["left"]."` >= ".$ref_ind." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["right"]."` = `".$this->fields["right"]."` + ".$ndif." " .
"WHERE " .
"`".$this->fields["right"]."` >= ".$ref_ind." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$ldif = $ref_id == 0 ? 0 : $ref_node[$this->fields["level"]] + 1;
$idif = $ref_ind;
if($node !== false) {
$ldif = $node[$this->fields["level"]] - ($ref_node[$this->fields["level"]] + 1);
$idif = $node[$this->fields["left"]] - $ref_ind;
if($is_copy) {
$sql[] = "" .
"INSERT INTO `".$this->table."` (" .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."`, " .
"`".$this->fields["right"]."`, " .
"`".$this->fields["level"]."`" .
") " .
"SELECT " .
"".$ref_id.", " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."` - (".($idif + ($node[$this->fields["left"]] >= $ref_ind ? $ndif : 0))."), " .
"`".$this->fields["right"]."` - (".($idif + ($node[$this->fields["left"]] >= $ref_ind ? $ndif : 0))."), " .
"`".$this->fields["level"]."` - (".$ldif.") " .
"FROM `".$this->table."` " .
"WHERE " .
"`".$this->fields["id"]."` IN (".implode(",", $node_ids).") " .
"ORDER BY `".$this->fields["level"]."` ASC";
}
else {
$sql[] = "" .
"UPDATE `".$this->table."` SET " .
"`".$this->fields["parent_id"]."` = ".$ref_id.", " .
"`".$this->fields["position"]."` = ".$position." " .
"WHERE " .
"`".$this->fields["id"]."` = ".$id;
$sql[] = "" .
"UPDATE `".$this->table."` SET " .
"`".$this->fields["left"]."` = `".$this->fields["left"]."` - (".$idif."), " .
"`".$this->fields["right"]."` = `".$this->fields["right"]."` - (".$idif."), " .
"`".$this->fields["level"]."` = `".$this->fields["level"]."` - (".$ldif.") " .
"WHERE " .
"`".$this->fields["id"]."` IN (".implode(",", $node_ids).") ";
}
}
else {
$sql[] = "" .
"INSERT INTO `".$this->table."` (" .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."`, " .
"`".$this->fields["right"]."`, " .
"`".$this->fields["level"]."` " .
") " .
"VALUES (" .
$ref_id.", " .
$position.", " .
$idif.", " .
($idif + 1).", " .
$ldif.
")";
}
foreach($sql as $q) { $this->db->query($q); }
$ind = $this->db->insert_id();
if($is_copy) $this->_fix_copy($ind, $position);
return $node === false || $is_copy ? $ind : true;
}
function _fix_copy($id, $position) {
$node = $this->_get_node($id);
$children = $this->_get_children($id, true);
$map = array();
for($i = $node[$this->fields["left"]] + 1; $i < $node[$this->fields["right"]]; $i++) {
$map[$i] = $id;
}
foreach($children as $cid => $child) {
if((int)$cid == (int)$id) {
$this->db->query("UPDATE `".$this->table."` SET `".$this->fields["position"]."` = ".$position." WHERE `".$this->fields["id"]."` = ".$cid);
continue;
}
$this->db->query("UPDATE `".$this->table."` SET `".$this->fields["parent_id"]."` = ".$map[(int)$child[$this->fields["left"]]]." WHERE `".$this->fields["id"]."` = ".$cid);
for($i = $child[$this->fields["left"]] + 1; $i < $child[$this->fields["right"]]; $i++) {
$map[$i] = $cid;
}
}
}
function _reconstruct() {
$this->db->query("" .
"CREATE TEMPORARY TABLE `temp_tree` (" .
"`".$this->fields["id"]."` INTEGER NOT NULL, " .
"`".$this->fields["parent_id"]."` INTEGER NOT NULL, " .
"`". $this->fields["position"]."` INTEGER NOT NULL" .
") type=HEAP"
);
$this->db->query("" .
"INSERT INTO `temp_tree` " .
"SELECT " .
"`".$this->fields["id"]."`, " .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."` " .
"FROM `".$this->table."`"
);
$this->db->query("" .
"CREATE TEMPORARY TABLE `temp_stack` (" .
"`".$this->fields["id"]."` INTEGER NOT NULL, " .
"`".$this->fields["left"]."` INTEGER, " .
"`".$this->fields["right"]."` INTEGER, " .
"`".$this->fields["level"]."` INTEGER, " .
"`stack_top` INTEGER NOT NULL, " .
"`".$this->fields["parent_id"]."` INTEGER, " .
"`".$this->fields["position"]."` INTEGER " .
") type=HEAP"
);
$counter = 2;
$this->db->query("SELECT COUNT(*) FROM temp_tree");
$this->db->nextr();
$maxcounter = (int) $this->db->f(0) * 2;
$currenttop = 1;
$this->db->query("" .
"INSERT INTO `temp_stack` " .
"SELECT " .
"`".$this->fields["id"]."`, " .
"1, " .
"NULL, " .
"0, " .
"1, " .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."` " .
"FROM `temp_tree` " .
"WHERE `".$this->fields["parent_id"]."` = 0"
);
$this->db->query("DELETE FROM `temp_tree` WHERE `".$this->fields["parent_id"]."` = 0");
while ($counter <= $maxcounter) {
$this->db->query("" .
"SELECT " .
"`temp_tree`.`".$this->fields["id"]."` AS tempmin, " .
"`temp_tree`.`".$this->fields["parent_id"]."` AS pid, " .
"`temp_tree`.`".$this->fields["position"]."` AS lid " .
"FROM `temp_stack`, `temp_tree` " .
"WHERE " .
"`temp_stack`.`".$this->fields["id"]."` = `temp_tree`.`".$this->fields["parent_id"]."` AND " .
"`temp_stack`.`stack_top` = ".$currenttop." " .
"ORDER BY `temp_tree`.`".$this->fields["position"]."` ASC LIMIT 1"
);
if ($this->db->nextr()) {
$tmp = $this->db->f("tempmin");
$q = "INSERT INTO temp_stack (stack_top, `".$this->fields["id"]."`, `".$this->fields["left"]."`, `".$this->fields["right"]."`, `".$this->fields["level"]."`, `".$this->fields["parent_id"]."`, `".$this->fields["position"]."`) VALUES(".($currenttop + 1).", ".$tmp.", ".$counter.", NULL, ".$currenttop.", ".$this->db->f("pid").", ".$this->db->f("lid").")";
$this->db->query($q);
$this->db->query("DELETE FROM `temp_tree` WHERE `".$this->fields["id"]."` = ".$tmp);
$counter++;
$currenttop++;
}
else {
$this->db->query("" .
"UPDATE temp_stack SET " .
"`".$this->fields["right"]."` = ".$counter.", " .
"`stack_top` = -`stack_top` " .
"WHERE `stack_top` = ".$currenttop
);
$counter++;
$currenttop--;
}
}
$temp_fields = $this->fields;
unset($temp_fields["parent_id"]);
unset($temp_fields["position"]);
unset($temp_fields["left"]);
unset($temp_fields["right"]);
unset($temp_fields["level"]);
if(count($temp_fields) > 1) {
$this->db->query("" .
"CREATE TEMPORARY TABLE `temp_tree2` " .
"SELECT `".implode("`, `", $temp_fields)."` FROM `".$this->table."` "
);
}
$this->db->query("TRUNCATE TABLE `".$this->table."`");
$this->db->query("" .
"INSERT INTO ".$this->table." (" .
"`".$this->fields["id"]."`, " .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."`, " .
"`".$this->fields["right"]."`, " .
"`".$this->fields["level"]."` " .
") " .
"SELECT " .
"`".$this->fields["id"]."`, " .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."`, " .
"`".$this->fields["right"]."`, " .
"`".$this->fields["level"]."` " .
"FROM temp_stack " .
"ORDER BY `".$this->fields["id"]."`"
);
if(count($temp_fields) > 1) {
$sql = "" .
"UPDATE `".$this->table."` v, `temp_tree2` SET v.`".$this->fields["id"]."` = v.`".$this->fields["id"]."` ";
foreach($temp_fields as $k => $v) {
if($k == "id") continue;
$sql .= ", v.`".$v."` = `temp_tree2`.`".$v."` ";
}
$sql .= " WHERE v.`".$this->fields["id"]."` = `temp_tree2`.`".$this->fields["id"]."` ";
$this->db->query($sql);
}
}
function _analyze() {
$report = array();
$this->db->query("" .
"SELECT " .
"`".$this->fields["left"]."` FROM `".$this->table."` s " .
"WHERE " .
"`".$this->fields["parent_id"]."` = 0 "
);
$this->db->nextr();
if($this->db->nf() == 0) {
$report[] = "[FAIL]\tNo root node.";
}
else {
$report[] = ($this->db->nf() > 1) ? "[FAIL]\tMore than one root node." : "[OK]\tJust one root node.";
}
$report[] = ($this->db->f(0) != 1) ? "[FAIL]\tRoot node's left index is not 1." : "[OK]\tRoot node's left index is 1.";
$this->db->query("" .
"SELECT " .
"COUNT(*) FROM `".$this->table."` s " .
"WHERE " .
"`".$this->fields["parent_id"]."` != 0 AND " .
"(SELECT COUNT(*) FROM `".$this->table."` WHERE `".$this->fields["id"]."` = s.`".$this->fields["parent_id"]."`) = 0 ");
$this->db->nextr();
$report[] = ($this->db->f(0) > 0) ? "[FAIL]\tMissing parents." : "[OK]\tNo missing parents.";
$this->db->query("SELECT MAX(`".$this->fields["right"]."`) FROM `".$this->table."`");
$this->db->nextr();
$n = $this->db->f(0);
$this->db->query("SELECT COUNT(*) FROM `".$this->table."`");
$this->db->nextr();
$c = $this->db->f(0);
$report[] = ($n/2 != $c) ? "[FAIL]\tRight index does not match node count." : "[OK]\tRight index matches count.";
$this->db->query("" .
"SELECT COUNT(`".$this->fields["id"]."`) FROM `".$this->table."` s " .
"WHERE " .
"(SELECT COUNT(*) FROM `".$this->table."` WHERE " .
"`".$this->fields["right"]."` < s.`".$this->fields["right"]."` AND " .
"`".$this->fields["left"]."` > s.`".$this->fields["left"]."` AND " .
"`".$this->fields["level"]."` = s.`".$this->fields["level"]."` + 1" .
") != " .
"(SELECT COUNT(*) FROM `".$this->table."` WHERE " .
"`".$this->fields["parent_id"]."` = s.`".$this->fields["id"]."`" .
") "
);
$this->db->nextr();
$report[] = ($this->db->f(0) > 0) ? "[FAIL]\tAdjacency and nested set do not match." : "[OK]\tNS and AJ match";
return implode("<br />",$report);
}
function _dump($output = false) {
$nodes = array();
$this->db->query("SELECT * FROM ".$this->table." ORDER BY `".$this->fields["left"]."`");
while($this->db->nextr()) $nodes[] = $this->db->get_row("assoc");
if($output) {
echo "<pre>";
foreach($nodes as $node) {
echo str_repeat("&#160;",(int)$node[$this->fields["level"]] * 2);
echo $node[$this->fields["id"]]." (".$node[$this->fields["left"]].",".$node[$this->fields["right"]].",".$node[$this->fields["level"]].",".$node[$this->fields["parent_id"]].",".$node[$this->fields["position"]].")<br />";
}
echo str_repeat("-",40);
echo "</pre>";
}
return $nodes;
}
function _drop() {
$this->db->query("TRUNCATE TABLE `".$this->table."`");
$this->db->query("" .
"INSERT INTO `".$this->table."` (" .
"`".$this->fields["id"]."`, " .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."`, " .
"`".$this->fields["right"]."`, " .
"`".$this->fields["level"]."` " .
") " .
"VALUES (" .
"1, " .
"0, " .
"0, " .
"1, " .
"2, " .
"0 ".
")");
}
}
class json_tree extends _tree_struct {
function __construct($table = "tree", $fields = array(), $add_fields = array("title" => "title", "type" => "type")) {
parent::__construct($table, $fields);
$this->fields = array_merge($this->fields, $add_fields);
$this->add_fields = $add_fields;
}
function create_node($data) {
$id = parent::_create((int)$data[$this->fields["id"]], (int)$data[$this->fields["position"]]);
if($id) {
$data["id"] = $id;
$this->set_data($data);
return "{ \"status\" : 1, \"id\" : ".(int)$id." }";
}
return "{ \"status\" : 0 }";
}
function set_data($data) {
if(count($this->add_fields) == 0) { return "{ \"status\" : 1 }"; }
$s = "UPDATE `".$this->table."` SET `".$this->fields["id"]."` = `".$this->fields["id"]."` ";
foreach($this->add_fields as $k => $v) {
if(isset($data[$k])) $s .= ", `".$this->fields[$v]."` = \"".$this->db->escape($data[$k])."\" ";
else $s .= ", `".$this->fields[$v]."` = `".$this->fields[$v]."` ";
}
$s .= "WHERE `".$this->fields["id"]."` = ".(int)$data["id"];
$this->db->query($s);
return "{ \"status\" : 1 }";
}
function rename_node($data) { return $this->set_data($data); }
function move_node($data) {
$id = parent::_move((int)$data["id"], (int)$data["ref"], (int)$data["position"], (int)$data["copy"]);
if(!$id) return "{ \"status\" : 0 }";
if((int)$data["copy"] && count($this->add_fields)) {
$ids = array_keys($this->_get_children($id, true));
$data = $this->_get_children((int)$data["id"], true);
$i = 0;
foreach($data as $dk => $dv) {
$s = "UPDATE `".$this->table."` SET `".$this->fields["id"]."` = `".$this->fields["id"]."` ";
foreach($this->add_fields as $k => $v) {
if(isset($dv[$k])) $s .= ", `".$this->fields[$v]."` = \"".$this->db->escape($dv[$k])."\" ";
else $s .= ", `".$this->fields[$v]."` = `".$this->fields[$v]."` ";
}
$s .= "WHERE `".$this->fields["id"]."` = ".$ids[$i];
$this->db->query($s);
$i++;
}
}
return "{ \"status\" : 1, \"id\" : ".$id." }";
}
function remove_node($data) {
$id = parent::_remove((int)$data["id"]);
return "{ \"status\" : 1 }";
}
function get_children($data) {
$tmp = $this->_get_children((int)$data["id"]);
if((int)$data["id"] === 1 && count($tmp) === 0) {
$this->_create_default();
$tmp = $this->_get_children((int)$data["id"]);
}
$result = array();
if((int)$data["id"] === 0) return json_encode($result);
foreach($tmp as $k => $v) {
$result[] = array(
"attr" => array("id" => "node_".$k, "rel" => $v[$this->fields["type"]]),
"data" => $v[$this->fields["title"]],
"state" => ((int)$v[$this->fields["right"]] - (int)$v[$this->fields["left"]] > 1) ? "closed" : ""
);
}
return json_encode($result);
}
function search($data) {
$this->db->query("SELECT `".$this->fields["left"]."`, `".$this->fields["right"]."` FROM `".$this->table."` WHERE `".$this->fields["title"]."` LIKE '%".$this->db->escape($data["search_str"])."%'");
if($this->db->nf() === 0) return "[]";
$q = "SELECT DISTINCT `".$this->fields["id"]."` FROM `".$this->table."` WHERE 0 ";
while($this->db->nextr()) {
$q .= " OR (`".$this->fields["left"]."` < ".(int)$this->db->f(0)." AND `".$this->fields["right"]."` > ".(int)$this->db->f(1).") ";
}
$result = array();
$this->db->query($q);
while($this->db->nextr()) { $result[] = "#node_".$this->db->f(0); }
return json_encode($result);
}
function _create_default() {
$this->_drop();
$this->create_node(array(
"id" => 1,
"position" => 0,
"title" => "C:",
"type" => "drive"
));
$this->create_node(array(
"id" => 1,
"position" => 1,
"title" => "D:",
"type" => "drive"
));
$this->create_node(array(
"id" => 2,
"position" => 0,
"title" => "_demo",
"type" => "folder"
));
$this->create_node(array(
"id" => 2,
"position" => 1,
"title" => "_docs",
"type" => "folder"
));
$this->create_node(array(
"id" => 4,
"position" => 0,
"title" => "index.html",
"type" => "default"
));
$this->create_node(array(
"id" => 5,
"position" => 1,
"title" => "doc.html",
"type" => "default"
));
}
}
?>

View File

@ -0,0 +1,6 @@
1) Create a database and a user with all privileges for this database.
2) Edit the config.php file and update the configuration for the database at the top of the file
3) Import the _dump.sql in your newly created database
4) You are ready to go
*) PLEASE NOTE THAT THE PHP TREE CLASS HAS NOT BEEN THOROUGHLY TESTED

View File

@ -0,0 +1,14 @@
<?php
// Database config & class
$db_config = array(
"servername"=> "localhost",
"username" => "root",
"password" => "",
"database" => ""
);
if(extension_loaded("mysqli")) require_once("_inc/class._database_i.php");
else require_once("_inc/class._database.php");
// Tree class
require_once("_inc/class.tree.php");
?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

View File

@ -0,0 +1,461 @@
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jsTree v.1.0 - Demo</title>
<script type="text/javascript" src="../_lib/jquery.js"></script>
<script type="text/javascript" src="../_lib/jquery.cookie.js"></script>
<script type="text/javascript" src="../_lib/jquery.hotkeys.js"></script>
<script type="text/javascript" src="../jquery.jstree.js"></script>
<link type="text/css" rel="stylesheet" href="../_docs/syntax/!style.css"/>
<link type="text/css" rel="stylesheet" href="../_docs/!style.css"/>
<script type="text/javascript" src="../_docs/syntax/!script.js"></script>
</head>
<body id="demo_body">
<div id="container">
<h1 id="dhead">jsTree v.1.0</h1>
<h1>DEMO</h1>
<h2>Creating a tree, binding events, using the instance</h2>
<div id="description">
<p>Here is how you create an instance, bind an event and then get the instance.</p>
<div id="demo1" class="demo" style="height:100px;">
<ul>
<li id="phtml_1">
<a href="#">Root node 1</a>
<ul>
<li id="phtml_2">
<a href="#">Child node 1</a>
</li>
<li id="phtml_3">
<a href="#">Child node 2</a>
</li>
</ul>
</li>
<li id="phtml_4">
<a href="#">Root node 2</a>
</li>
</ul>
</div>
<script type="text/javascript" class="source below">
$(function () {
// TO CREATE AN INSTANCE
// select the tree container using jQuery
$("#demo1")
// call `.jstree` with the options object
.jstree({
// the `plugins` array allows you to configure the active plugins on this instance
"plugins" : ["themes","html_data","ui","crrm","hotkeys"],
// each plugin you have included can have its own config object
"core" : { "initially_open" : [ "phtml_1" ] }
// it makes sense to configure a plugin only if overriding the defaults
})
// EVENTS
// each instance triggers its own events - to process those listen on the container
// all events are in the `.jstree` namespace
// so listen for `function_name`.`jstree` - you can function names from the docs
.bind("loaded.jstree", function (event, data) {
// you get two params - event & data - check the core docs for a detailed description
});
// INSTANCES
// 1) you can call most functions just by selecting the container and calling `.jstree("func",`
setTimeout(function () { $("#demo1").jstree("set_focus"); }, 500);
// with the methods below you can call even private functions (prefixed with `_`)
// 2) you can get the focused instance using `$.jstree._focused()`.
setTimeout(function () { $.jstree._focused().select_node("#phtml_1"); }, 1000);
// 3) you can use $.jstree._reference - just pass the container, a node inside it, or a selector
setTimeout(function () { $.jstree._reference("#phtml_1").close_node("#phtml_1"); }, 1500);
// 4) when you are working with an event you can use a shortcut
$("#demo1").bind("open_node.jstree", function (e, data) {
// data.inst is the instance which triggered this event
data.inst.select_node("#phtml_2", true);
});
setTimeout(function () { $.jstree._reference("#phtml_1").open_node("#phtml_1"); }, 2500);
});
</script>
</div>
<h2>Doing something when the tree is loaded</h2>
<div id="description">
<p>You can use a few events to do that.</p>
<div id="demo2" class="demo" style="height:100px;">
<ul>
<li id="rhtml_1" class="jstree-open">
<a href="#">Root node 1</a>
<ul>
<li id="rhtml_2">
<a href="#">Child node 1</a>
</li>
<li id="rhtml_3">
<a href="#">Child node 2</a>
</li>
</ul>
</li>
<li id="rhtml_4">
<a href="#">Root node 2</a>
</li>
</ul>
</div>
<script type="text/javascript" class="source below">
// Note method 2) and 3) use `one`, this is because if `refresh` is called those events are triggered
$(function () {
$("#demo2")
.jstree({ "plugins" : ["themes","html_data","ui"] })
// 1) the loaded event fires as soon as data is parsed and inserted
.bind("loaded.jstree", function (event, data) { })
// 2) but if you are using the cookie plugin or the core `initially_open` option:
.one("reopen.jstree", function (event, data) { })
// 3) but if you are using the cookie plugin or the UI `initially_select` option:
.one("reselect.jstree", function (event, data) { });
});
</script>
</div>
<h2>Doing something when a node is clicked</h2>
<div id="description">
<div id="demo3" class="demo" style="height:100px;">
<ul>
<li id="shtml_1" class="jstree-open">
<a href="#">Root node 1</a>
<ul>
<li id="shtml_2">
<a href="#">Child node 1</a>
</li>
<li id="shtml_3">
<a href="#">Child node 2</a>
</li>
</ul>
</li>
<li id="shtml_4">
<a href="#">Root node 2</a>
</li>
</ul>
</div>
<script type="text/javascript" class="source below">
$(function () {
$("#demo3")
.jstree({ "plugins" : ["themes","html_data","ui"] })
// 1) if using the UI plugin bind to select_node
.bind("select_node.jstree", function (event, data) {
// `data.rslt.obj` is the jquery extended node that was clicked
alert(data.rslt.obj.attr("id"));
})
// 2) if not using the UI plugin - the Anchor tags work as expected
// so if the anchor has a HREF attirbute - the page will be changed
// you can actually prevent the default, etc (normal jquery usage)
.delegate("a", "click", function (event, data) { event.preventDefault(); })
});
</script>
</div>
<h2>Using CSS to make nodes wrap</h2>
<div id="description">
<div id="demo4" class="demo" style="height:120px;">
<ul>
<li class="jstree-open">
<a href="#">Root node 1</a>
<ul>
<li>
<a href="#">Child node 1 with a long text which would normally just cause a scrollbar, but with this line of CSS it will actually wrap, this is not really throughly tested but it works</a>
</li>
<li>
<a href="#">Child node 2</a>
</li>
</ul>
</li>
<li>
<a href="#">Root node 2</a>
</li>
</ul>
</div>
<style type="text/css" class="source below">
#demo4 a { white-space:normal !important; height: auto; padding:1px 2px; }
#demo4 li > ins { vertical-align:top; }
#demo4 .jstree-hovered, #demo4 .jstree-clicked { border:0; }
</style>
<script type="text/javascript">
$(function () {
$("#demo4")
.jstree({ "plugins" : ["themes","html_data","ui"] });
});
</script>
</div>
<h2>Using CSS to make the nodes bigger</h2>
<div id="description">
<div id="demo5" class="demo" style="height:120px;">
<ul>
<li class="jstree-open">
<a href="#">Root node 1</a>
<ul>
<li>
<a href="#">Child node 1 with a long text which would normally just cause a scrollbar, but with this line of CSS it will actually wrap, this is not really throughly tested but it works</a>
</li>
<li>
<a href="#">Child node 2</a>
</li>
</ul>
</li>
<li>
<a href="#">Root node 2</a>
</li>
</ul>
</div>
<style type="text/css" class="source below">
#demo5 li { min-height:22px; line-height:22px; }
#demo5 a { line-height:20px; height:20px; font-size:10px; }
#demo5 a ins { height:20px; width:20px; background-position:-56px -17px; }
</style>
<script type="text/javascript">
$(function () {
$("#demo5")
.jstree({ "plugins" : ["themes","html_data","ui"] });
});
</script>
</div>
<h2>PHP &amp; mySQL demo + event order</h2>
<div id="description">
<p>Here is a PHP &amp; mySQL enabled demo. You can use the classes/DB structure included, but those are not thoroughly tested and not officially a part of jstree. In the log window you can also see all function calls as they happen on the instance.</p>
<div id="mmenu" style="height:30px; overflow:auto;">
<input type="button" id="add_folder" value="add folder" style="display:block; float:left;"/>
<input type="button" id="add_default" value="add file" style="display:block; float:left;"/>
<input type="button" id="rename" value="rename" style="display:block; float:left;"/>
<input type="button" id="remove" value="remove" style="display:block; float:left;"/>
<input type="button" id="cut" value="cut" style="display:block; float:left;"/>
<input type="button" id="copy" value="copy" style="display:block; float:left;"/>
<input type="button" id="paste" value="paste" style="display:block; float:left;"/>
<input type="button" id="clear_search" value="clear" style="display:block; float:right;"/>
<input type="button" id="search" value="search" style="display:block; float:right;"/>
<input type="text" id="text" value="" style="display:block; float:right;" />
</div>
<!-- the tree container (notice NOT an UL node) -->
<div id="demo" class="demo" style="height:200px;"></div>
<div style="height:30px; text-align:center;">
<input type="button" style='width:170px; height:24px; margin:5px auto;' value="reconstruct" onclick="$.get('./server.php?reconstruct', function () { $('#demo').jstree('refresh',-1); });" />
<input type="button" style='width:170px; height:24px; margin:5px auto;' id="analyze" value="analyze" onclick="$('#alog').load('./server.php?analyze');" />
<input type="button" style='width:170px; height:24px; margin:5px auto;' value="refresh" onclick="$('#demo').jstree('refresh',-1);" />
</div>
<div id='alog' style="border:1px solid gray; padding:5px; height:100px; margin-top:15px; overflow:auto; font-family:Monospace;"></div>
<!-- JavaScript neccessary for the tree -->
<script type="text/javascript" class="source below">
$(function () {
$("#demo")
.bind("before.jstree", function (e, data) {
$("#alog").append(data.func + "<br />");
})
.jstree({
// List of active plugins
"plugins" : [
"themes","json_data","ui","crrm","cookies","dnd","search","types","hotkeys","contextmenu"
],
// I usually configure the plugin that handles the data first
// This example uses JSON as it is most common
"json_data" : {
// This tree is ajax enabled - as this is most common, and maybe a bit more complex
// All the options are almost the same as jQuery's AJAX (read the docs)
"ajax" : {
// the URL to fetch the data
"url" : "./server.php",
// the `data` function is executed in the instance's scope
// the parameter is the node being loaded
// (may be -1, 0, or undefined when loading the root nodes)
"data" : function (n) {
// the result is fed to the AJAX request `data` option
return {
"operation" : "get_children",
"id" : n.attr ? n.attr("id").replace("node_","") : 1
};
}
}
},
// Configuring the search plugin
"search" : {
// As this has been a common question - async search
// Same as above - the `ajax` config option is actually jQuery's AJAX object
"ajax" : {
"url" : "./server.php",
// You get the search string as a parameter
"data" : function (str) {
return {
"operation" : "search",
"search_str" : str
};
}
}
},
// Using types - most of the time this is an overkill
// read the docs carefully to decide whether you need types
"types" : {
// I set both options to -2, as I do not need depth and children count checking
// Those two checks may slow jstree a lot, so use only when needed
"max_depth" : -2,
"max_children" : -2,
// I want only `drive` nodes to be root nodes
// This will prevent moving or creating any other type as a root node
"valid_children" : [ "drive" ],
"types" : {
// The default type
"default" : {
// I want this type to have no children (so only leaf nodes)
// In my case - those are files
"valid_children" : "none",
// If we specify an icon for the default type it WILL OVERRIDE the theme icons
"icon" : {
"image" : "./file.png"
}
},
// The `folder` type
"folder" : {
// can have files and other folders inside of it, but NOT `drive` nodes
"valid_children" : [ "default", "folder" ],
"icon" : {
"image" : "./folder.png"
}
},
// The `drive` nodes
"drive" : {
// can have files and folders inside, but NOT other `drive` nodes
"valid_children" : [ "default", "folder" ],
"icon" : {
"image" : "./root.png"
},
// those prevent the functions with the same name to be used on `drive` nodes
// internally the `before` event is used
"start_drag" : false,
"move_node" : false,
"delete_node" : false,
"remove" : false
}
}
},
// UI & core - the nodes to initially select and open will be overwritten by the cookie plugin
// the UI plugin - it handles selecting/deselecting/hovering nodes
"ui" : {
// this makes the node with ID node_4 selected onload
"initially_select" : [ "node_4" ]
},
// the core plugin - not many options here
"core" : {
// just open those two nodes up
// as this is an AJAX enabled tree, both will be downloaded from the server
"initially_open" : [ "node_2" , "node_3" ]
}
})
.bind("create.jstree", function (e, data) {
$.post(
"./server.php",
{
"operation" : "create_node",
"id" : data.rslt.parent.attr("id").replace("node_",""),
"position" : data.rslt.position,
"title" : data.rslt.name,
"type" : data.rslt.obj.attr("rel")
},
function (r) {
if(r.status) {
$(data.rslt.obj).attr("id", "node_" + r.id);
}
else {
$.jstree.rollback(data.rlbk);
}
}
);
})
.bind("remove.jstree", function (e, data) {
data.rslt.obj.each(function () {
$.ajax({
async : false,
type: 'POST',
url: "./server.php",
data : {
"operation" : "remove_node",
"id" : this.id.replace("node_","")
},
success : function (r) {
if(!r.status) {
data.inst.refresh();
}
}
});
});
})
.bind("rename.jstree", function (e, data) {
$.post(
"./server.php",
{
"operation" : "rename_node",
"id" : data.rslt.obj.attr("id").replace("node_",""),
"title" : data.rslt.new_name
},
function (r) {
if(!r.status) {
$.jstree.rollback(data.rlbk);
}
}
);
})
.bind("move_node.jstree", function (e, data) {
data.rslt.o.each(function (i) {
$.ajax({
async : false,
type: 'POST',
url: "./server.php",
data : {
"operation" : "move_node",
"id" : $(this).attr("id").replace("node_",""),
"ref" : data.rslt.cr === -1 ? 1 : data.rslt.np.attr("id").replace("node_",""),
"position" : data.rslt.cp + i,
"title" : data.rslt.name,
"copy" : data.rslt.cy ? 1 : 0
},
success : function (r) {
if(!r.status) {
$.jstree.rollback(data.rlbk);
}
else {
$(data.rslt.oc).attr("id", "node_" + r.id);
if(data.rslt.cy && $(data.rslt.oc).children("UL").length) {
data.inst.refresh(data.inst._get_parent(data.rslt.oc));
}
}
$("#analyze").click();
}
});
});
});
});
</script>
<script type="text/javascript" class="source below">
// Code for the menu buttons
$(function () {
$("#mmenu input").click(function () {
switch(this.id) {
case "add_default":
case "add_folder":
$("#demo").jstree("create", null, "last", { "attr" : { "rel" : this.id.toString().replace("add_", "") } });
break;
case "search":
$("#demo").jstree("search", document.getElementById("text").value);
break;
case "text": break;
default:
$("#demo").jstree(this.id);
break;
}
});
});
</script>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

View File

@ -0,0 +1,69 @@
<?php
require_once("config.php");
$jstree = new json_tree();
//$jstree->_create_default();
//die();
if(isset($_GET["reconstruct"])) {
$jstree->_reconstruct();
die();
}
if(isset($_GET["analyze"])) {
echo $jstree->_analyze();
die();
}
if($_REQUEST["operation"] && strpos($_REQUEST["operation"], "_") !== 0 && method_exists($jstree, $_REQUEST["operation"])) {
header("HTTP/1.0 200 OK");
header('Content-type: application/json; charset=utf-8');
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Pragma: no-cache");
echo $jstree->{$_REQUEST["operation"]}($_REQUEST);
die();
}
header("HTTP/1.0 404 Not Found");
?>
<?php
/*
$jstree->_drop();
$jstree->create_node(array("id"=>0,"position"=>0));
$jstree->create_node(array("id"=>1,"position"=>0));
$jstree->create_node(array("id"=>1,"position"=>0));
$jstree->create_node(array("id"=>3,"position"=>0,"name"=>"Pesho"));
$jstree->move(3,2,0,true);
$jstree->_dump(true);
$jstree->_reconstruct();
echo $jstree->_analyze();
die();
$tree = new _tree_struct;
$tree->drop();
$tree->create(0, 0);
$tree->create(0, 0);
$tree->create(1, 0);
$tree->create(0, 3);
$tree->create(2, 3);
$tree->create(2, 0);
$tree->dump(true);
$tree->move(6,4,0);
$tree->move(1,0,0);
$tree->move(3,2,99,true);
$tree->move(7,1,0,true);
$tree->move(1,7,0);
$tree->move(1,0,1,true);
$tree->move(2, 0, 0, true);
$tree->move(13, 12, 2, true);
$tree->dump(true);
$tree->move(15, 16, 2, true);
$tree->dump(true);
$tree->move(4, 0, 0);
$tree->dump(true);
$tree->move(4, 0, 2);
$tree->dump(true);
echo $tree->analyze();
$tree->drop();
*/
?>

View File

@ -0,0 +1,48 @@
html, body { margin:0; padding:0; background:#D9E3CB; }
body, td, th, pre, code, select, option, input, textarea { font-family:"lucida grande",tahoma,verdana,arial,sans-serif; font-size:10pt; }
#dhead { margin:0 0 0 -10px; padding:0; line-height:80px; font-size:18pt; font-family:Georgia; /*text-shadow:1px 1px 2px gray;*/ border-bottom:10px solid #73796B; margin-bottom:0.5em; text-align:center; width:820px; background:black; color:white; -moz-border-radius:5px 5px 0 0; border-radius:5px 5px 0 0; -webkit-border-radius:5px 5px 0 0; text-indent:-2000px; background:black url("logo.png") center center no-repeat; }
h1 { margin:0 0 0 0px; padding:0; font-size:14pt; font-family:Georgia; /*text-shadow:1px 1px 2px gray;*/ margin-bottom:1em; text-align:center; text-transform:uppercase;}
h2 { margin:0.5em 0 0.5em 0; padding:0.5em 0 0.5em 20px; font-size:12pt; font-family:Georgia; color:white; background:silver; text-shadow:1px 1px 2px gray; clear:both; -moz-border-radius:5px; border-radius:5px; -webkit-border-radius:5px; }
h3 { margin:0; padding:0.5em 0 0.5em 0; font-size:11.5pt; font-family:Georgia; color:gray; clear:both; }
p { padding:0em 0 0.5em 0; margin:0; line-height:1.8em; }
p.meta { font-size:9pt; color:gray; margin-top:-5px; }
.arguments .tp, p code { color:green; padding:0 4px; font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; font-weight: normal !important; font-style: normal !important; font-size:13px; }
#description, .panel { margin:0 20px; }
#container { width:800px; margin:10px auto; overflow:hidden; background:white; padding:0 10px 10px 10px; -moz-border-radius:5px; border-radius:5px; -webkit-border-radius:5px; -moz-box-shadow: 0px 0px 10px #000; }
.demo { width:255px; float:left; margin:0; border:1px solid gray; background:white; overflow:auto; }
.code { width:490px; float:right; margin:0 0 10px 0; border:1px solid gray; font-size:12px; }
pre { display:block; }
.code_f { border:1px solid gray; margin-bottom:1em; }
.syntaxhighlighter { margin:0 0 0 0 !important; padding:0 !important; line-height:18px; }
.log { padding:4px; border:1px solid gray; margin-bottom:1em; }
.button { display:block; margin-bottom:0.5em; }
.arguments { margin:0em 1em; padding:0; list-style-type:none; }
.arguments .tp { padding:0 0 0 0; float:left; width:70px; }
.arguments strong { display:block; }
.api h3 { margin-left:-10px; color:black; font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; font-weight: normal !important; font-size:14px; margin-top:2em; border-top:1px solid; width:780px; }
.api .arguments li strong { color:black; font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; font-weight: normal !important; font-size:13px; }
.configuration h3 { margin-left:-10px; color:black; font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; font-weight: normal !important; font-size:14px; margin-top:2em; border-top:1px solid; width:780px; }
.note { background:#ffffee; padding:10px 20px; border:1px solid #333; -moz-border-radius:5px; border-radius:5px; -webkit-border-radius:5px; margin-bottom:15px; text-align:center; font-weight:bold; }
.plugins, .demos { margin:0 auto 20px auto; }
ul.columns { list-style-type:none; width:700px; margin:0px auto 15px auto; padding:0; overflow:hidden; }
ul.columns li { float:left; margin:0; padding:0 0 0 0px; line-height:18px; width:345px; }
ul.demos li, ul.plugins li { width:220px; text-align:left; padding:5px 0; }
ul.demos li a, ul.plugins li a { text-decoration:none; color:#3B5998; }
ul.demos li a:hover, ul.plugins li a:hover { text-decoration:underline; }
ul.plugins li p { text-align:left; font-size:9px; color:#333; margin:0 5px 0 0; }
ul.demos li { width:auto; }
.demo, .demo input, .jstree-dnd-helper, #vakata-contextmenu { font-size:10px; font-family:Verdana; }
#demo_body .demo, #demo_body .code { width:auto; float:none; clear:both; margin:10px auto; }
#demo_body .code { margin-bottom:20px; }
ul.jstree { width:700px; margin:0px auto 15px auto; padding:0; }
ul.jstree li { margin:0; padding:2px 0; }
ul.jstree li a { color:#3B5998; text-decoration:underline; }

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

View File

@ -0,0 +1,2 @@
<li class="jstree-closed"><a href="#">Node 1</a></li>
<li><a href="#">Node 2</a></li>

Some files were not shown because too many files have changed in this diff Show More